@multileaf/ai-workflow 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,16 @@ All notable changes to this project are documented in this file. The format foll
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.1.5] - 2026-09-12
8
+
9
+ ### Fixed
10
+
11
+ - Connect SDD capability recommendations through explicit prerequisites so custom selections include required earlier workflow stages.
12
+ - Recommend verification for supported project profiles and test runners, including test commands discovered in monorepo workspaces.
13
+ - Align brainstorming, specification, planning, and verification gates with their matching artifacts; remove references to a nonexistent review gate command.
14
+ - Clarify skill handoffs across brainstorming, requirements, design, planning, implementation, verification, and code review.
15
+ - Correct the project profile path referenced by the project initialization skill.
16
+
7
17
  ## [0.1.4] - 2026-09-12
8
18
 
9
19
  ### Added
@@ -66,7 +76,8 @@ All notable changes to this project are documented in this file. The format foll
66
76
 
67
77
  - Path confinement, symlink protection, explicit permission gates, secret redaction, strict parsers, atomic migrations, and immutable execution checkpoints.
68
78
 
69
- [Unreleased]: https://github.com/MultiLeaf/aiw/compare/v0.1.4...HEAD
79
+ [Unreleased]: https://github.com/MultiLeaf/aiw/compare/v0.1.5...HEAD
80
+ [0.1.5]: https://github.com/MultiLeaf/aiw/compare/v0.1.4...v0.1.5
70
81
  [0.1.4]: https://github.com/MultiLeaf/aiw/compare/v0.1.3...v0.1.4
71
82
  [0.1.3]: https://github.com/MultiLeaf/aiw/compare/v0.1.2...v0.1.3
72
83
  [0.1.2]: https://github.com/MultiLeaf/aiw/compare/v0.1.1...v0.1.2
package/README.md CHANGED
@@ -122,49 +122,52 @@ flowchart TD
122
122
  D --> E[(.aiw/recommendations.yml)]
123
123
  E --> F{User confirms scope}
124
124
  F -->|Revise| B
125
- F -->|Proceed| G[Brainstorm]
126
-
127
- G --> H[(generated/specs/brainstorm.md)]
128
- H --> I{Brainstorm gate}
129
- I -->|Incomplete| G
130
- I -->|Complete| J[Write specification]
131
-
132
- J --> K[(generated/specs/specification.md)]
133
- K --> L{Specification gate}
134
- L -->|Incomplete| J
135
- L -->|Complete| M{Architecture decision needed?}
136
-
137
- M -->|Yes| N[Create ADR]
138
- N --> O[(.context/adrs/ADR-NNN-title.md)]
139
- O --> P[Update ADR index]
140
- P --> Q[(.context/adrs/INDEX.md)]
141
- M -->|No| R[Create implementation plan]
142
- Q --> R
143
-
144
- R --> S[(generated/plans/implementation-plan.md)]
145
- S --> T{Plan gate}
146
- T -->|Incomplete| R
147
- T -->|Ready| U[Implement tasks with TDD]
148
-
149
- U --> V[Write code and tests]
150
- V --> W[Run task validation commands]
151
- W --> X{Validation passes?}
152
- X -->|No| U
153
- X -->|Yes| Y[Record completion evidence]
154
-
155
- Y --> Z[(generated/artifacts and checkpoint evidence)]
156
- Z --> AA[Verify declared evidence]
157
- AA --> AB{Verification gate}
158
- AB -->|Missing evidence| U
159
- AB -->|Complete| AC[Build traceability graph]
160
-
161
- AC --> AD[Requirement → ADR → Task → Code → Test → Evidence]
162
- AD --> AE[(generated artifacts and trace output)]
163
- AE --> AF[Run repository self-validation]
164
- AF --> AG[(.aiw/checkpoints/self-validation-TICKET.yml)]
165
- AG --> AH{Review outcome}
166
- AH -->|Changes required| U
167
- AH -->|Accepted| AI[Commit and independent integration validation]
125
+ F -->|Proceed| G{Clarification needed?}
126
+
127
+ G -->|Yes| H[Brainstorm]
128
+ H --> I[(generated/specs/brainstorm.md)]
129
+ I --> J{Brainstorm gate}
130
+ J -->|Incomplete| H
131
+ J -->|Complete| K[Write specification]
132
+ G -->|No| K
133
+
134
+ K --> L[(generated/specs/specification.md)]
135
+ L --> M{Specification gate}
136
+ M -->|Incomplete| K
137
+ M -->|Complete| N{Architecture decision needed?}
138
+
139
+ N -->|Yes| O[Create ADR]
140
+ O --> P[(.context/adrs/ADR-NNN-title.md)]
141
+ P --> Q[Update ADR index]
142
+ Q --> R[(.context/adrs/INDEX.md)]
143
+ N -->|No| S[Create implementation plan]
144
+ R --> S
145
+
146
+ S --> T[(generated/plans/implementation-plan.md)]
147
+ T --> U{Plan gate}
148
+ U -->|Incomplete| S
149
+ U -->|Ready| V[Implement tasks with TDD]
150
+
151
+ V --> W[Write code and tests]
152
+ W --> X[Run task validation commands]
153
+ X --> Y{Validation passes?}
154
+ Y -->|No| V
155
+ Y -->|Yes| Z[Record completion evidence]
156
+
157
+ Z --> AA[(generated/artifacts and checkpoint evidence)]
158
+ AA --> AB[Write verification report]
159
+ AB --> AC{Verification gate}
160
+ AC -->|Missing evidence| V
161
+ AC -->|Complete| AD[Build traceability graph]
162
+
163
+ AD --> AE[Requirement → ADR → Task → Code → Test → Evidence]
164
+ AE --> AF[(generated artifacts and trace output)]
165
+ AF --> AG[Run code-review skill when installed]
166
+ AG --> AH{Review findings?}
167
+ AH -->|Changes required| V
168
+ AH -->|Clear| AI[Run repository self-validation]
169
+ AI --> AJ[(.aiw/checkpoints/self-validation-TICKET.yml)]
170
+ AJ --> AK[Commit and independent integration validation]
168
171
 
169
172
  B -. command history and evidence .-> LOGS[(.aiw/checkpoints/)]
170
173
  D -. command history and evidence .-> LOGS
@@ -180,7 +183,7 @@ npx @multileaf/ai-workflow scan
180
183
  npx @multileaf/ai-workflow recommend
181
184
 
182
185
  # In CI, provide comma-separated recommendation IDs detected for that project.
183
- npx @multileaf/ai-workflow recommend --select=typescript-quality,vitest-testing
186
+ npx @multileaf/ai-workflow recommend --select=typescript-quality,verification
184
187
 
185
188
  # Create structured product artifacts.
186
189
  npx @multileaf/ai-workflow brainstorm --title="Feature name"
@@ -188,13 +191,18 @@ npx @multileaf/ai-workflow spec --title="Feature requirements"
188
191
  npx @multileaf/ai-workflow adr --id=001 --title="Technical decision"
189
192
  npx @multileaf/ai-workflow plan --title="Implementation plan"
190
193
 
191
- # Fill the generated scaffold sections before running their quality gates.
194
+ # Optional, after creating a brainstorm artifact for an unclear request:
195
+ npx @multileaf/ai-workflow gate brainstorming
196
+ # After filling the specification and plan scaffolds shown above:
192
197
  npx @multileaf/ai-workflow gate specification
198
+ npx @multileaf/ai-workflow gate plan
199
+ # After writing .aiw/generated/reports/verification-report.md from the verification report template:
200
+ npx @multileaf/ai-workflow gate verification
193
201
  npx @multileaf/ai-workflow verify
194
202
  npx @multileaf/ai-workflow trace
195
203
  ```
196
204
 
197
- Scaffold commands write deterministic files at fixed paths and a repeated invocation replaces that scaffold. Complete and review each artifact before advancing. Requirements use stable identifiers and Given/When/Then acceptance criteria. Plans link tasks to requirements, tests, risks, dependencies, and expected evidence. `gate` performs textual completeness checks, `verify` validates the expected verification fields rather than running a test command, and `trace` records declared links between requirements, decisions, tasks, code, tests, and evidence.
205
+ Scaffold commands write deterministic files at fixed paths and a repeated invocation replaces that scaffold. Complete and review each artifact before advancing. Requirements use stable identifiers and Given/When/Then acceptance criteria. Plans link tasks to requirements, tests, risks, dependencies, and expected evidence. Each `gate` validates the artifact named by its stage. `verify` checks that the specification has acceptance criteria and the plan links requirements to validation; it does not execute project test commands. `trace` records declared links between requirements, decisions, tasks, code, tests, and evidence. Code review is performed with the `code-review` skill when installed; there is no separate review gate command.
198
206
 
199
207
  ## Project intelligence
200
208
 
package/dist/adapter.js CHANGED
@@ -44,8 +44,8 @@ This skill is the bootstrap for AI Workflow. The installer intentionally install
44
44
  2. Use the host's native subagent mechanism to launch these read-only analyses in parallel: (a) technologies, root and nested manifests, workspaces, and monorepo boundaries; (b) architecture, modules, entry points, and recurring code patterns; (c) tests, quality commands, CI, and developer tools. Keep the main agent as orchestrator. Wait for all results, verify important claims against cited project files, reconcile disagreements, and consolidate one evidence-backed project profile. Do not inspect secrets, ignored files, dependency directories such as \`node_modules\`, or generated output; inspect declared dependencies in project manifests. If subagents are unavailable, perform the same analyses directly and disclose the fallback.
45
45
  3. Run \`npx --yes --package=@multileaf/ai-workflow -- aiw scan\` and read \`.aiw/profile.yml\`. Treat this deterministic scan as another evidence source, not as a replacement for workspace-level analysis. Summarize each workspace separately; do not assume root dependencies or commands apply to every module. Ask the user to confirm uncertain or conflicting facts before using them as project policy. Add confirmed architecture and recurring patterns to the matching entries in the \`project_modules\` JSON array in \`.aiw/profile.yml\`, including file-path evidence; create a root-level entry when only the root project exists. Preserve existing detected fields and never store secrets or source-code excerpts there.
46
46
  4. Run \`npx --yes --package=@multileaf/ai-workflow -- aiw recommend\` and read \`.aiw/recommendations.yml\`. Combine catalog results with the consolidated project profile. Recommend matching skills, rules, agents, hooks, templates, and MCP servers. For every MCP, disclose its publisher/source, purpose, capabilities, permissions, transport, and credential needs; verify them against current official host and server documentation. Recommend only integrations supported by project evidence and never invent credentials.
47
- 5. Use the host's native selection widget. First offer three choices: install all recommendations, customize, or install none. If the user chooses customization, show the install plan in separate selectable blocks for skills, rules, agents, hooks, templates, and MCPs, with each item, its rationale, project-specific changes, and dependencies visible. If the host lacks a multi-select widget, use a numbered all/custom/none prompt and grouped checklists. MCP selection does not grant permission to execute the server or use external access; ask separately for those permissions.
48
- 6. Record all recommendations with \`npx --yes --package=@multileaf/ai-workflow -- aiw recommend --select=all\`; for customized item-level choices, pass the selected resource references such as \`skills/verification,rules/tdd-policy,agents/test-engineer\`. Use \`npx --yes --package=@multileaf/ai-workflow -- aiw recommend --select=\` when none are chosen. If any AI Workflow resources are selected, run \`npx --yes --package=@multileaf/ai-workflow -- aiw sync\`, adding \`--allow=network:external\` only after separate approval. Install only selected resources and declared dependencies. Tailor instructions only where project evidence changes their usefulness (such as test commands, workspace boundaries, framework patterns, or module architecture). Preserve existing files, configuration, and secrets; report conflicts rather than overwriting them.
47
+ 5. Present recommendations as concise tables grouped by category: skills, rules, agents, hooks, templates, and MCPs. Include one row per recommended item and columns for the item, a short project-specific reason for the recommendation, and relevant evidence. For MCP rows, also summarize purpose, source, permissions, transport, and credential needs (use a separate table if needed). Do not show a flat list without category headings or generic reasons such as “useful for this project.” After the tables, use the host's native selection widget to offer three choices: install all recommendations, customize, or install none. If the user customizes, show selectable category blocks and individual items, keeping each item's short reason and declared prerequisites visible. Read \`requires\` from \`.aiw/recommendations.yml\`; explain that choosing a stage auto-selects its prerequisite capabilities and their resources. If the host lacks a multi-select widget, use a numbered all/custom/none prompt and grouped checklists. MCP selection does not grant permission to execute the server or use external access; ask separately for those permissions.
48
+ 6. Record all recommendations with \`npx --yes --package=@multileaf/ai-workflow -- aiw recommend --select=all\`; for customized item-level choices, pass the selected resource references such as \`skills/verification,rules/tdd-policy,agents/test-engineer\`. Use \`npx --yes --package=@multileaf/ai-workflow -- aiw recommend --select=\` when none are chosen. If any AI Workflow resources are selected, run \`npx --yes --package=@multileaf/ai-workflow -- aiw sync\` without extra permissions first. It installs selected bundled resources and reports any external resource that is still pending approval. Only if the user separately approves external access, rerun with \`--allow=network:external\` to install that pending external resource. Install only selected resources and declared dependencies. Tailor instructions only where project evidence changes their usefulness (such as test commands, workspace boundaries, framework patterns, or module architecture). Preserve existing files, configuration, and secrets; report conflicts rather than overwriting them.
49
49
  7. For selected MCPs, add only the selected servers to the host's supported project configuration. Check current official host and server documentation for the configuration format, merge existing settings without replacing unrelated entries, and use environment-variable references instead of literal credentials. Do not run server install/start/authentication commands without separate approval. If the target requires user-level changes or safe configuration cannot be validated, give the user exact manual steps and report the MCP as pending rather than installed.
50
50
  8. Report installed resources by block, project-specific changes, skipped recommendations, MCP trust/authentication steps, and conflicts. Recommend restarting or reloading the coding-agent session so it discovers newly installed resources; follow known host behavior if it reloads changes automatically. Introduce only the gates supported by installed resources: brainstorming → specification → architecture decision when needed → implementation plan → implementation with tests → verification → traceability → review.
51
51
 
@@ -53,11 +53,11 @@ If the user declines all recommendations, leave the project with only the bootst
53
53
 
54
54
  ## For each feature request after setup
55
55
 
56
- - Start with the brainstorming skill when scope, users, constraints, or assumptions are unclear.
57
- - Create and complete a specification with stable requirement IDs and Given/When/Then acceptance criteria; pass \`npx --yes --package=@multileaf/ai-workflow -- aiw gate specification\` before planning.
58
- - Record consequential architecture choices as ADRs. Create an implementation plan that links tasks to requirements, tests, risks, and validation commands; pass \`npx --yes --package=@multileaf/ai-workflow -- aiw gate plan\` before coding.
59
- - Follow the TDD policy and project quality rules. Use specialist agents for requirements, architecture, implementation, tests, security, documentation, and review when useful.
60
- - Run the declared checks, then \`npx --yes --package=@multileaf/ai-workflow -- aiw verify\`, \`npx --yes --package=@multileaf/ai-workflow -- aiw trace\`, and the review gate. Do not claim completion without evidence.
56
+ - Use the brainstorming skill when scope, users, constraints, or assumptions are unclear; create its artifact with \`npx --yes --package=@multileaf/ai-workflow -- aiw brainstorm\`, then validate it with \`npx --yes --package=@multileaf/ai-workflow -- aiw gate brainstorming\`.
57
+ - Create a specification with stable requirement IDs and Given/When/Then acceptance criteria; pass \`npx --yes --package=@multileaf/ai-workflow -- aiw gate specification\` before planning.
58
+ - For changes with architecture impact, use technical design, record consequential choices as ADRs with \`npx --yes --package=@multileaf/ai-workflow -- aiw adr\`, and link those decisions to the requirements. Then create an implementation plan with \`npx --yes --package=@multileaf/ai-workflow -- aiw plan\`, linking tasks to requirements, tests, risks, and validation commands; pass \`npx --yes --package=@multileaf/ai-workflow -- aiw gate plan\` before coding.
59
+ - When TDD resources are installed and the project has a test workflow, follow the TDD policy; otherwise use the project's existing validation methods. Follow installed project quality rules and use specialist agents only when they are installed and useful.
60
+ - Run the declared checks, write \`.aiw/generated/reports/verification-report.md\` using the verification-report template, and pass \`npx --yes --package=@multileaf/ai-workflow -- aiw gate verification\`. Then run \`npx --yes --package=@multileaf/ai-workflow -- aiw verify\` and \`npx --yes --package=@multileaf/ai-workflow -- aiw trace\`. Use the code-review skill when installed and record its findings; AI Workflow does not provide a separate review gate. Do not claim completion without evidence.
61
61
 
62
62
  ## Language policy
63
63
 
package/dist/generator.js CHANGED
@@ -2,18 +2,28 @@ import { resolveGeneratedPath } from "./drift.js";
2
2
  export function generateProjectResources(profile, selected, write) {
3
3
  const linterCommand = safeInlineValue(profile.quality.linter?.command);
4
4
  const formatterCommand = safeInlineValue(profile.quality.formatter?.command);
5
- const testCommand = safeInlineValue(profile.testing?.command);
5
+ const testCommands = [
6
+ ...(profile.testing?.command ? [{ scope: "project", command: profile.testing.command }] : []),
7
+ ...(profile.modules ?? []).flatMap((module) => module.testing?.command
8
+ ? [{ scope: `workspace ${module.path}`, command: module.testing.command }]
9
+ : []),
10
+ ].map(({ scope, command }) => ({ scope, command: safeInlineValue(command) }));
11
+ const uniqueTestCommands = [
12
+ ...new Map(testCommands
13
+ .filter(({ command }) => command)
14
+ .map(({ scope, command }) => [`${scope}:${command}`, { scope, command }])).values(),
15
+ ];
6
16
  if (selected.includes("typescript-quality") || selected.includes("rules/project-quality"))
7
17
  write(resolveGeneratedPath("rules/project-quality.md"), `# Project Quality Rules\n\n- Use ${profile.runtime.languages.map((language) => (language === "typescript" ? "TypeScript" : language)).join(", ")} with strict typing.\n${linterCommand ? `- Run \`${linterCommand}\` before completion.\n` : ""}${formatterCommand ? `- Run \`${formatterCommand}\` before review.\n` : ""}- Keep all generated AI Workflow artifacts in English.\n`);
8
18
  if (selected.includes("tdd-development") || selected.includes("rules/tdd-project-policy"))
9
- write(resolveGeneratedPath("rules/tdd-project-policy.md"), `# TDD Project Policy\n\n${testCommand ? `- Run \`${testCommand}\` for verification.\n` : ""}- Write a failing behavioral test before implementation.\n- Refactor only after the test is green.\n`);
19
+ write(resolveGeneratedPath("rules/tdd-project-policy.md"), `# TDD Project Policy\n\n${uniqueTestCommands.map(({ scope, command }) => `- Run the ${scope} test command \`${command}\` for verification.`).join("\n")}${uniqueTestCommands.length ? "\n" : ""}- Write a failing behavioral test before implementation.\n- Refactor only after the test is green.\n`);
10
20
  if (selected.includes("nextjs-development") ||
11
21
  selected.includes("react-best-practices") ||
12
22
  selected.includes("rules/architecture-policy"))
13
23
  write(resolveGeneratedPath("agents/project-context.md"), `# Project Context\n\nThis project uses ${profile.frameworks.map((framework) => (framework === "nextjs" ? "Next.js" : framework)).join(", ")}. Follow the detected project structure and existing framework conventions.\n`);
14
24
  if (selected.length > 0) {
15
25
  write(resolveGeneratedPath("context/project-profile.md"), `# Confirmed Project Profile\n\n- Languages: ${profile.runtime.languages.join(", ") || "none detected"}\n- Frameworks: ${profile.frameworks.join(", ") || "none detected"}\n- Package manager: ${profile.packageManager}\n- All generated content is in English.\n`);
16
- write(resolveGeneratedPath("hooks/quality-check.md"), `# Quality Check Hook\n\nRun the available project quality commands before completion.${linterCommand ? `\n\n- Linter: \`${linterCommand}\`` : ""}${formatterCommand ? `\n- Formatter: \`${formatterCommand}\`` : ""}${testCommand ? `\n- Tests: \`${testCommand}\`` : ""}\n`);
26
+ write(resolveGeneratedPath("hooks/quality-check.md"), `# Quality Check Hook\n\nRun the available project quality commands before completion.${linterCommand ? `\n\n- Linter: \`${linterCommand}\`` : ""}${formatterCommand ? `\n- Formatter: \`${formatterCommand}\`` : ""}${uniqueTestCommands.map(({ scope, command }) => `\n- ${scope} tests: \`${command}\``).join("")}\n`);
17
27
  }
18
28
  }
19
29
  function safeInlineValue(value) {
@@ -1,2 +1,2 @@
1
- export type QualityGateStage = "specification" | "plan" | "verification";
1
+ export type QualityGateStage = "brainstorming" | "specification" | "plan" | "verification";
2
2
  export declare function evaluateQualityGate(stage: QualityGateStage, content: string): string[];
@@ -11,7 +11,7 @@ function requireSections(content, artifact, headings) {
11
11
  });
12
12
  }
13
13
  export function evaluateQualityGate(stage, content) {
14
- if (stage === "specification")
14
+ if (stage === "brainstorming")
15
15
  return requireSections(content, "Brainstorm", [
16
16
  "Goal",
17
17
  "Users",
@@ -19,7 +19,7 @@ export function evaluateQualityGate(stage, content) {
19
19
  "Risks",
20
20
  "Non-goals",
21
21
  ]);
22
- if (stage === "plan") {
22
+ if (stage === "specification") {
23
23
  const issues = [];
24
24
  if (!/REQ-\d+/.test(content))
25
25
  issues.push("Specification must define a stable REQ-### ID.");
@@ -29,12 +29,21 @@ export function evaluateQualityGate(stage, content) {
29
29
  issues.push("Requirement acceptance criteria must use Given, When, and Then.");
30
30
  return issues;
31
31
  }
32
- const fields = ["Requirement", "Code", "Tests", "Validation", "Evidence"];
33
- const issues = !/TASK-\d+/.test(content)
34
- ? ["Implementation plan must define a TASK-### ID."]
35
- : [];
36
- for (const field of fields)
37
- if (!new RegExp(`^[ \\t]*-?[ \\t]*${field}:[ \\t]*\\S+`, "im").test(content))
38
- issues.push(`Implementation plan task must define ${field}.`);
39
- return issues;
32
+ if (stage === "plan") {
33
+ const fields = ["Requirement", "Code", "Tests", "Validation", "Evidence"];
34
+ const issues = !/TASK-\d+/.test(content)
35
+ ? ["Implementation plan must define a TASK-### ID."]
36
+ : [];
37
+ for (const field of fields)
38
+ if (!new RegExp(`^[ \\t]*-?[ \\t]*${field}:[ \\t]*\\S+`, "im").test(content))
39
+ issues.push(`Implementation plan task must define ${field}.`);
40
+ return issues;
41
+ }
42
+ return requireSections(content, "Verification Report", [
43
+ "Requirements Checked",
44
+ "Checks Passed",
45
+ "Missing Evidence",
46
+ "Residual Risks",
47
+ "Decision",
48
+ ]);
40
49
  }
@@ -13,6 +13,7 @@ export type CapabilityRecommendation = {
13
13
  permissions: string[];
14
14
  conflicts: string[];
15
15
  resources: RecommendedResource[];
16
+ requires?: string[];
16
17
  };
17
18
  export declare function recommendCapabilities(profile: ProjectProfile): CapabilityRecommendation[];
18
19
  export declare function resourcesForCapabilities(ids: string[]): RecommendedResource[];
@@ -38,10 +38,26 @@ const CATALOG = [
38
38
  { type: "agents", id: "technical-architect" },
39
39
  { type: "templates", id: "implementation-plan" },
40
40
  ]),
41
+ requires: ["requirements-specification"],
41
42
  matches: (profile) => hasProjectSignals(profile)
42
43
  ? { evidence: projectEvidence(profile), confidence: 0.88 }
43
44
  : undefined,
44
45
  },
46
+ {
47
+ id: "technical-design",
48
+ provider: "multileaf",
49
+ rationale: "Architecture changes benefit from explicit alternatives, trade-offs, and decision records.",
50
+ permissions: [],
51
+ resources: local([
52
+ { type: "skills", id: "technical-design" },
53
+ { type: "agents", id: "technical-architect" },
54
+ { type: "templates", id: "technical-design" },
55
+ { type: "templates", id: "decision-record" },
56
+ ]),
57
+ matches: (profile) => hasProjectSignals(profile)
58
+ ? { evidence: projectEvidence(profile), confidence: 0.82 }
59
+ : undefined,
60
+ },
45
61
  {
46
62
  id: "code-review",
47
63
  provider: "multileaf",
@@ -51,6 +67,7 @@ const CATALOG = [
51
67
  { type: "skills", id: "code-review" },
52
68
  { type: "agents", id: "quality-reviewer" },
53
69
  ]),
70
+ requires: ["verification"],
54
71
  matches: (profile) => profile.runtime.languages.length
55
72
  ? { evidence: projectEvidence(profile), confidence: 0.86 }
56
73
  : undefined,
@@ -68,9 +85,25 @@ const CATALOG = [
68
85
  { type: "hooks", id: "post-implementation" },
69
86
  { type: "templates", id: "test-plan" },
70
87
  ]),
71
- matches: (profile) => profile.testing
72
- ? { evidence: [`testing:${profile.testing.name}`], confidence: 1 }
73
- : undefined,
88
+ requires: ["verification"],
89
+ matches: (profile) => {
90
+ const runners = [
91
+ ...(profile.testing ? [profile.testing] : []),
92
+ ...(profile.modules ?? []).flatMap((module) => module.testing ? [{ ...module.testing, module: module.path }] : []),
93
+ ];
94
+ return runners.length
95
+ ? {
96
+ evidence: [
97
+ ...new Set(runners.flatMap((runner) => [
98
+ ...("module" in runner ? [`workspace:${runner.module}`] : []),
99
+ `testing:${runner.name}`,
100
+ ...(runner.command ? [`test-command:${runner.command}`] : []),
101
+ ])),
102
+ ],
103
+ confidence: 1,
104
+ }
105
+ : undefined;
106
+ },
74
107
  },
75
108
  {
76
109
  id: "typescript-quality",
@@ -116,18 +149,19 @@ const CATALOG = [
116
149
  : undefined,
117
150
  },
118
151
  {
119
- id: "vitest-testing",
152
+ id: "verification",
120
153
  provider: "multileaf",
121
- rationale: "Vitest is configured and can be used by the verification skill and test specialist.",
154
+ rationale: "Verification guidance can use the project's detected test runner and quality commands.",
122
155
  permissions: [],
123
156
  resources: local([
124
157
  { type: "skills", id: "verification" },
125
- { type: "agents", id: "test-engineer" },
158
+ { type: "agents", id: "quality-reviewer" },
126
159
  { type: "templates", id: "test-plan" },
127
160
  { type: "templates", id: "verification-report" },
128
161
  ]),
129
- matches: (profile) => profile.testing?.name === "vitest"
130
- ? { evidence: ["testing:vitest"], confidence: 1 }
162
+ requires: ["implementation-planning"],
163
+ matches: (profile) => hasProjectSignals(profile)
164
+ ? { evidence: projectEvidence(profile), confidence: profile.testing ? 1 : 0.84 }
131
165
  : undefined,
132
166
  },
133
167
  {
@@ -208,8 +242,9 @@ export function recommendCapabilities(profile) {
208
242
  });
209
243
  }
210
244
  export function resourcesForCapabilities(ids) {
211
- const selectedCapabilities = new Set(CATALOG.filter(({ id }) => ids.includes(id)).map(({ id }) => id));
212
- const selectedResources = new Set(ids.filter((id) => id.includes("/")));
245
+ const normalizedIds = ids.map((id) => (id === "vitest-testing" ? "verification" : id));
246
+ const selectedCapabilities = new Set(CATALOG.filter(({ id }) => normalizedIds.includes(id)).map(({ id }) => id));
247
+ const selectedResources = new Set(normalizedIds.filter((id) => id.includes("/")));
213
248
  const resources = CATALOG.flatMap(({ id, resources }) => selectedCapabilities.has(id)
214
249
  ? resources
215
250
  : resources.filter(({ type, id: resourceId }) => selectedResources.has(`${type}/${resourceId}`)));
@@ -219,7 +254,7 @@ export function resourcesForCapabilities(ids) {
219
254
  }
220
255
  export function serializeRecommendations(items, selected = []) {
221
256
  return `schema: 1\nrecommendations:\n${items
222
- .map((item) => ` - id: ${item.id}\n provider: ${item.provider}\n confidence: ${item.confidence}\n selected: ${selected.includes(item.id)}\n resources: [${item.resources.map(({ type, id }) => `${type}/${id}`).join(", ")}]\n selected_resources: [${item.resources
257
+ .map((item) => ` - id: ${item.id}\n provider: ${item.provider}\n confidence: ${item.confidence}\n selected: ${selected.includes(item.id)}\n requires: [${(item.requires ?? []).join(", ")}]\n resources: [${item.resources.map(({ type, id }) => `${type}/${id}`).join(", ")}]\n selected_resources: [${item.resources
223
258
  .filter(({ type, id }) => selected.includes(`${type}/${id}`))
224
259
  .map(({ type, id }) => `${type}/${id}`)
225
260
  .join(", ")}]\n evidence: [${item.evidence.map((evidence) => `"${evidence}"`).join(", ")}]\n rationale: ${item.rationale}`)
package/dist/selection.js CHANGED
@@ -3,15 +3,45 @@ export async function selectRecommendations(items, answer, selectedIds) {
3
3
  item.id,
4
4
  ...(item.resources ?? []).map(({ type, id }) => `${type}/${id}`),
5
5
  ]));
6
+ available.add("vitest-testing");
6
7
  if (selectedIds?.includes("all"))
7
8
  return items.map(({ id }) => id);
8
9
  if (selectedIds)
9
- return [...new Set(selectedIds.filter((id) => available.has(id)))];
10
+ return includeRequirements(items, selectedIds
11
+ .filter((id) => available.has(id))
12
+ .map((id) => (id === "vitest-testing" ? "verification" : id)));
10
13
  const selected = [];
11
14
  for (const item of items) {
12
15
  const response = (await answer(`Install ${item.id}? [Y/n] `)).trim().toLowerCase();
13
16
  if (response === "" || response === "y" || response === "yes")
14
17
  selected.push(item.id);
15
18
  }
16
- return selected;
19
+ return includeRequirements(items, selected);
20
+ }
21
+ function includeRequirements(items, selectedIds) {
22
+ const selected = new Set(selectedIds);
23
+ const byId = new Map(items.map((item) => [item.id, item]));
24
+ const owners = new Map();
25
+ for (const item of items)
26
+ for (const resource of item.resources ?? [])
27
+ owners.set(`${resource.type}/${resource.id}`, item.id);
28
+ const visit = (capabilityId, visited) => {
29
+ if (visited.has(capabilityId))
30
+ return;
31
+ visited.add(capabilityId);
32
+ const capability = byId.get(capabilityId);
33
+ if (!capability)
34
+ return;
35
+ for (const requirement of capability.requires ?? []) {
36
+ if (!byId.has(requirement))
37
+ continue;
38
+ selected.add(requirement);
39
+ visit(requirement, visited);
40
+ }
41
+ };
42
+ const initial = [...selected];
43
+ const visited = new Set();
44
+ for (const id of initial)
45
+ visit(byId.has(id) ? id : (owners.get(id) ?? ""), visited);
46
+ return [...selected];
17
47
  }
package/dist/workflow.js CHANGED
@@ -749,6 +749,36 @@ export async function runCommand(args, root, fs, services = {}) {
749
749
  : await profileProject(root);
750
750
  const selectedArg = args.find((arg) => arg.startsWith("--select="))?.split("=", 2)[1];
751
751
  const selected = selectedArg?.split(",") ?? (command === "sync" ? readSelectedRecommendations(fs, aiw) : []);
752
+ if (command === "sync") {
753
+ const result = syncSelectedResources(fs, root, aiw, profile, selected);
754
+ if (result.error)
755
+ return { exitCode: 1, error: result.error };
756
+ const messages = [result.output ?? "Selected bundled resources synchronized."];
757
+ if (selected.includes("react-best-practices")) {
758
+ const approvedPermissions = parseApprovedPermissions(args);
759
+ if (!approvedPermissions.includes("network:external")) {
760
+ messages.push("Remote skill pending: network:external was not approved. Bundled resources were installed; rerun sync with --allow=network:external only if you approve external access.");
761
+ }
762
+ else {
763
+ try {
764
+ enforceConfiguredOrganizationPolicy(fs, aiw, {
765
+ provider: "vercel-skills",
766
+ source: "vercel-labs/agent-skills",
767
+ permissions: ["network:external"],
768
+ });
769
+ const target = parseManifest(fs.read(join(aiw, "manifest.yml"))).target.active;
770
+ await installVercelSkill(services.externalSkills ?? nodeCommandExecutor, "vercel-labs/agent-skills", "vercel-react-best-practices", target);
771
+ writeVercelSkillLock(fs, root, aiw, "vercel-labs/agent-skills", "vercel-react-best-practices");
772
+ messages.push("Remote React best-practices skill installed.");
773
+ }
774
+ catch (error) {
775
+ const reason = error instanceof Error ? error.message : String(error);
776
+ messages.push(`Remote skill pending: ${reason}`);
777
+ }
778
+ }
779
+ }
780
+ return { exitCode: 0, output: messages.join(" ") };
781
+ }
752
782
  if (selected.includes("react-best-practices")) {
753
783
  const approvedPermissions = parseApprovedPermissions(args);
754
784
  if (!approvedPermissions.includes("network:external"))
@@ -765,12 +795,6 @@ export async function runCommand(args, root, fs, services = {}) {
765
795
  await installVercelSkill(services.externalSkills ?? nodeCommandExecutor, "vercel-labs/agent-skills", "vercel-react-best-practices", target);
766
796
  writeVercelSkillLock(fs, root, aiw, "vercel-labs/agent-skills", "vercel-react-best-practices");
767
797
  }
768
- if (command === "sync") {
769
- const result = syncSelectedResources(fs, root, aiw, profile, selected);
770
- return result.error
771
- ? { exitCode: 1, error: result.error }
772
- : { exitCode: 0, output: result.output };
773
- }
774
798
  const conflicts = [];
775
799
  generateProjectResources(profile, selected, (path, content) => {
776
800
  const destination = join(aiw, path);
@@ -1019,12 +1043,16 @@ export async function runCommand(args, root, fs, services = {}) {
1019
1043
  return { exitCode: 1, error: "Run `aiw install` first." };
1020
1044
  const stage = args[1];
1021
1045
  const requirements = {
1022
- specification: "generated/specs/brainstorm.md",
1023
- plan: "generated/specs/specification.md",
1024
- verification: "generated/plans/implementation-plan.md",
1046
+ brainstorming: "generated/specs/brainstorm.md",
1047
+ specification: "generated/specs/specification.md",
1048
+ plan: "generated/plans/implementation-plan.md",
1049
+ verification: "generated/reports/verification-report.md",
1025
1050
  };
1026
- if (!stage || !(stage in requirements))
1027
- return { exitCode: 1, error: "Usage: aiw gate <specification|plan|verification>" };
1051
+ if (!stage || !Object.hasOwn(requirements, stage))
1052
+ return {
1053
+ exitCode: 1,
1054
+ error: "Usage: aiw gate <brainstorming|specification|plan|verification>",
1055
+ };
1028
1056
  const gateStage = stage;
1029
1057
  const artifact = requirements[gateStage];
1030
1058
  if (!fs.exists(join(aiw, artifact)))
@@ -10,9 +10,9 @@ Make `/ai-init` a guided, evidence-backed onboarding flow. The initial `npx` ins
10
10
  2. **Parallel project analysis.** Use the host's native subagent mechanism to start independent read-only scans in parallel. Assign separate work to (a) technologies and package/workspace topology, (b) architecture, modules, and code patterns, and (c) tests, quality tools, and CI. The initiating agent is the orchestrator: it consolidates findings, resolves conflicts using repository evidence, and records paths for every material conclusion. If the host cannot start subagents, do the same scans directly and say so.
11
11
  3. **Monorepo coverage.** Discover root and nested project manifests, workspace definitions, package boundaries, framework configs, tests, and module entry points. Analyze each workspace separately, then summarize shared tooling and cross-workspace relationships. Never infer that root dependencies apply to every workspace.
12
12
  4. **Scan record.** Run the deterministic AI Workflow scan and combine it with the parallel analysis. Present technologies, architecture, patterns, modules, tests, quality commands, workspace topology, confidence, and source evidence. Do not include secret values. Ask for confirmation where conflicting or uncertain findings would affect installed guidance.
13
- 5. **Recommendations.** Match catalog capabilities to the consolidated project profile. Show each recommendation with its purpose, evidence, resource types (skills, rules, agents, hooks, templates), required permissions, MCP server/source, and project-specific configuration steps. Recommend an MCP only when repository evidence supports its use; disclose its publisher/source, capabilities, access, transport, and credential needs. Never invent credentials or silently enable an MCP.
14
- 6. **Selection.** Use the coding host's native selection widget when it supports one. First offer: install all recommendations, customize, or install none. For customization, show selectable blocks grouped by resource type, then the individual recommended items in each selected block. Include MCPs as a separate block. Keep dependencies visible and select required dependencies together. If the host has no selection widget, use an equivalent numbered prompt and accept all/custom/none explicitly.
15
- 7. **Install and personalize.** Install only the confirmed selection. For “all”, install every recommendation. For custom selection, install only selected items and their declared dependencies. Personalize resources only when project evidence materially changes their instructions (for example, test commands, workspace/module layout, framework patterns, or architectural boundaries). Preserve existing files and secrets; report conflicts rather than overwriting. MCP setup must use the selected host's supported project-level configuration, preserve existing configuration, use environment-variable references for secrets, and request separate approval for permissions or external execution.
13
+ 5. **Recommendations.** Match catalog capabilities to the consolidated project profile. Show concise tables grouped by resource category (skills, rules, agents, hooks, templates, and MCPs), with one row per item and a short, project-specific reason plus supporting evidence. Include resource types, required permissions, and project-specific configuration steps where relevant. Recommend an MCP only when repository evidence supports its use; disclose its publisher/source, capabilities, access, transport, and credential needs. Never invent credentials or silently enable an MCP.
14
+ 6. **Selection.** After the recommendation tables, use the coding host's native selection widget when it supports one. First offer: install all recommendations, customize, or install none. For customization, show selectable blocks grouped by resource type, then the individual recommended items in each selected block; retain each item's concise reason and evidence in the selection details. Include MCPs as a separate block. Keep dependencies visible and select required dependencies together. If the host has no selection widget, use an equivalent numbered prompt and accept all/custom/none explicitly.
15
+ 7. **Install and personalize.** Install only the confirmed selection. For “all”, install every recommendation that does not require an unapproved external permission. A missing external permission must not block independent bundled resources; report the external item as pending and give the user the exact retry command. For custom selection, install only selected items and their declared dependencies. Personalize resources only when project evidence materially changes their instructions (for example, test commands, workspace/module layout, framework patterns, or architectural boundaries). Preserve existing files and secrets; report conflicts rather than overwriting. MCP setup must use the selected host's supported project-level configuration, preserve existing configuration, use environment-variable references for secrets, and request separate approval for permissions or external execution.
16
16
  8. **Completion.** Report installed resources by block, project-specific changes, skipped recommendations, conflicts, MCP authentication/trust steps, and validation performed. Recommend restarting/reloading the coding-agent session so newly installed resources are discovered. Do not claim a restart is required when the host loads changes immediately; distinguish host behavior where known.
17
17
 
18
18
  ## Safety and compatibility
@@ -31,12 +31,14 @@ Make `/ai-init` a guided, evidence-backed onboarding flow. The initial `npx` ins
31
31
  - **AIINIT-003:** On supported hosts, three independent read-only analysis agents start in parallel and the orchestrator consolidates their evidence; unsupported hosts use a disclosed sequential fallback.
32
32
  - **AIINIT-004:** Scans include separate summaries for every detected monorepo workspace and do not attribute root dependencies to all packages.
33
33
  - **AIINIT-005:** Recommendations identify matching evidence, resource blocks, dependencies, MCP sources, and permissions.
34
+ - **AIINIT-012:** Recommendations are displayed in concise tables grouped by category, and each item has a project-specific reason and supporting evidence before selection.
34
35
  - **AIINIT-006:** The selection UI offers install-all, custom, and none; custom selections can choose individual items by skills, rules, agents, hooks, templates, and MCPs.
35
36
  - **AIINIT-007:** Installation activates only selected resources and required dependencies, personalizes only context-sensitive content, and preserves unowned or edited files.
36
37
  - **AIINIT-008:** MCP setup is target-aware, merges safely with existing configuration, never stores literal secrets, and requires separate permission approval.
37
38
  - **AIINIT-009:** Completion lists changes and recommends a session restart/reload to discover installed resources.
38
39
  - **AIINIT-010:** CLI tests cover mixed-stack monorepos, all/custom/none selection, permission gating, MCP config merging, personalization, conflicts, and completion output.
39
40
  - **AIINIT-011:** Custom selections can choose individual resource references by block, while `--select=all` selects every recommended capability and `--select=` selects none.
41
+ - **AIINIT-013:** A selected remote resource without approved network access does not block independent bundled resource sync; sync reports the remote item as pending and preserves unrelated project files.
40
42
 
41
43
  ## Delivery slices
42
44
 
package/docs/backlog.md CHANGED
@@ -43,6 +43,7 @@ Priority levels: **P0** blocks the product or makes it unsafe; **P1** is require
43
43
  - [x] **SDD-005** Implement verification skill. _Acceptance:_ missing evidence and untested requirements are reported.
44
44
  - [x] **SDD-006** Implement requirement-to-evidence traceability graph. _Acceptance:_ requirement → decision → task → code → test → evidence is queryable.
45
45
  - [x] **SDD-007** Add quality gates between workflow stages. _Acceptance:_ incomplete artifacts block progression with actionable feedback.
46
+ - [x] **SDD-008** Connect workflow recommendations and quality gates to the SDD sequence. _Acceptance:_ selected later stages include declared prerequisites; verification is recommended for supported project profiles and test runners; each gate checks the matching artifact; review instructions do not refer to a nonexistent CLI gate.
46
47
 
47
48
  ## Adapters and migration — P1/P2
48
49
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@multileaf/ai-workflow",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Portable spec-driven development workflow for AI coding agents",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -7,3 +7,4 @@ description: Turn an early product idea into structured goals, assumptions, cons
7
7
 
8
8
  Separate facts, hypotheses, decisions, and open questions. Identify users, desired outcomes, constraints, risks, and non-goals. Do not prematurely prescribe implementation. Produce a versioned brainstorm artifact in English.
9
9
 
10
+ When the request is already clear, skip brainstorming. Once the goal and constraints are clear, hand off to `requirements-specification` and link the specification to this brainstorm when one exists.
@@ -7,3 +7,4 @@ description: Review code for correctness, maintainability, design quality, and r
7
7
 
8
8
  Review behavior, boundaries, cohesion, naming, types, error handling, duplication, complexity, tests, and documentation. Prioritize actionable findings with severity and evidence.
9
9
 
10
+ If findings require changes, send them back to implementation and require verification again. If there are no blocking findings, record the review result and complete traceability. This skill is a review checklist, not a CLI quality gate.
@@ -7,3 +7,4 @@ description: Break an approved design into independently verifiable implementati
7
7
 
8
8
  Create small ordered tasks. Each task must reference requirements, affected modules, tests, commands, dependencies, and completion evidence.
9
9
 
10
+ After the plan passes its gate, implement in task order. Use `tdd-development` when it is installed and the project has a test workflow; otherwise use the repository's existing validation methods. Hand completed work to `verification`.
@@ -5,5 +5,4 @@ description: Inspect a repository, build a project profile, and prepare AI Workf
5
5
 
6
6
  # Project Initialization
7
7
 
8
- Inspect structure and configuration safely. Detect languages, frameworks, package managers, scripts, tests, quality tools, CI, and conventions. Record evidence and confidence in `.ai-workflow/profile.yaml`. Ask for confirmation before treating uncertain inferences as facts. Recommend capabilities with rationale, permissions, and conflicts.
9
-
8
+ Inspect structure and configuration safely. Detect languages, frameworks, package managers, scripts, tests, quality tools, CI, and conventions. Record evidence and confidence in `.aiw/profile.yml`. Ask for confirmation before treating uncertain inferences as facts. Recommend capabilities with rationale, permissions, and conflicts.
@@ -7,3 +7,4 @@ description: Convert a product idea into testable, traceable requirements.
7
7
 
8
8
  Give each requirement a stable identifier. Define observable behavior, acceptance criteria, constraints, and unresolved questions. Link requirements to their source brainstorm and distinguish confirmed facts from assumptions. Do not approve ambiguous critical requirements.
9
9
 
10
+ After requirements are confirmed, use `technical-design` when the change affects architecture or has consequential design choices; otherwise hand off to `implementation-planning`.
@@ -7,3 +7,4 @@ description: Implement repository changes through test-first development.
7
7
 
8
8
  Follow Red, Green, Refactor, Verify. Write a failing behavioral test first, implement the smallest change, refactor for clarity and design quality, then run the relevant quality gate. Never weaken a test to make an implementation pass.
9
9
 
10
+ After implementation tasks are green and refactored, hand off to `verification` with the changed requirements, test commands, and evidence.
@@ -7,3 +7,4 @@ description: Design modular technical solutions from approved requirements.
7
7
 
8
8
  Map requirements to components, interfaces, data flows, and validation strategy. Compare meaningful alternatives and record decisions with rationale, risks, and consequences. Prefer small cohesive modules, explicit contracts, dependency inversion, and reversible changes.
9
9
 
10
+ Link each design and ADR to the affected requirements. Once decisions are recorded, hand off to `implementation-planning`.
@@ -7,3 +7,4 @@ description: Verify implementation against requirements and produce traceable ev
7
7
 
8
8
  Check every acceptance criterion, quality gate, security requirement, and affected adapter. Report passed checks, missing evidence, failures, and residual risks. A task is not complete when required evidence is missing.
9
9
 
10
+ Create the verification report and validate it with `npx --yes --package=@multileaf/ai-workflow -- aiw gate verification`. Then hand off to `code-review` when installed; after review, update traceability and completion evidence.