From 0f77ea56681269092737dc4b27e2fed142e1b306 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 29 Mar 2026 07:33:27 +0000 Subject: [PATCH 1/2] Replace skip with persisted other option for architecture MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add "other" option to architecture facet with empty recipe, so selecting it applies no conventions but persists the choice - Keep architecture as required: false; update promptSelect to skip adding the generic "Skip" button when a facet already has an "other" option — avoiding a redundant skip+other pair in the UI - Update all integration tests to select "other" instead of "__skip__" for architecture, and adjust assertions to expect architecture: "other" in persisted choices https://claude.ai/code/session_01QEdCvpUop37cdbqgiVzkqr --- .../src/commands/conventions.integration.spec.ts | 14 +++++++------- .../cli/src/commands/install.integration.spec.ts | 6 +++--- .../cli/src/commands/knowledge.integration.spec.ts | 2 +- .../cli/src/commands/setup.integration.spec.ts | 14 +++++++------- packages/cli/src/commands/setup.ts | 2 +- packages/core/src/catalog/facets/architecture.ts | 6 ++++++ 6 files changed, 25 insertions(+), 19 deletions(-) diff --git a/packages/cli/src/commands/conventions.integration.spec.ts b/packages/cli/src/commands/conventions.integration.spec.ts index 4e44325..ab7faa2 100644 --- a/packages/cli/src/commands/conventions.integration.spec.ts +++ b/packages/cli/src/commands/conventions.integration.spec.ts @@ -134,7 +134,7 @@ describe("architecture and practices facets integration", () => { // Facet order: process (select), architecture (select), practices (multiselect) vi.mocked(clack.select) .mockResolvedValueOnce("native-agents-md") // process - .mockResolvedValueOnce("__skip__"); // architecture: skip + .mockResolvedValueOnce("other"); // architecture: other vi.mocked(clack.multiselect) .mockResolvedValueOnce(["conventional-commits", "tdd-london"]) // practices .mockResolvedValueOnce(["claude-code"]); // harnesses @@ -182,7 +182,7 @@ describe("architecture and practices facets integration", () => { // Facet order: process (select), architecture (select), practices (multiselect) vi.mocked(clack.select) .mockResolvedValueOnce("native-agents-md") // process - .mockResolvedValueOnce("__skip__"); // architecture: skip + .mockResolvedValueOnce("other"); // architecture: other vi.mocked(clack.multiselect) .mockResolvedValueOnce(["adr-nygard"]) .mockResolvedValueOnce(["claude-code"]); // harnesses @@ -199,13 +199,13 @@ describe("architecture and practices facets integration", () => { expect(adr).toContain("## Consequences"); }); - it("skips both architecture and practices when none selected", async () => { + it("writes no .ade directory when architecture is other and no practices selected", async () => { const catalog = getDefaultCatalog(); // Facet order: process (select), architecture (select), practices (multiselect) vi.mocked(clack.select) .mockResolvedValueOnce("native-agents-md") // process - .mockResolvedValueOnce("__skip__"); // architecture: skip + .mockResolvedValueOnce("other"); // architecture: other vi.mocked(clack.multiselect) .mockResolvedValueOnce([]) // practices: none .mockResolvedValueOnce(["claude-code"]); // harnesses @@ -215,9 +215,9 @@ describe("architecture and practices facets integration", () => { // No .ade directory should exist await expect(access(join(dir, ".ade"))).rejects.toThrow(); - // config.yaml should not have architecture or practices keys + // config.yaml should have architecture: "other" but no practices key const config = await readUserConfig(dir); - expect(config!.choices).not.toHaveProperty("architecture"); + expect(config!.choices).toHaveProperty("architecture", "other"); expect(config!.choices).not.toHaveProperty("practices"); }); @@ -227,7 +227,7 @@ describe("architecture and practices facets integration", () => { // Facet order: process (select), architecture (select), practices (multiselect) vi.mocked(clack.select) .mockResolvedValueOnce("native-agents-md") // process - .mockResolvedValueOnce("__skip__"); // architecture: skip + .mockResolvedValueOnce("other"); // architecture: other vi.mocked(clack.multiselect) .mockResolvedValueOnce(["tdd-london"]) .mockResolvedValueOnce(["claude-code"]); // harnesses diff --git a/packages/cli/src/commands/install.integration.spec.ts b/packages/cli/src/commands/install.integration.spec.ts index c56d0da..c8c3579 100644 --- a/packages/cli/src/commands/install.integration.spec.ts +++ b/packages/cli/src/commands/install.integration.spec.ts @@ -46,7 +46,7 @@ describe("install integration (real temp dir)", () => { // Step 1: Run setup to create config.yaml + config.lock.yaml vi.mocked(clack.select) .mockResolvedValueOnce("codemcp-workflows") // process - .mockResolvedValueOnce("__skip__"); // architecture + .mockResolvedValueOnce("other"); // architecture vi.mocked(clack.multiselect).mockResolvedValueOnce([]); // practices: none await runSetup(dir, catalog); @@ -73,7 +73,7 @@ describe("install integration (real temp dir)", () => { // Setup first vi.mocked(clack.select) .mockResolvedValueOnce("codemcp-workflows") // process - .mockResolvedValueOnce("__skip__"); // architecture + .mockResolvedValueOnce("other"); // architecture vi.mocked(clack.multiselect).mockResolvedValueOnce([]); // practices: none await runSetup(dir, catalog); @@ -102,7 +102,7 @@ describe("install integration (real temp dir)", () => { // Setup with native-agents-md vi.mocked(clack.select) .mockResolvedValueOnce("native-agents-md") // process - .mockResolvedValueOnce("__skip__"); // architecture + .mockResolvedValueOnce("other"); // architecture vi.mocked(clack.multiselect).mockResolvedValueOnce([]); // practices: none await runSetup(dir, catalog); diff --git a/packages/cli/src/commands/knowledge.integration.spec.ts b/packages/cli/src/commands/knowledge.integration.spec.ts index e36a9aa..1ec7b49 100644 --- a/packages/cli/src/commands/knowledge.integration.spec.ts +++ b/packages/cli/src/commands/knowledge.integration.spec.ts @@ -95,7 +95,7 @@ describe("knowledge integration", () => { vi.mocked(clack.select) .mockResolvedValueOnce("native-agents-md") // process - .mockResolvedValueOnce("__skip__"); // architecture: skip + .mockResolvedValueOnce("other"); // architecture: other vi.mocked(clack.multiselect).mockResolvedValueOnce(["tdd-london"]); // practices: tdd-london has no docsets await runSetup(dir, catalog); diff --git a/packages/cli/src/commands/setup.integration.spec.ts b/packages/cli/src/commands/setup.integration.spec.ts index f381f14..2fb929b 100644 --- a/packages/cli/src/commands/setup.integration.spec.ts +++ b/packages/cli/src/commands/setup.integration.spec.ts @@ -45,7 +45,7 @@ describe("setup integration (real temp dir)", () => { vi.mocked(clack.select) .mockResolvedValueOnce("codemcp-workflows") // process - .mockResolvedValueOnce("__skip__"); // architecture + .mockResolvedValueOnce("other"); // architecture vi.mocked(clack.multiselect).mockResolvedValueOnce([]); // practices: none await runSetup(dir, catalog); @@ -53,7 +53,7 @@ describe("setup integration (real temp dir)", () => { // ── config.yaml ────────────────────────────────────────────────────── const config = await readUserConfig(dir); expect(config).not.toBeNull(); - expect(config!.choices).toEqual({ process: "codemcp-workflows" }); + expect(config!.choices).toEqual({ process: "codemcp-workflows", architecture: "other" }); // harnesses must NOT be in config.yaml — setup no longer selects them expect(config).not.toHaveProperty("harnesses"); @@ -61,7 +61,7 @@ describe("setup integration (real temp dir)", () => { const lock = await readLockFile(dir); expect(lock).not.toBeNull(); expect(lock!.version).toBe(1); - expect(lock!.choices).toEqual({ process: "codemcp-workflows" }); + expect(lock!.choices).toEqual({ process: "codemcp-workflows", architecture: "other" }); expect(lock!.generated_at).toBeTruthy(); // harnesses must NOT be in the lock file expect(lock).not.toHaveProperty("harnesses"); @@ -78,16 +78,16 @@ describe("setup integration (real temp dir)", () => { vi.mocked(clack.select) .mockResolvedValueOnce("native-agents-md") // process - .mockResolvedValueOnce("__skip__"); // architecture + .mockResolvedValueOnce("other"); // architecture vi.mocked(clack.multiselect).mockResolvedValueOnce([]); // practices: none await runSetup(dir, catalog); const config = await readUserConfig(dir); - expect(config!.choices).toEqual({ process: "native-agents-md" }); + expect(config!.choices).toEqual({ process: "native-agents-md", architecture: "other" }); const lock = await readLockFile(dir); - expect(lock!.choices).toEqual({ process: "native-agents-md" }); + expect(lock!.choices).toEqual({ process: "native-agents-md", architecture: "other" }); expect(lock!.logical_config.instructions.length).toBeGreaterThan(0); }); @@ -112,7 +112,7 @@ describe("setup integration (real temp dir)", () => { vi.mocked(clack.select) .mockResolvedValueOnce("codemcp-workflows") // process - .mockResolvedValueOnce("__skip__"); // architecture + .mockResolvedValueOnce("other"); // architecture vi.mocked(clack.multiselect).mockResolvedValueOnce([]); // practices: none await runSetup(dir, catalog); diff --git a/packages/cli/src/commands/setup.ts b/packages/cli/src/commands/setup.ts index 0ab1ffa..ded77cf 100644 --- a/packages/cli/src/commands/setup.ts +++ b/packages/cli/src/commands/setup.ts @@ -194,7 +194,7 @@ function promptSelect( hint: o.description })); - if (!facet.required) { + if (!facet.required && !facet.options.some((o) => o.id === "other")) { options.push({ value: "__skip__", label: "Skip", hint: "" }); } diff --git a/packages/core/src/catalog/facets/architecture.ts b/packages/core/src/catalog/facets/architecture.ts index f1647b6..c0d65bc 100644 --- a/packages/core/src/catalog/facets/architecture.ts +++ b/packages/core/src/catalog/facets/architecture.ts @@ -464,6 +464,12 @@ export const architectureFacet: Facet = { } } ] + }, + { + id: "other", + label: "Other", + description: "Custom or unlisted architecture — no conventions will be applied", + recipe: [] } ] }; From 8050be6708541083bd1ec3ae1bd3546c0132e24c Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 29 Mar 2026 07:55:31 +0000 Subject: [PATCH 2/2] Apply prettier formatting https://claude.ai/code/session_01QEdCvpUop37cdbqgiVzkqr --- .../src/commands/setup.integration.spec.ts | 20 +++++++++++++++---- .../core/src/catalog/facets/architecture.ts | 3 ++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/packages/cli/src/commands/setup.integration.spec.ts b/packages/cli/src/commands/setup.integration.spec.ts index 2fb929b..0c9011c 100644 --- a/packages/cli/src/commands/setup.integration.spec.ts +++ b/packages/cli/src/commands/setup.integration.spec.ts @@ -53,7 +53,10 @@ describe("setup integration (real temp dir)", () => { // ── config.yaml ────────────────────────────────────────────────────── const config = await readUserConfig(dir); expect(config).not.toBeNull(); - expect(config!.choices).toEqual({ process: "codemcp-workflows", architecture: "other" }); + expect(config!.choices).toEqual({ + process: "codemcp-workflows", + architecture: "other" + }); // harnesses must NOT be in config.yaml — setup no longer selects them expect(config).not.toHaveProperty("harnesses"); @@ -61,7 +64,10 @@ describe("setup integration (real temp dir)", () => { const lock = await readLockFile(dir); expect(lock).not.toBeNull(); expect(lock!.version).toBe(1); - expect(lock!.choices).toEqual({ process: "codemcp-workflows", architecture: "other" }); + expect(lock!.choices).toEqual({ + process: "codemcp-workflows", + architecture: "other" + }); expect(lock!.generated_at).toBeTruthy(); // harnesses must NOT be in the lock file expect(lock).not.toHaveProperty("harnesses"); @@ -84,10 +90,16 @@ describe("setup integration (real temp dir)", () => { await runSetup(dir, catalog); const config = await readUserConfig(dir); - expect(config!.choices).toEqual({ process: "native-agents-md", architecture: "other" }); + expect(config!.choices).toEqual({ + process: "native-agents-md", + architecture: "other" + }); const lock = await readLockFile(dir); - expect(lock!.choices).toEqual({ process: "native-agents-md", architecture: "other" }); + expect(lock!.choices).toEqual({ + process: "native-agents-md", + architecture: "other" + }); expect(lock!.logical_config.instructions.length).toBeGreaterThan(0); }); diff --git a/packages/core/src/catalog/facets/architecture.ts b/packages/core/src/catalog/facets/architecture.ts index c0d65bc..2b5149f 100644 --- a/packages/core/src/catalog/facets/architecture.ts +++ b/packages/core/src/catalog/facets/architecture.ts @@ -468,7 +468,8 @@ export const architectureFacet: Facet = { { id: "other", label: "Other", - description: "Custom or unlisted architecture — no conventions will be applied", + description: + "Custom or unlisted architecture — no conventions will be applied", recipe: [] } ]