Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ brew install instructa/tap/switchloom
### npm

```sh
npm install --global switchloom@0.3.1
npm install --global switchloom@0.3.2
```

Both channels install the branded `switchloom` command and the compatibility
Expand All @@ -42,7 +42,7 @@ the browser. After choosing a provider and team, open the provider onboarding
flow, run the copied apply command from the target repository, then run doctor:

```sh
npx switchloom@0.3.1 apply --recipe 'sw1_...' --repository .
npx switchloom@0.3.2 apply --recipe 'sw1_...' --repository .
npx switchloom doctor codex
```

Expand Down Expand Up @@ -71,7 +71,7 @@ apply when setup depends on a locally installed host CLI.

## Current Status

The v0.3.1 public CLI compiles independently and hard-cuts maintainer-only
The v0.3.2 public CLI compiles independently and hard-cuts maintainer-only
evaluation, catalog, registry, and live-verification operations from the
public command surface.

Expand Down Expand Up @@ -104,7 +104,7 @@ pnpm site:dev
```

The website setup contract is the provider onboarding flow: the copied
`npx switchloom@0.3.1 apply --recipe 'sw1_...' --repository .` command runs the
`npx switchloom@0.3.2 apply --recipe 'sw1_...' --repository .` command runs the
CLI-owned preview and confirmation before writing repository-local artifacts,
and the provider-specific doctor command verifies the resulting host setup.

Expand All @@ -131,11 +131,11 @@ pnpm security:check
## Releases

Releases are created only through the repository-owned script. Prepare and
commit a bracketed changelog section such as `## [0.3.1]`, then run:
commit a bracketed changelog section such as `## [0.3.2]`, then run:

```sh
RELEASE_DRY_RUN=1 scripts/release.sh 0.3.1 "Codex 0.145 native V2 compatibility"
scripts/release.sh 0.3.1 "Codex 0.145 native V2 compatibility"
RELEASE_DRY_RUN=1 scripts/release.sh 0.3.2 "Multi-agent generator and Codex V2 catalog"
scripts/release.sh 0.3.2 "Multi-agent generator and Codex V2 catalog"
```

The script requires a clean, synchronized `main`, runs the complete local
Expand Down
12 changes: 9 additions & 3 deletions website/src/lib/generator.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { describe, expect, it } from "vitest";

import { applyPreset, canRenderParentRecommendation, changeHost, CHILD_ROLE_IDS, choosePreset, createConfig, createPresetSelection, HOST_IDS, hostCatalogFrom, isChildRoleId, isPresetDirty, isPrimaryRecommendationId, lifecycleCommands, markPresetCustom, parentRecommendationEffortCopy, PRESETS, primaryRecommendation, PRIMARY_RECOMMENDATION_ID, recipeApplyCommand, removeChildRole, resetRolesToPreset, ROLE_IDS, selectedChildRoleIds, setEffort, setIntegration, setModel, setRoles, setupConfigToml, setupRecipe, setupSpec, setupSummary, setupTransportFrom } from "./generator";
import packageMetadata from "../../../package.json";

import { applyPreset, canRenderParentRecommendation, changeHost, CHILD_ROLE_IDS, choosePreset, createConfig, createPresetSelection, HOST_IDS, hostCatalogFrom, isChildRoleId, isPresetDirty, isPrimaryRecommendationId, lifecycleCommands, markPresetCustom, parentRecommendationEffortCopy, PRESETS, primaryRecommendation, PRIMARY_RECOMMENDATION_ID, recipeApplyCommand, removeChildRole, resetRolesToPreset, ROLE_IDS, selectedChildRoleIds, setEffort, setIntegration, setModel, setRoles, setupConfigToml, setupRecipe, setupSpec, setupSummary, setupTransportFrom, SWITCHLOOM_VERSION } from "./generator";

const generatedCatalog = {
setupContract: {
Expand Down Expand Up @@ -63,6 +65,10 @@ const generatedCatalog = {
const hostCatalog = hostCatalogFrom(generatedCatalog);

describe("Switchloom generator", () => {
it("derives the pinned CLI version from package metadata", () => {
expect(SWITCHLOOM_VERSION).toBe(packageMetadata.version);
});

it("splits the primary recommendation id from generated child role ids", () => {
expect(PRIMARY_RECOMMENDATION_ID).toBe("orchestrator");
expect(CHILD_ROLE_IDS).toEqual(["implementer", "reviewer", "verifier"]);
Expand Down Expand Up @@ -413,7 +419,7 @@ describe("Switchloom generator", () => {
const recipe = setupRecipe(config, hostCatalog, transport.recipePrefix);
expect(recipe).toMatch(/^sw1_[A-Za-z0-9_-]+$/);
const command = recipeApplyCommand(config, hostCatalog, transport.recipePrefix);
expect(command).toMatch(/^npx switchloom@0\.3\.1 apply --recipe 'sw1_[A-Za-z0-9_-]+' --repository \.$/);
expect(command).toBe(`npx switchloom@${SWITCHLOOM_VERSION} apply --recipe '${recipe}' --repository .`);
const toml = setupConfigToml(config, hostCatalog);
expect(toml).toContain('host = "codex-openai"');
expect(toml).toContain('integration = "standalone"');
Expand All @@ -428,7 +434,7 @@ describe("Switchloom generator", () => {
it("shows the full CLI lifecycle without claiming custom setup verification", () => {
const commands = lifecycleCommands(createConfig("cursor"), hostCatalog);
expect(commands.map((entry) => entry.command)).toEqual([
"npm install -g switchloom@0.3.1",
`npm install -g switchloom@${SWITCHLOOM_VERSION}`,
expect.stringMatching(/^switchloom preview --recipe 'sw1_/),
expect.stringMatching(/^switchloom apply --recipe 'sw1_/),
"switchloom doctor cursor",
Expand Down
4 changes: 3 additions & 1 deletion website/src/lib/generator.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import packageMetadata from "../../../package.json";

export const PRIMARY_RECOMMENDATION_ID = "orchestrator" as const;
export const CHILD_ROLE_IDS = ["implementer", "reviewer", "verifier"] as const;
export const ROLE_IDS = [PRIMARY_RECOMMENDATION_ID, ...CHILD_ROLE_IDS] as const;
export const HOST_IDS = ["codex", "cursor", "claude-code", "opencode", "pi"] as const;
export const PRESET_IDS = ["light", "balanced", "high"] as const;
export const SWITCHLOOM_VERSION = "0.3.1";
export const SWITCHLOOM_VERSION = packageMetadata.version;

export type PrimaryRecommendationId = typeof PRIMARY_RECOMMENDATION_ID;
export type ChildRoleId = (typeof CHILD_ROLE_IDS)[number];
Expand Down
4 changes: 2 additions & 2 deletions website/src/lib/onboarding.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, expect, it } from "vitest";

import { HOST_IDS } from "./generator";
import { HOST_IDS, SWITCHLOOM_VERSION } from "./generator";
import { PROVIDER_ONBOARDING, providerOnboarding } from "./onboarding";

describe("provider onboarding templates", () => {
Expand All @@ -19,7 +19,7 @@ describe("provider onboarding templates", () => {
});

it("injects the exact generated recipe command without mutating provider copy", () => {
const command = "npx switchloom@0.3.1 apply --recipe 'sw1_example' --repository .";
const command = `npx switchloom@${SWITCHLOOM_VERSION} apply --recipe 'sw1_example' --repository .`;
const onboarding = providerOnboarding("codex", command);

expect(onboarding.steps.find((step) => step.id === "install")?.command).toBe(command);
Expand Down
3 changes: 2 additions & 1 deletion website/src/lib/website-cli-parity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
setupRecipe,
setupTransportFrom,
shellQuote,
SWITCHLOOM_VERSION,
} from "./generator";
import type { ChildRoleId, GeneratorConfig } from "./generator";

Expand Down Expand Up @@ -222,7 +223,7 @@ describe("website SetupSpec to CLI parity", () => {
const command = recipeApplyCommand(config, hostCatalog, setupTransport.recipePrefix);
const recipe = command.match(/--recipe '([^']+)'/)?.[1];
expect(recipe).toBeTruthy();
expect(command).toBe(`npx switchloom@0.3.1 apply --recipe ${shellQuote(recipe!)} --repository .`);
expect(command).toBe(`npx switchloom@${SWITCHLOOM_VERSION} apply --recipe ${shellQuote(recipe!)} --repository .`);

const { repository } = await tempRepo("switchloom-website-standalone-");
const preview = report(run(["preview", "--recipe", recipe!, "--repository", repository]));
Expand Down
Loading