@planu/cli 5.7.5 → 5.7.7

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.
Files changed (210) hide show
  1. package/CHANGELOG.md +88 -0
  2. package/README.md +3 -3
  3. package/dist/.planu-build.json +1 -1
  4. package/dist/cli/commands/package-handoff.js +30 -5
  5. package/dist/config/compliance-profiles.json +36 -3
  6. package/dist/config/environment-schema.json +21 -0
  7. package/dist/config/hook-templates/planu-review-panel-trigger.sh +2 -3
  8. package/dist/config/hook-templates/planu-session-safeguard.sh +22 -15
  9. package/dist/config/official-sdd-tools.d.ts +1 -1
  10. package/dist/config/official-sdd-tools.js +11 -24
  11. package/dist/config/registries/hosts/codex.json +14 -30
  12. package/dist/config/registries/hosts/opencode.json +1 -6
  13. package/dist/config/server-instructions.js +0 -21
  14. package/dist/config/skill-templates/planu-context-assets.md +3 -6
  15. package/dist/config/skill-templates/planu-implement.md +2 -2
  16. package/dist/config/skill-templates/planu-multi-teammate-review.md +8 -12
  17. package/dist/config/skill-templates/planu-release.md +2 -7
  18. package/dist/config/skill-templates/planu-validate.md +3 -3
  19. package/dist/config/spec-templates/crud-rest-api/template.json +5 -1
  20. package/dist/config/spec-templates/file-upload-s3/template.json +5 -1
  21. package/dist/config/spec-templates/stripe-payments/template.json +5 -1
  22. package/dist/config/spec-templates/webhook-system/template.json +5 -1
  23. package/dist/config/subagent-templates/planu-challenger.md +4 -9
  24. package/dist/config/subagent-templates/planu-spec-implementer.md +2 -4
  25. package/dist/config/subagent-templates/planu-validator.md +5 -8
  26. package/dist/config/tool-groups.json +6 -144
  27. package/dist/engine/ambiguity-scorer.js +40 -1
  28. package/dist/engine/autopilot/bootstrap.js +1 -1
  29. package/dist/engine/code-impact-analyzer.js +2 -6
  30. package/dist/engine/context-orchestrator/index.js +2 -2
  31. package/dist/engine/convention-scanner/codebase-scanner.js +2 -2
  32. package/dist/engine/dogfooding/runtime-gap-detector.js +2 -2
  33. package/dist/engine/evidence-gates/artifact-reader.d.ts +1 -0
  34. package/dist/engine/evidence-gates/artifact-reader.js +1 -1
  35. package/dist/engine/evidence-gates/evidence-autofill.d.ts +13 -5
  36. package/dist/engine/evidence-gates/evidence-autofill.js +106 -43
  37. package/dist/engine/evidence-gates/evidence-skeletons.js +3 -1
  38. package/dist/engine/evidence-gates/lifecycle-gate.js +7 -4
  39. package/dist/engine/evidence-index/index-builder.js +21 -4
  40. package/dist/engine/execution/job-runtime.js +1 -1
  41. package/dist/engine/execution/package-handoff-job-executor.d.ts +22 -0
  42. package/dist/engine/execution/package-handoff-job-executor.js +490 -0
  43. package/dist/engine/execution/validate-job-executor.js +20 -8
  44. package/dist/engine/git/exec-git.d.ts +4 -0
  45. package/dist/engine/git/exec-git.js +14 -0
  46. package/dist/engine/handoff-artifacts/implementation-review-reader.js +15 -2
  47. package/dist/engine/handoff-artifacts/schemas.d.ts +2 -0
  48. package/dist/engine/handoff-artifacts/schemas.js +1 -0
  49. package/dist/engine/handoff-format.d.ts +36 -0
  50. package/dist/engine/handoff-format.js +314 -0
  51. package/dist/engine/handoff-packager.d.ts +5 -3
  52. package/dist/engine/handoff-packager.js +89 -32
  53. package/dist/engine/host-tool-filter.js +20 -49
  54. package/dist/engine/human-summary.js +14 -3
  55. package/dist/engine/implementation-contract/common.d.ts +8 -3
  56. package/dist/engine/implementation-contract/common.js +9 -6
  57. package/dist/engine/implementation-contract/evaluator.js +4 -6
  58. package/dist/engine/implementation-contract/renderer.js +18 -23
  59. package/dist/engine/project-health-checker.js +2 -2
  60. package/dist/engine/readiness-checker.js +43 -5
  61. package/dist/engine/reconcile/apply-changes.js +4 -0
  62. package/dist/engine/reconcile/propagate-mirrors.d.ts +3 -0
  63. package/dist/engine/reconcile/propagate-mirrors.js +311 -0
  64. package/dist/engine/self-healing/healer.js +12 -5
  65. package/dist/engine/self-healing/strategies/lint-fix.d.ts +1 -1
  66. package/dist/engine/self-healing/strategies/lint-fix.js +4 -1
  67. package/dist/engine/self-healing/strategies/test-fix.d.ts +4 -3
  68. package/dist/engine/self-healing/strategies/test-fix.js +32 -14
  69. package/dist/engine/self-healing/strategies/typescript-fix.d.ts +1 -1
  70. package/dist/engine/self-healing/strategies/typescript-fix.js +28 -10
  71. package/dist/engine/session/checkpoint-writer.js +8 -4
  72. package/dist/engine/session/session-tracker.d.ts +5 -16
  73. package/dist/engine/session/session-tracker.js +29 -26
  74. package/dist/engine/session-state/writer.js +3 -11
  75. package/dist/engine/skill-generator/workflow-skill-generator.d.ts +4 -2
  76. package/dist/engine/skill-generator/workflow-skill-generator.js +113 -38
  77. package/dist/engine/spec-format/bdd-parser.d.ts +1 -11
  78. package/dist/engine/spec-format/bdd-parser.js +40 -11
  79. package/dist/engine/spec-format/lean-spec-generator.js +32 -12
  80. package/dist/engine/spec-format/retired-scaffold.d.ts +3 -0
  81. package/dist/engine/spec-format/retired-scaffold.js +5 -0
  82. package/dist/engine/spec-format/technical-md-populator.d.ts +1 -0
  83. package/dist/engine/spec-format/technical-md-populator.js +27 -0
  84. package/dist/engine/spec-format/unified-spec-builder.d.ts +1 -0
  85. package/dist/engine/spec-format/unified-spec-builder.js +30 -20
  86. package/dist/engine/spec-grounding/contract.d.ts +3 -3
  87. package/dist/engine/spec-grounding/contract.js +65 -4
  88. package/dist/engine/spec-grounding/grounding-entry-parser.d.ts +5 -0
  89. package/dist/engine/spec-grounding/grounding-entry-parser.js +185 -0
  90. package/dist/engine/spec-quality/generic-output-gate.js +37 -3
  91. package/dist/engine/technical-enricher/index.js +4 -1
  92. package/dist/engine/type-safety-gate.js +3 -11
  93. package/dist/engine/universal-rules/catalog.js +0 -2
  94. package/dist/engine/universal-rules/rules/planu-workflow.js +1 -1
  95. package/dist/engine/validation/durable-validation.d.ts +3 -2
  96. package/dist/engine/validation/durable-validation.js +106 -40
  97. package/dist/engine/validation/validation-freshness.d.ts +3 -2
  98. package/dist/engine/validation/validation-freshness.js +22 -16
  99. package/dist/engine/validation/validation-worktree.js +34 -0
  100. package/dist/hosts/claude-code/ux/mcp-prompts.js +8 -8
  101. package/dist/index.js +3 -17
  102. package/dist/resources/process.js +38 -65
  103. package/dist/storage/session-state-store.js +2 -0
  104. package/dist/storage/spec-store.js +8 -1
  105. package/dist/tools/bump-spec-version.js +5 -5
  106. package/dist/tools/challenge-spec/scenarios-utils.js +2 -2
  107. package/dist/tools/configure-checkpoint-policy.js +3 -3
  108. package/dist/tools/create-spec-helpers.js +2 -5
  109. package/dist/tools/create-spec.js +21 -4
  110. package/dist/tools/facilitate.js +3 -6
  111. package/dist/tools/git/branch-ops.js +16 -4
  112. package/dist/tools/github-release-handler.js +1 -20
  113. package/dist/tools/init-project/agents-md-writer.js +6 -6
  114. package/dist/tools/init-project/claude-md-generator.d.ts +0 -1
  115. package/dist/tools/init-project/claude-md-generator.js +0 -35
  116. package/dist/tools/init-project/handler.js +7 -5
  117. package/dist/tools/init-project/per-client-files-writer.js +5 -5
  118. package/dist/tools/init-project/planu-workflow-generator.js +2 -13
  119. package/dist/tools/init-project/portable-index-reconciler.d.ts +2 -1
  120. package/dist/tools/init-project/portable-index-reconciler.js +7 -2
  121. package/dist/tools/init-project/rules-generator.d.ts +0 -11
  122. package/dist/tools/init-project/rules-generator.js +4 -85
  123. package/dist/tools/init-project/scaffold-writer.d.ts +0 -1
  124. package/dist/tools/init-project/scaffold-writer.js +1 -12
  125. package/dist/tools/init-project/skills-multi-teammate-review-writer.js +1 -1
  126. package/dist/tools/jobs/handlers.d.ts +0 -6
  127. package/dist/tools/jobs/handlers.js +13 -40
  128. package/dist/tools/list-specs.js +6 -21
  129. package/dist/tools/multi-teammate-review.js +1 -14
  130. package/dist/tools/package-handoff.d.ts +3 -2
  131. package/dist/tools/package-handoff.js +153 -427
  132. package/dist/tools/reconcile-session-safeguard-hook.js +22 -15
  133. package/dist/tools/register-platform-tools/design-stack-tools.js +3 -3
  134. package/dist/tools/register-sdd-tools.js +0 -23
  135. package/dist/tools/register-spec-tools/analysis-tools.js +22 -9
  136. package/dist/tools/register-spec-tools/core-spec-tools.js +115 -70
  137. package/dist/tools/schemas/index.d.ts +1 -1
  138. package/dist/tools/schemas/index.js +1 -1
  139. package/dist/tools/schemas/output-schemas.d.ts +1 -18
  140. package/dist/tools/schemas/output-schemas.js +1 -11
  141. package/dist/tools/schemas/package-handoff-output-schema.d.ts +40 -0
  142. package/dist/tools/schemas/package-handoff-output-schema.js +68 -0
  143. package/dist/tools/schemas/validate-output-schema.d.ts +1 -2
  144. package/dist/tools/schemas/validate-output-schema.js +3 -2
  145. package/dist/tools/session-checkpoint.js +2 -2
  146. package/dist/tools/skill-registry/index.d.ts +0 -1
  147. package/dist/tools/skill-registry/index.js +0 -1
  148. package/dist/tools/sync-spec-state-handler.d.ts +2 -2
  149. package/dist/tools/sync-spec-state-handler.js +23 -3
  150. package/dist/tools/tool-registry/core-tools.js +72 -164
  151. package/dist/tools/tool-registry/group-infra.js +2 -39
  152. package/dist/tools/tool-registry/group-quality-compliance.js +20 -15
  153. package/dist/tools/tool-registry-helpers.js +6 -2
  154. package/dist/tools/update-status/batch.js +17 -0
  155. package/dist/tools/update-status/dod-gates.js +14 -1
  156. package/dist/tools/update-status/done-receipt-verifier.d.ts +22 -0
  157. package/dist/tools/update-status/done-receipt-verifier.js +56 -26
  158. package/dist/tools/update-status/evidence-gate.js +10 -21
  159. package/dist/tools/update-status/file-sync.d.ts +1 -0
  160. package/dist/tools/update-status/file-sync.js +6 -0
  161. package/dist/tools/update-status/index.d.ts +6 -0
  162. package/dist/tools/update-status/index.js +39 -44
  163. package/dist/tools/update-status-actions.js +2 -7
  164. package/dist/tools/validate.js +34 -28
  165. package/dist/transports/oauth-validator.js +12 -1
  166. package/dist/transports/transport-factory.d.ts +2 -1
  167. package/dist/transports/transport-factory.js +19 -0
  168. package/dist/types/common/primitives.d.ts +2 -0
  169. package/dist/types/durable-job.d.ts +45 -0
  170. package/dist/types/durable-validation.d.ts +1 -1
  171. package/dist/types/evidence-autofill.d.ts +13 -1
  172. package/dist/types/handoff-artifacts.d.ts +2 -1
  173. package/dist/types/readiness.d.ts +8 -1
  174. package/dist/types/reconcile.d.ts +6 -0
  175. package/dist/types/skill-registry.d.ts +26 -1
  176. package/dist/types/spec/core.d.ts +5 -0
  177. package/dist/types/spec/inputs.d.ts +2 -2
  178. package/dist/types/spec-format.d.ts +11 -1
  179. package/dist/types/spec-grounding.d.ts +26 -0
  180. package/dist/types/transport.d.ts +1 -0
  181. package/dist/types/validation-receipt.d.ts +27 -0
  182. package/package.json +3 -2
  183. package/planu-plugin.json +13 -26
  184. package/src/i18n/messages/en.json +1 -1
  185. package/src/i18n/messages/es.json +1 -1
  186. package/src/i18n/messages/pt.json +1 -1
  187. package/dist/engine/skill-generator/conventions-hasher.d.ts +0 -7
  188. package/dist/engine/skill-generator/conventions-hasher.js +0 -24
  189. package/dist/engine/universal-rules/rules/agent-teams.d.ts +0 -3
  190. package/dist/engine/universal-rules/rules/agent-teams.js +0 -63
  191. package/dist/tools/clarify-requirements/multiple-choice.d.ts +0 -30
  192. package/dist/tools/clarify-requirements/multiple-choice.js +0 -306
  193. package/dist/tools/clarify-requirements/questions-context.d.ts +0 -9
  194. package/dist/tools/clarify-requirements/questions-context.js +0 -74
  195. package/dist/tools/clarify-requirements/questions.d.ts +0 -16
  196. package/dist/tools/clarify-requirements/questions.js +0 -96
  197. package/dist/tools/clarify-requirements.d.ts +0 -4
  198. package/dist/tools/clarify-requirements.js +0 -314
  199. package/dist/tools/code-graph-handler.d.ts +0 -6
  200. package/dist/tools/code-graph-handler.js +0 -72
  201. package/dist/tools/create-rule.d.ts +0 -4
  202. package/dist/tools/create-rule.js +0 -107
  203. package/dist/tools/feedback-handler.d.ts +0 -7
  204. package/dist/tools/feedback-handler.js +0 -150
  205. package/dist/tools/semantic-search-handler.d.ts +0 -7
  206. package/dist/tools/semantic-search-handler.js +0 -71
  207. package/dist/tools/skill-registry/search.d.ts +0 -11
  208. package/dist/tools/skill-registry/search.js +0 -159
  209. package/dist/tools/tool-registry/deprecated-stubs.d.ts +0 -19
  210. package/dist/tools/tool-registry/deprecated-stubs.js +0 -65
@@ -16,90 +16,63 @@ function getSddProcess() {
16
16
  {
17
17
  id: 'initializing',
18
18
  name: '1. Initialize',
19
- tools: ['init_project', 'init_constitution', 'detect_agent'],
20
- description: 'Detect project language, framework, architecture, and conventions. ' +
21
- 'Generate the project constitution. Detect the AI agent platform in use.',
19
+ tools: ['init_project'],
20
+ description: 'Load or bootstrap the Planu project context for the current repository.',
22
21
  },
23
22
  {
24
- id: 'analyzing',
25
- name: '2. Analyze',
26
- tools: [
27
- 'clarify_requirements',
28
- 'suggest_stack',
29
- 'check_versions',
30
- 'consult_docs',
31
- 'discover_mcps',
32
- 'suggest_mcps',
33
- 'suggest_tooling',
34
- ],
35
- description: 'Clarify requirements, analyze the stack, check dependency versions, ' +
36
- 'discover available MCP servers, and assess dev lifecycle tooling.',
37
- },
38
- {
39
- id: 'creating-spec',
40
- name: '3. Create Spec',
41
- tools: ['create_spec', 'reverse_engineer', 'estimate'],
42
- description: 'Create a full SDD spec.md from requirements or ' +
43
- 'reverse-engineer from existing code. Estimate effort, cost, and tokens.',
23
+ id: 'defining',
24
+ name: '2. Define',
25
+ tools: ['facilitate', 'create_spec'],
26
+ description: 'Facilitate requirements discovery through the universal SDD entry point, ' +
27
+ 'then create the spec.md that becomes the contract for implementation.',
44
28
  },
45
29
  {
46
- id: 'filtering',
47
- name: '4. Filter & Enrich',
30
+ id: 'approving',
31
+ name: '3. Refine & Approve',
48
32
  tools: [
49
- 'generate_adr',
50
- 'design_schema',
51
- 'define_ui_contract',
52
33
  'challenge_spec',
53
- 'generate_execution_plan',
54
- ],
55
- description: 'Enrich the spec with architecture decisions, database schema, UI contracts, ' +
56
- 'resilience analysis, and step-by-step execution plans.',
57
- },
58
- {
59
- id: 'reviewing',
60
- name: '5. Review',
61
- tools: [
62
- 'summarize_spec',
63
- 'generate_checklist',
64
- 'reconcile_spec',
65
- 'list_specs',
34
+ 'check_readiness',
35
+ 'estimate',
36
+ 'request_changes',
66
37
  'update_status',
67
38
  ],
68
- description: 'Review specs via summaries and checklists. Reconcile with changes. ' +
69
- 'Transition spec status through the lifecycle.',
39
+ description: 'Stress-test the spec, verify it has enough detail to implement, estimate ' +
40
+ 'effort and cost, request changes if gaps remain, and move the spec through ' +
41
+ 'draft → review → approved.',
70
42
  },
71
43
  {
72
44
  id: 'implementing',
73
- name: '6. Implement',
74
- tools: [
75
- 'generate_skill',
76
- 'generate_sub_agent',
77
- 'generate_rules',
78
- 'manage_git',
79
- 'manage_context',
80
- 'orchestrate',
81
- ],
82
- description: 'Generate agent skills and rules. Manage git branches and PRs. ' +
83
- 'Orchestrate multi-agent workflows. Persist context across sessions.',
45
+ name: '4. Implement',
46
+ tools: ['package_handoff', 'bump_spec_version'],
47
+ description: 'Generate the implementation handoff package for the coding agent and bump ' +
48
+ "the spec's SemVer as its contract evolves.",
84
49
  },
85
50
  {
86
51
  id: 'validating',
87
- name: '7. Validate',
88
- tools: ['validate', 'detect_drift', 'audit', 'generate_tests'],
89
- description: 'Validate implementation against spec. Detect drift. Audit code quality. ' +
90
- 'Generate and run test plans.',
52
+ name: '5. Validate',
53
+ tools: ['validate', 'get_job', 'restart_job'],
54
+ description: 'Check the implementation against acceptance criteria, poll the durable ' +
55
+ 'validation job to completion, and restart it if it fails or is cancelled.',
56
+ },
57
+ {
58
+ id: 'closing',
59
+ name: '6. Reconcile & Close',
60
+ tools: ['reconcile_spec', 'migrate_legacy_spec', 'update_status_batch'],
61
+ description: 'Reconcile implementation drift back into the spec, migrate legacy spec docs ' +
62
+ 'onto the canonical spec.md, and batch-transition specs to done. Shipping ' +
63
+ 'runs the local-first release contract (`pnpm check:preflight`, then ' +
64
+ '`pnpm release:local`) outside the MCP tool surface.',
91
65
  },
92
66
  {
93
- id: 'documenting',
94
- name: '8. Document & Ship',
95
- tools: ['generate_docs', 'generate_docs_site', 'integrate_pm', 'learn_pattern'],
96
- description: 'Generate documentation, run the local-first release contract ' +
97
- '(`pnpm check:preflight`, `pnpm release:local` when shipping), ' +
98
- 'sync with project management tools, and learn patterns for future estimations.',
67
+ id: 'tracking',
68
+ name: '7. Track',
69
+ tools: ['list_specs', 'planu_status', 'session_checkpoint'],
70
+ description: 'List specs and their status, check overall project health, and persist ' +
71
+ 'session context so work can resume across sessions.',
99
72
  },
100
73
  ],
101
74
  specLifecycle: ['draft', 'review', 'approved', 'implementing', 'done'],
102
- totalTools: 104,
75
+ totalTools: 19,
103
76
  };
104
77
  }
105
78
  /**
@@ -31,6 +31,8 @@ export function getStagedFiles(projectPath) {
31
31
  cwd: projectPath,
32
32
  encoding: 'utf-8',
33
33
  stdio: ['pipe', 'pipe', 'pipe'],
34
+ timeout: 5_000,
35
+ maxBuffer: 10 * 1024 * 1024,
34
36
  });
35
37
  return output
36
38
  .split('\n')
@@ -256,6 +256,9 @@ async function refreshSpecFromDisk(projectId, spec, canonicalRoot) {
256
256
  specMdPath = await resolveVerifiedSpecPath(spec.id, spec.specPath, canonicalRoot);
257
257
  }
258
258
  catch (error) {
259
+ if (error instanceof PortablePathError && error.code === 'NOT_FOUND') {
260
+ return null;
261
+ }
259
262
  reportClassifiedDegradation('SPEC_CONTENT_DIGEST_CHECK_SKIPPED', error);
260
263
  return spec;
261
264
  }
@@ -264,6 +267,9 @@ async function refreshSpecFromDisk(projectId, spec, canonicalRoot) {
264
267
  content = await readFile(specMdPath, 'utf-8');
265
268
  }
266
269
  catch (error) {
270
+ if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
271
+ return null;
272
+ }
267
273
  reportClassifiedDegradation('SPEC_CONTENT_DIGEST_CHECK_SKIPPED', error);
268
274
  return spec;
269
275
  }
@@ -290,7 +296,8 @@ export async function listSpecs(projectId, canonicalRoot) {
290
296
  if (canonicalRoot === undefined) {
291
297
  return specs;
292
298
  }
293
- return Promise.all(specs.map((spec) => refreshSpecFromDisk(projectId, spec, canonicalRoot)));
299
+ const refreshed = await Promise.all(specs.map((spec) => refreshSpecFromDisk(projectId, spec, canonicalRoot)));
300
+ return refreshed.filter((spec) => spec !== null);
294
301
  }
295
302
  /**
296
303
  * Run a read-modify side effect against a fresh spec snapshot while holding the
@@ -19,14 +19,14 @@ const BumpSpecVersionSchema = {
19
19
  .min(1)
20
20
  .max(4096)
21
21
  .optional()
22
- .describe('Absolute path to the project root. Takes precedence over projectId.'),
22
+ .describe('Absolute path to the project root. Takes precedence over projectId. Max 4096 characters.'),
23
23
  projectId: z
24
24
  .string()
25
25
  .min(1)
26
26
  .max(500)
27
27
  .optional()
28
- .describe('Project ID (hash). Required if projectPath is not provided.'),
29
- specId: SpecIdSchema.describe('Spec ID to bump, e.g. SPEC-042.'),
28
+ .describe('Project ID (hash). Required if projectPath is not provided. Max 500 characters.'),
29
+ specId: SpecIdSchema.describe('Spec ID to bump, e.g. SPEC-042. Must match pattern ^SPEC-\\d+$, max 50 characters.'),
30
30
  kind: z
31
31
  .enum(['patch', 'minor', 'major'])
32
32
  .describe('Bump kind: patch (typo/format), minor (new criterion/scope expansion), major (breaking change).'),
@@ -34,13 +34,13 @@ const BumpSpecVersionSchema = {
34
34
  .string()
35
35
  .min(5)
36
36
  .max(500)
37
- .describe('Free-text reason for the bump (min 5 chars). Recorded in history.'),
37
+ .describe('Free-text reason for the bump. Min 5, max 500 characters. Recorded in history.'),
38
38
  by: z
39
39
  .string()
40
40
  .min(1)
41
41
  .max(200)
42
42
  .optional()
43
- .describe('Actor identifier (session id, plugin id, username). Defaults to a session token.'),
43
+ .describe('Actor identifier (session id, plugin id, username). Defaults to a session token. Max 200 characters.'),
44
44
  };
45
45
  // ---------------------------------------------------------------------------
46
46
  // Handler
@@ -33,8 +33,8 @@ const CAPABILITY_SIGNALS = {
33
33
  /\bbatch\s+upload\b/i,
34
34
  ],
35
35
  scale: [
36
- /\b(?:traffic|load\b(?![\s‐-―-]+bearing)|throughput|requests?\s+per\s+second|concurrent\s+users?)\b/i,
37
- /\b(?:auto[ -]?scal|load\s+test|capacity\s+plan)/i,
36
+ /\b(?:traffic|throughput|requests?\s+per\s+second|concurrent\s+users?)\b/i,
37
+ /\b(?:auto[ -]?scal|load\s+(?:test|balanc|shedding|envelope|spike)|(?:peak|heavy|normal|sustained|read|write)\s+load|capacity\s+plan)/i,
38
38
  /\b(?:data\s+growth|growing\s+dataset|query\s+performance\s+at\s+scale)\b/i,
39
39
  ],
40
40
  dataWrite: [
@@ -1,16 +1,16 @@
1
1
  // tools/configure-checkpoint-policy.ts — Configure auto checkpoint policy (SPEC-563).
2
- import { sessionTracker } from '../engine/session/session-tracker.js';
2
+ import { setCheckpointPolicy, getCheckpointPolicy } from '../engine/session/session-tracker.js';
3
3
  import { compactResult } from './output-formatter.js';
4
4
  /**
5
5
  * Handle the configure_checkpoint_policy tool.
6
6
  * Updates threshold and/or enabled flag, returns the current policy.
7
7
  */
8
8
  export function handleConfigureCheckpointPolicy(args) {
9
- sessionTracker.setPolicy({
9
+ setCheckpointPolicy({
10
10
  threshold: args.threshold,
11
11
  enabled: args.enabled,
12
12
  });
13
- const policy = sessionTracker.getPolicy();
13
+ const policy = getCheckpointPolicy();
14
14
  return compactResult(`Checkpoint policy updated for ${args.projectPath}.\n` +
15
15
  `Threshold: every ${String(policy.threshold)} calls, ` +
16
16
  `enabled: ${String(policy.enabled)}.`);
@@ -26,11 +26,8 @@ export async function tryAutoSetupGit(projectId, specId, options) {
26
26
  /* v8 ignore start -- requires real git repo with branches */
27
27
  try {
28
28
  const r = await handleAutoSetup(projectId, specId, undefined, options);
29
- if (!r.isError && r.content[0]?.type === 'text') {
30
- const data = JSON.parse(r.content[0].text);
31
- if (typeof data.newBranch !== 'string') {
32
- return undefined;
33
- }
29
+ const data = r.structuredContent;
30
+ if (!r.isError && data && typeof data.newBranch === 'string') {
34
31
  return { data, branch: data.newBranch };
35
32
  }
36
33
  }
@@ -20,6 +20,7 @@ import { generateLeanTechnicalContent, } from '../engine/spec-format/lean-techni
20
20
  import { extractFilesFromSpecBody, extractMarkerDeclaredPaths, } from '../engine/spec-format/technical-md-populator.js';
21
21
  import { buildCanonicalUnifiedSpecContent, containsUnresolvedContractPlaceholder, validateUnifiedSpecCandidate, } from '../engine/spec-format/unified-spec-builder.js';
22
22
  import { buildImplementationContractSection } from '../engine/implementation-contract/index.js';
23
+ import { updateFrontmatterField } from '../engine/frontmatter-parser.js';
23
24
  import { resolveEnglishOnlySpecGate } from '../engine/spec-language/english-only.js';
24
25
  import { FallbackGenerator } from '../engine/spec-generator/index.js';
25
26
  import { analyzeProjectForSpec, getEmptyAutopilotResult, } from './create-spec/autopilot-analyzer.js';
@@ -1257,7 +1258,7 @@ async function prepareCreateSpecCandidate(initialParams, server) {
1257
1258
  outOfScope,
1258
1259
  verificationCommands,
1259
1260
  });
1260
- const unifiedSpec = buildCanonicalUnifiedSpecContent({
1261
+ let unifiedSpec = buildCanonicalUnifiedSpecContent({
1261
1262
  leanSpecBody: leanSpec,
1262
1263
  sourceDescription: params.description,
1263
1264
  technicalBody: leanTechnical,
@@ -1269,12 +1270,18 @@ async function prepareCreateSpecCandidate(initialParams, server) {
1269
1270
  const candidateValidation = validateUnifiedSpecCandidate(unifiedSpec, {
1270
1271
  groundedFilePaths: groundedTechnical.records.map((record) => record.path),
1271
1272
  });
1272
- if (!candidateValidation.valid) {
1273
+ // SPEC-1435: MISSING_EXECUTABLE_CRITERIA no longer blocks persistence — plain-text
1274
+ // criteria are accepted input today (checkbox items via extractAcceptanceCriteriaTexts),
1275
+ // and the constant GIVEN/WHEN/THEN scaffold that used to satisfy this check has been
1276
+ // retired. The readiness-checker approval gate now blocks a zero-BDD spec at
1277
+ // review -> approved instead; here it downgrades to a persisted quality warning.
1278
+ const blockingCandidateIssues = candidateValidation.issues.filter((issue) => issue.code !== 'MISSING_EXECUTABLE_CRITERIA');
1279
+ if (blockingCandidateIssues.length > 0) {
1273
1280
  return earlyPreparation({
1274
1281
  content: [
1275
1282
  {
1276
1283
  type: 'text',
1277
- text: `Unified spec candidate is invalid: ${candidateValidation.issues
1284
+ text: `Unified spec candidate is invalid: ${blockingCandidateIssues
1278
1285
  .slice(0, 3)
1279
1286
  .map((issue) => issue.message)
1280
1287
  .join('; ')}`,
@@ -1285,10 +1292,20 @@ async function prepareCreateSpecCandidate(initialParams, server) {
1285
1292
  error: 'SPEC_FORMAT_INVALID',
1286
1293
  code: 422,
1287
1294
  persisted: false,
1288
- issues: candidateValidation.issues,
1295
+ issues: blockingCandidateIssues,
1289
1296
  },
1290
1297
  });
1291
1298
  }
1299
+ if (candidateValidation.issues.some((issue) => issue.code === 'MISSING_EXECUTABLE_CRITERIA')) {
1300
+ const nonExecutableCriteriaWarning = 'Acceptance criteria are not executable GIVEN/WHEN/THEN — restate them before approval';
1301
+ spec.qualityWarnings = [
1302
+ ...new Set([...(spec.qualityWarnings ?? []), nonExecutableCriteriaWarning]),
1303
+ ];
1304
+ // unifiedSpec's frontmatter was already serialized from `spec` before this warning was
1305
+ // known — patch the persisted YAML field directly rather than re-serializing the whole
1306
+ // candidate.
1307
+ unifiedSpec = updateFrontmatterField(unifiedSpec, 'qualityWarnings', JSON.stringify(spec.qualityWarnings));
1308
+ }
1292
1309
  const genericOutputGate = checkGenericSpecOutput(unifiedSpec);
1293
1310
  if (!genericOutputGate.passed) {
1294
1311
  return earlyPreparation({
@@ -39,8 +39,8 @@ function buildExistingProjectResponse(description) {
39
39
  return (`I'll run a diagnostic on your project.\n\n` +
40
40
  `Please provide the project path and call:\n` +
41
41
  `- \`init_project\` with your project path (if not yet initialized)\n` +
42
- `- \`reverse_engineer\` to analyze the codebase\n` +
43
- `- \`audit\` to check spec health\n\n` +
42
+ `- \`list_specs\` to see existing specs\n` +
43
+ `- \`planu_status\` to check overall project health\n\n` +
44
44
  `Request received: "${description.slice(0, 120)}"`);
45
45
  }
46
46
  // ---------------------------------------------------------------------------
@@ -51,7 +51,6 @@ const PROBLEM_TO_TOOL = [
51
51
  [/validat/i, 'validate', 'validate a spec'],
52
52
  [/spec|user stor/i, 'create_spec', 'create a spec/user story'],
53
53
  [/estimat/i, 'estimate', 'estimate effort and cost'],
54
- [/test/i, 'generate_tests', 'generate tests'],
55
54
  [/document|doc/i, 'generate_docs', 'generate documentation'],
56
55
  [/drift|diverge/i, 'detect_drift', 'detect spec drift'],
57
56
  [/schema|database|db/i, 'design_schema', 'design a database schema'],
@@ -69,10 +68,8 @@ function buildConcreteProblemResponse(description) {
69
68
  }
70
69
  return (`I can help with that! Here are the most relevant Planu tools:\n\n` +
71
70
  `- \`create_spec\` — write a new user story / spec\n` +
72
- `- \`clarify_requirements\` — clarify vague requirements\n` +
73
71
  `- \`estimate\` — estimate effort and cost\n` +
74
- `- \`validate\` — check if a spec is complete\n` +
75
- `- \`generate_tests\` — generate test scaffolds\n\n` +
72
+ `- \`validate\` — check if a spec is complete\n\n` +
76
73
  `What specifically would you like to do?`);
77
74
  }
78
75
  // ---------------------------------------------------------------------------
@@ -54,7 +54,10 @@ export async function handleCreateBranch(projectId, specId, config, resolvedProj
54
54
  ? `Switched to existing branch '${branchName}'`
55
55
  : `Branch '${branchName}' already exists (checkout left untouched)`,
56
56
  };
57
- return compactResult(formatKeyValue(result));
57
+ return {
58
+ ...compactResult(formatKeyValue(result)),
59
+ structuredContent: result,
60
+ };
58
61
  }
59
62
  }
60
63
  catch {
@@ -74,7 +77,10 @@ export async function handleCreateBranch(projectId, specId, config, resolvedProj
74
77
  branchName,
75
78
  message: ti('tools.manage_git.success', { action: 'create-branch' }),
76
79
  };
77
- return compactResult(formatKeyValue(result));
80
+ return {
81
+ ...compactResult(formatKeyValue(result)),
82
+ structuredContent: result,
83
+ };
78
84
  }
79
85
  export async function handleCheckBranch(projectId, _specId, config) {
80
86
  const projectPath = await resolveProjectPath(projectId);
@@ -217,7 +223,10 @@ export async function handleAutoSetup(projectId, specId, config, options) {
217
223
  ? `Switched to existing branch '${branchName}' (${gitFlowType} workflow detected)`
218
224
  : `Branch '${branchName}' already exists (checkout left untouched)`,
219
225
  };
220
- return compactResult(formatKeyValue(result));
226
+ return {
227
+ ...compactResult(formatKeyValue(result)),
228
+ structuredContent: result,
229
+ };
221
230
  }
222
231
  }
223
232
  catch {
@@ -235,7 +244,10 @@ export async function handleAutoSetup(projectId, specId, config, options) {
235
244
  ? `Created branch '${branchName}' from '${baseBranch}' (${gitFlowType} workflow detected)`
236
245
  : `Created branch '${branchName}' from '${baseBranch}' without switching the checkout`,
237
246
  };
238
- return compactResult(formatKeyValue(result));
247
+ return {
248
+ ...compactResult(formatKeyValue(result)),
249
+ structuredContent: result,
250
+ };
239
251
  }
240
252
  // ---------------------------------------------------------------------------
241
253
  // Worktree operations (SPEC-260)
@@ -252,26 +252,7 @@ export async function handleCreateRelease(args, exec = defaultExec) {
252
252
  /* best-effort — release_completed cascade never blocks the release response */
253
253
  }
254
254
  })();
255
- // SPEC-1003: Auto-merge develop to main after release (best-effort)
256
- void (async () => {
257
- try {
258
- const releasePath = process.cwd();
259
- const run = promisify(nodeExecFile);
260
- const { stdout: currentBranch } = await run('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {
261
- cwd: releasePath,
262
- });
263
- if (currentBranch.trim() === 'develop') {
264
- await run('git', ['checkout', 'main'], { cwd: releasePath });
265
- await run('git', ['merge', 'develop', '--no-edit'], { cwd: releasePath });
266
- await run('git', ['push', '--no-verify', 'origin', 'main'], { cwd: releasePath });
267
- await run('git', ['checkout', 'develop'], { cwd: releasePath });
268
- outputLines.push(' Auto-merge: develop → main');
269
- }
270
- }
271
- catch {
272
- /* best-effort — auto-merge never blocks release */
273
- }
274
- })();
255
+ outputLines.push(' Mirror sync (run manually if develop exists): git checkout develop && git merge --ff-only origin/main && git push origin develop');
275
256
  return {
276
257
  content: [
277
258
  {
@@ -34,13 +34,13 @@ Auto-generated by \`init_project\`. Mirrors CLAUDE.md for IDEs that read AGENTS.
34
34
  \`\`\`
35
35
  facilitate("what to build") → create_spec → challenge_spec → check_readiness
36
36
  → update_status(review) → approve → update_status(approved) → implement
37
- → validate (ack) → watch_job (completed) → inspect job.result → update_status(done)
37
+ → validate (ack) → get_job (poll until completed) → inspect job.result → update_status(done)
38
38
  \`\`\`
39
39
 
40
40
  ## Durable Validation Gate
41
41
 
42
- 1. Call \`validate\` and capture \`operationId\`, \`projectId\`, \`workspaceId\`, and \`cursor\` from the acknowledgement
43
- 2. Call \`watch_job\` with those identifiers and the latest cursor until the job reaches a terminal state
42
+ 1. Call \`validate\` and capture \`operationId\`, \`projectId\`, and \`workspaceId\` from the acknowledgement
43
+ 2. Poll \`get_job\` with those identifiers until the job reaches a terminal state
44
44
  3. Require \`completed\` and inspect \`job.result.structuredContent\`; stop on \`failed\`, \`dead-letter\`, or \`cancelled\`
45
45
  4. Call \`update_status(done)\` only when the completed result reports \`ready: true\`, \`status: "passing"\`, and passing quality gates
46
46
 
@@ -52,7 +52,7 @@ facilitate("what to build") → create_spec → challenge_spec → check_readine
52
52
  ## Session End
53
53
 
54
54
  - Call \`session_checkpoint\` to save context
55
- - Run \`validate\`, await the completed job with \`watch_job\`, inspect \`job.result.structuredContent\`, then call \`update_status(done)\`
55
+ - Run \`validate\`, poll \`get_job\` until completed, inspect \`job.result.structuredContent\`, then call \`update_status(done)\`
56
56
 
57
57
  ## Quick Reference
58
58
 
@@ -79,7 +79,7 @@ Auto-generated by init_project.
79
79
  1. Before writing any code, call facilitate() or create_spec() first.
80
80
  2. Never write code without an approved Planu spec.
81
81
  3. Always call validate() after implementation; it returns a durable job acknowledgement, not pass/fail.
82
- 4. Call watch_job() until completed and inspect job.result.structuredContent before marking done.
82
+ 4. Poll get_job() until completed and inspect job.result.structuredContent before marking done.
83
83
  5. Use update_status() to track progress: draft → review → approved → implementing → done.
84
84
 
85
85
  ## Session
@@ -91,7 +91,7 @@ Auto-generated by init_project.
91
91
 
92
92
  - New feature: facilitate("what to build")
93
93
  - Check status: planu_status
94
- - Mark done: validate, watch_job until completed, inspect job.result.structuredContent, then update_status(done)
94
+ - Mark done: validate, poll get_job until completed, inspect job.result.structuredContent, then update_status(done)
95
95
  `;
96
96
  async function writeIfMissing(path, content) {
97
97
  try {
@@ -1,4 +1,3 @@
1
1
  import type { ProjectKnowledge } from '../../types/project/core.js';
2
- export declare function buildTeamCoordinationSection(knowledge: ProjectKnowledge): string | null;
3
2
  export declare function buildProjectSections(knowledge: ProjectKnowledge): string;
4
3
  //# sourceMappingURL=claude-md-generator.d.ts.map
@@ -214,37 +214,6 @@ function buildDeployment(knowledge) {
214
214
  const label = key ? DEPLOY_PLATFORM_MAP[key] : raw;
215
215
  return wrap('deployment', `## Deployment\n- **Platform**: ${label}`);
216
216
  }
217
- export function buildTeamCoordinationSection(knowledge) {
218
- const isMultiLayer = knowledge.layers.length > 2;
219
- const isMonorepo = knowledge.monorepo;
220
- if (!isMultiLayer && !isMonorepo) {
221
- return null;
222
- }
223
- const patternList = [
224
- '- `implement-and-test` — one agent implements, another writes tests (no shared files)',
225
- '- `full-stack` — frontend/backend split with clear API boundary',
226
- '- `research-then-build` — researcher gathers context, builder implements',
227
- '- `parallel-specs` — N agents implement N independent specs simultaneously',
228
- ];
229
- const lines = [
230
- '## Agent Teams (for 3+ specs in parallel)',
231
- '',
232
- 'When implementing multiple independent specs simultaneously, use Agent Teams:',
233
- '',
234
- '1. Call `plan_team_distribution` with spec IDs → assigns exclusive file ownership per agent',
235
- '2. Call `generate_teammate_prompt` for each teammate → generates isolated prompt with context',
236
- '3. Spawn N Claude Code agents with the generated prompts (`claude -p "<prompt>"`)',
237
- '4. Call `validate_team_results` after completion → verifies merged code integrity',
238
- '',
239
- '**When to use teams**: 3+ independent specs ready, estimated effort >8h, clear module boundaries.',
240
- '',
241
- '**Available patterns:**',
242
- ...patternList,
243
- '',
244
- '> MANDATORY: two teammates NEVER modify the same file — `plan_team_distribution` enforces this.',
245
- ];
246
- return wrap('team-coordination', lines.join('\n'));
247
- }
248
217
  function buildGitWorkflow(knowledge) {
249
218
  const hasConventional = 'commitlint' in knowledge.conventions ||
250
219
  (knowledge.conventions['commit-style']?.toLowerCase().includes('conventional') ?? false) ||
@@ -288,10 +257,6 @@ export function buildProjectSections(knowledge) {
288
257
  if (gitWorkflow) {
289
258
  sections.push(gitWorkflow);
290
259
  }
291
- const teamCoordination = buildTeamCoordinationSection(knowledge);
292
- if (teamCoordination) {
293
- sections.push(teamCoordination);
294
- }
295
260
  // SPEC-655: Single hardcoded skill entry point — all others discovered via find-skills
296
261
  sections.push(wrap('find-skills', '## Skill Discovery\nUse find-skills to discover available workflows.'));
297
262
  // SPEC-755: Spec location preference — overrides brainstorming skill default (docs/superpowers/specs/)
@@ -23,6 +23,8 @@ import { buildProjectConfig } from './config-builder.js';
23
23
  import { runSpecMigrations, listProjectSpecs } from './migration-runner.js';
24
24
  import { reconcilePortableSpecIndex, buildAlreadyInitializedResult, buildAuthorizedMigrationResult, } from './portable-index-reconciler.js';
25
25
  import { refreshCoreHostAssets } from './host-assets-writer.js';
26
+ import { generateWorkflowSkills } from '../../engine/skill-generator/workflow-skill-generator.js';
27
+ import { fileExists } from '../../core/shared/fs.js';
26
28
  import { scanLegacyGuidance, summarizeLegacyGuidanceScan } from './legacy-guidance-scanner.js';
27
29
  import { runScaffoldWriter } from './scaffold-writer.js';
28
30
  import { readAutoInstallFlag, orchestrateSkillInstalls, runHealthCheckWithBaseline, runConventionScanSafe, fireTelemetry, } from './lifecycle-helpers.js';
@@ -32,7 +34,7 @@ import { join } from 'node:path';
32
34
  import { createHash } from 'node:crypto';
33
35
  import { homedir } from 'node:os';
34
36
  import { mkdir, stat } from 'node:fs/promises';
35
- import { generateAgentTeamsRulesIfMissing, generateWorkflowRulesIfMissing, } from './rules-generator.js';
37
+ import { generateWorkflowRulesIfMissing } from './rules-generator.js';
36
38
  import { installUniversalRules } from '../../engine/universal-rules/installer.js';
37
39
  import { detectHost } from '../../engine/host-detection/detect-host.js';
38
40
  import { configurePlanuHooks } from './hooks-configurator.js';
@@ -229,7 +231,10 @@ export async function handleInitProject(params, server) {
229
231
  ? await scanLegacyGuidance(projectPath)
230
232
  : { healed: [], warnings: [] };
231
233
  const refreshedAssets = canRefresh ? await refreshCoreHostAssets(projectPath) : [];
232
- return buildAlreadyInitializedResult(projectId, reconciliation, legacyMigration.migrated, refreshedAssets, legacyGuidanceScan, projectPath);
234
+ const skillSync = canRefresh && existing !== null && (await fileExists(join(projectPath, '.claude/skills')))
235
+ ? await generateWorkflowSkills(projectPath, existing).catch(() => null)
236
+ : null;
237
+ return buildAlreadyInitializedResult(projectId, reconciliation, legacyMigration.migrated, refreshedAssets, legacyGuidanceScan, projectPath, skillSync);
233
238
  }
234
239
  if (isUpdate) {
235
240
  if (existing === null) {
@@ -465,9 +470,6 @@ export async function handleInitProject(params, server) {
465
470
  // SPEC-200: Anonymous opt-in telemetry — fire-and-forget, never blocks response
466
471
  const neverPrompted = await fireTelemetry(knowledge).catch(() => false);
467
472
  // SPEC-457: Auto-bootstrap rules, hooks, skills for detected stack (fire-and-forget)
468
- void withAudit(projectPath, 'init_project', 'generateAgentTeamsRulesIfMissing', () => generateAgentTeamsRulesIfMissing(projectPath)).catch(() => {
469
- /* best-effort */
470
- });
471
473
  void withAudit(projectPath, 'init_project', 'generateWorkflowRulesIfMissing', () => generateWorkflowRulesIfMissing(projectPath)).catch(() => {
472
474
  /* best-effort */
473
475
  });
@@ -18,13 +18,13 @@ alwaysApply: true
18
18
  \`\`\`
19
19
  facilitate("what to build") → create_spec → challenge_spec → check_readiness
20
20
  → update_status(review) → approve → update_status(approved) → implement
21
- → validate (ack) → watch_job (completed) → inspect job.result → update_status(done)
21
+ → validate (ack) → get_job (poll until completed) → inspect job.result → update_status(done)
22
22
  \`\`\`
23
23
 
24
24
  ## Durable Validation Gate
25
25
 
26
- 1. Call \`validate\` and capture \`operationId\`, \`projectId\`, \`workspaceId\`, and \`cursor\`
27
- 2. Call \`watch_job\` with the latest cursor until terminal
26
+ 1. Call \`validate\` and capture \`operationId\`, \`projectId\`, and \`workspaceId\`
27
+ 2. Poll \`get_job\` with those identifiers until terminal
28
28
  3. Require \`completed\` and inspect \`job.result.structuredContent\`; stop on \`failed\`, \`dead-letter\`, or \`cancelled\`
29
29
  4. Mark done only when the completed result reports \`ready: true\`, \`status: "passing"\`, and passing quality gates
30
30
 
@@ -54,7 +54,7 @@ Planu enforces Spec Driven Development — spec first, then implement, then vali
54
54
 
55
55
  - Starting a new feature: use \`facilitate()\` or \`create_spec()\`
56
56
  - Resuming work: use \`planu_status\` to see what's in progress
57
- - Finishing work: submit \`validate()\`, await \`watch_job()\`, inspect \`job.result.structuredContent\`, then use \`update_status(done)\`
57
+ - Finishing work: submit \`validate()\`, poll \`get_job()\`, inspect \`job.result.structuredContent\`, then use \`update_status(done)\`
58
58
 
59
59
  ## Mandatory Workflow
60
60
 
@@ -64,7 +64,7 @@ Planu enforces Spec Driven Development — spec first, then implement, then vali
64
64
  4. \`update_status(specId, "approved")\` — lock the spec
65
65
  5. Implement the code
66
66
  6. \`validate(specId)\` — submit validation and capture the durable job acknowledgement
67
- 7. \`watch_job(operationId, projectId, workspaceId, cursor)\` — repeat until terminal
67
+ 7. \`get_job(operationId, projectId, workspaceId)\` — poll and repeat until terminal
68
68
  8. Require \`completed\` and inspect \`job.result.structuredContent\`
69
69
  9. \`update_status(specId, "done")\` — mark complete only after a completed passing result
70
70
 
@@ -10,7 +10,7 @@ const PLANU_WORKFLOW_CONTENT = `<!-- planu-sdd-workflow -->
10
10
  ### Session Start
11
11
  1. Call \`planu_status\` — load active specs and git state
12
12
  2. If spec is \`implementing\` → resume it before starting new work
13
- 3. Call \`semantic_search\` before starting any new task
13
+ 3. Call \`list_specs\` before starting any new task to find related work
14
14
 
15
15
  ### For ANY task > 5 minutes
16
16
  NEVER write production code without an approved spec.
@@ -21,22 +21,11 @@ NEVER write production code without an approved spec.
21
21
  ### Session End
22
22
  Call \`session_checkpoint\` to save context for the next session.
23
23
 
24
- ### For Multiple Specs (3+ parallel work)
25
- When implementing multiple independent specs simultaneously, use Agent Teams:
26
- 1. Call \`plan_team_distribution\` with spec IDs → auto-assigns file ownership
27
- 2. Call \`generate_teammate_prompt\` for each teammate → isolated context per agent
28
- 3. Spawn N Claude Code agents with the generated prompts
29
- 4. Call \`validate_team_results\` after completion → verify merged code
30
-
31
- Use teams when: 3+ specs ready, estimated effort >8h, monorepo with clear module boundaries.
32
- Quick ref: parallel work → \`plan_team_distribution\` → teammates → \`validate_team_results\`
33
-
34
24
  ### Quick reference
35
25
  - New feature → \`facilitate("description")\`
36
26
  - Check progress → \`planu_status\`
37
- - Find related work → \`semantic_search("keywords")\`
27
+ - Find related work → \`list_specs\` and scan titles
38
28
  - List pending → \`list_specs\` with status filter
39
- - Parallel work → \`plan_team_distribution\`
40
29
  <!-- /planu-sdd-workflow -->`;
41
30
  /**
42
31
  * Generate the Planu SDD section for CLAUDE.md.