@planu/cli 5.7.5 → 5.7.6

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 (196) hide show
  1. package/CHANGELOG.md +75 -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-session-safeguard.sh +22 -15
  8. package/dist/config/official-sdd-tools.d.ts +1 -1
  9. package/dist/config/official-sdd-tools.js +11 -24
  10. package/dist/config/registries/hosts/codex.json +14 -30
  11. package/dist/config/registries/hosts/opencode.json +1 -6
  12. package/dist/config/server-instructions.js +0 -21
  13. package/dist/config/skill-templates/planu-context-assets.md +3 -6
  14. package/dist/config/skill-templates/planu-implement.md +2 -2
  15. package/dist/config/skill-templates/planu-multi-teammate-review.md +1 -1
  16. package/dist/config/skill-templates/planu-release.md +2 -7
  17. package/dist/config/skill-templates/planu-validate.md +3 -3
  18. package/dist/config/spec-templates/crud-rest-api/template.json +5 -1
  19. package/dist/config/spec-templates/file-upload-s3/template.json +5 -1
  20. package/dist/config/spec-templates/stripe-payments/template.json +5 -1
  21. package/dist/config/spec-templates/webhook-system/template.json +5 -1
  22. package/dist/config/subagent-templates/planu-challenger.md +4 -9
  23. package/dist/config/subagent-templates/planu-spec-implementer.md +2 -4
  24. package/dist/config/subagent-templates/planu-validator.md +5 -8
  25. package/dist/config/tool-groups.json +6 -144
  26. package/dist/engine/ambiguity-scorer.js +40 -1
  27. package/dist/engine/autopilot/bootstrap.js +1 -1
  28. package/dist/engine/code-impact-analyzer.js +2 -6
  29. package/dist/engine/context-orchestrator/index.js +2 -2
  30. package/dist/engine/convention-scanner/codebase-scanner.js +2 -2
  31. package/dist/engine/dogfooding/runtime-gap-detector.js +2 -2
  32. package/dist/engine/evidence-gates/artifact-reader.d.ts +1 -0
  33. package/dist/engine/evidence-gates/artifact-reader.js +1 -1
  34. package/dist/engine/evidence-gates/evidence-autofill.d.ts +13 -5
  35. package/dist/engine/evidence-gates/evidence-autofill.js +106 -43
  36. package/dist/engine/evidence-gates/lifecycle-gate.js +7 -4
  37. package/dist/engine/evidence-index/index-builder.js +21 -4
  38. package/dist/engine/execution/job-runtime.js +1 -1
  39. package/dist/engine/execution/package-handoff-job-executor.d.ts +22 -0
  40. package/dist/engine/execution/package-handoff-job-executor.js +490 -0
  41. package/dist/engine/execution/validate-job-executor.js +20 -8
  42. package/dist/engine/git/exec-git.d.ts +4 -0
  43. package/dist/engine/git/exec-git.js +14 -0
  44. package/dist/engine/handoff-artifacts/implementation-review-reader.js +15 -2
  45. package/dist/engine/handoff-artifacts/schemas.d.ts +2 -0
  46. package/dist/engine/handoff-artifacts/schemas.js +1 -0
  47. package/dist/engine/handoff-format.d.ts +36 -0
  48. package/dist/engine/handoff-format.js +314 -0
  49. package/dist/engine/handoff-packager.d.ts +5 -3
  50. package/dist/engine/handoff-packager.js +89 -32
  51. package/dist/engine/host-tool-filter.js +20 -49
  52. package/dist/engine/human-summary.js +14 -3
  53. package/dist/engine/implementation-contract/common.d.ts +8 -3
  54. package/dist/engine/implementation-contract/common.js +9 -6
  55. package/dist/engine/implementation-contract/evaluator.js +4 -6
  56. package/dist/engine/implementation-contract/renderer.js +18 -23
  57. package/dist/engine/project-health-checker.js +2 -2
  58. package/dist/engine/readiness-checker.js +27 -0
  59. package/dist/engine/reconcile/apply-changes.js +4 -0
  60. package/dist/engine/reconcile/propagate-mirrors.d.ts +3 -0
  61. package/dist/engine/reconcile/propagate-mirrors.js +311 -0
  62. package/dist/engine/self-healing/healer.js +12 -5
  63. package/dist/engine/self-healing/strategies/lint-fix.d.ts +1 -1
  64. package/dist/engine/self-healing/strategies/lint-fix.js +4 -1
  65. package/dist/engine/self-healing/strategies/test-fix.d.ts +4 -3
  66. package/dist/engine/self-healing/strategies/test-fix.js +32 -14
  67. package/dist/engine/self-healing/strategies/typescript-fix.d.ts +1 -1
  68. package/dist/engine/self-healing/strategies/typescript-fix.js +28 -10
  69. package/dist/engine/session/checkpoint-writer.js +8 -4
  70. package/dist/engine/session/session-tracker.d.ts +5 -16
  71. package/dist/engine/session/session-tracker.js +29 -26
  72. package/dist/engine/session-state/writer.js +3 -11
  73. package/dist/engine/skill-generator/workflow-skill-generator.d.ts +4 -2
  74. package/dist/engine/skill-generator/workflow-skill-generator.js +113 -38
  75. package/dist/engine/spec-format/bdd-parser.d.ts +1 -11
  76. package/dist/engine/spec-format/bdd-parser.js +40 -11
  77. package/dist/engine/spec-format/lean-spec-generator.js +30 -10
  78. package/dist/engine/spec-format/retired-scaffold.d.ts +3 -0
  79. package/dist/engine/spec-format/retired-scaffold.js +5 -0
  80. package/dist/engine/spec-format/technical-md-populator.d.ts +1 -0
  81. package/dist/engine/spec-format/technical-md-populator.js +27 -0
  82. package/dist/engine/spec-format/unified-spec-builder.d.ts +1 -0
  83. package/dist/engine/spec-format/unified-spec-builder.js +30 -20
  84. package/dist/engine/spec-grounding/contract.js +115 -1
  85. package/dist/engine/spec-quality/generic-output-gate.js +37 -3
  86. package/dist/engine/technical-enricher/index.js +4 -1
  87. package/dist/engine/type-safety-gate.js +3 -11
  88. package/dist/engine/universal-rules/catalog.js +0 -2
  89. package/dist/engine/universal-rules/rules/planu-workflow.js +1 -1
  90. package/dist/engine/validation/durable-validation.d.ts +3 -2
  91. package/dist/engine/validation/durable-validation.js +106 -40
  92. package/dist/engine/validation/validation-freshness.d.ts +3 -2
  93. package/dist/engine/validation/validation-freshness.js +22 -16
  94. package/dist/engine/validation/validation-worktree.js +34 -0
  95. package/dist/hosts/claude-code/ux/mcp-prompts.js +8 -8
  96. package/dist/index.js +3 -17
  97. package/dist/resources/process.js +38 -65
  98. package/dist/storage/session-state-store.js +2 -0
  99. package/dist/tools/challenge-spec/scenarios-utils.js +2 -2
  100. package/dist/tools/configure-checkpoint-policy.js +3 -3
  101. package/dist/tools/create-spec-helpers.js +2 -5
  102. package/dist/tools/create-spec.js +21 -4
  103. package/dist/tools/facilitate.js +3 -6
  104. package/dist/tools/git/branch-ops.js +16 -4
  105. package/dist/tools/github-release-handler.js +1 -20
  106. package/dist/tools/init-project/agents-md-writer.js +6 -6
  107. package/dist/tools/init-project/claude-md-generator.d.ts +0 -1
  108. package/dist/tools/init-project/claude-md-generator.js +0 -35
  109. package/dist/tools/init-project/handler.js +7 -5
  110. package/dist/tools/init-project/per-client-files-writer.js +5 -5
  111. package/dist/tools/init-project/planu-workflow-generator.js +2 -13
  112. package/dist/tools/init-project/portable-index-reconciler.d.ts +2 -1
  113. package/dist/tools/init-project/portable-index-reconciler.js +7 -2
  114. package/dist/tools/init-project/rules-generator.d.ts +0 -11
  115. package/dist/tools/init-project/rules-generator.js +4 -85
  116. package/dist/tools/init-project/scaffold-writer.d.ts +0 -1
  117. package/dist/tools/init-project/scaffold-writer.js +1 -12
  118. package/dist/tools/jobs/handlers.d.ts +0 -6
  119. package/dist/tools/jobs/handlers.js +13 -40
  120. package/dist/tools/list-specs.js +6 -21
  121. package/dist/tools/package-handoff.d.ts +3 -2
  122. package/dist/tools/package-handoff.js +153 -427
  123. package/dist/tools/reconcile-session-safeguard-hook.js +22 -15
  124. package/dist/tools/register-sdd-tools.js +0 -23
  125. package/dist/tools/register-spec-tools/core-spec-tools.js +18 -27
  126. package/dist/tools/schemas/index.d.ts +1 -1
  127. package/dist/tools/schemas/index.js +1 -1
  128. package/dist/tools/schemas/output-schemas.d.ts +1 -18
  129. package/dist/tools/schemas/output-schemas.js +1 -11
  130. package/dist/tools/schemas/package-handoff-output-schema.d.ts +40 -0
  131. package/dist/tools/schemas/package-handoff-output-schema.js +68 -0
  132. package/dist/tools/schemas/validate-output-schema.d.ts +1 -2
  133. package/dist/tools/schemas/validate-output-schema.js +3 -2
  134. package/dist/tools/session-checkpoint.js +2 -2
  135. package/dist/tools/skill-registry/index.d.ts +0 -1
  136. package/dist/tools/skill-registry/index.js +0 -1
  137. package/dist/tools/sync-spec-state-handler.d.ts +2 -2
  138. package/dist/tools/sync-spec-state-handler.js +23 -3
  139. package/dist/tools/tool-registry/core-tools.js +1 -140
  140. package/dist/tools/tool-registry/group-infra.js +2 -39
  141. package/dist/tools/tool-registry/group-quality-compliance.js +9 -1
  142. package/dist/tools/update-status/batch.js +17 -0
  143. package/dist/tools/update-status/dod-gates.js +14 -1
  144. package/dist/tools/update-status/done-receipt-verifier.d.ts +22 -0
  145. package/dist/tools/update-status/done-receipt-verifier.js +56 -26
  146. package/dist/tools/update-status/evidence-gate.js +10 -21
  147. package/dist/tools/update-status/file-sync.d.ts +1 -0
  148. package/dist/tools/update-status/file-sync.js +6 -0
  149. package/dist/tools/update-status/index.d.ts +6 -0
  150. package/dist/tools/update-status/index.js +39 -44
  151. package/dist/tools/update-status-actions.js +2 -7
  152. package/dist/tools/validate.js +34 -28
  153. package/dist/transports/oauth-validator.js +12 -1
  154. package/dist/transports/transport-factory.d.ts +2 -1
  155. package/dist/transports/transport-factory.js +19 -0
  156. package/dist/types/common/primitives.d.ts +2 -0
  157. package/dist/types/durable-job.d.ts +45 -0
  158. package/dist/types/durable-validation.d.ts +1 -1
  159. package/dist/types/evidence-autofill.d.ts +13 -1
  160. package/dist/types/handoff-artifacts.d.ts +2 -1
  161. package/dist/types/readiness.d.ts +8 -1
  162. package/dist/types/reconcile.d.ts +6 -0
  163. package/dist/types/skill-registry.d.ts +26 -1
  164. package/dist/types/spec/core.d.ts +5 -0
  165. package/dist/types/spec/inputs.d.ts +2 -2
  166. package/dist/types/spec-format.d.ts +11 -1
  167. package/dist/types/spec-grounding.d.ts +12 -0
  168. package/dist/types/transport.d.ts +1 -0
  169. package/dist/types/validation-receipt.d.ts +27 -0
  170. package/package.json +3 -2
  171. package/planu-plugin.json +13 -26
  172. package/src/i18n/messages/en.json +1 -1
  173. package/src/i18n/messages/es.json +1 -1
  174. package/src/i18n/messages/pt.json +1 -1
  175. package/dist/engine/skill-generator/conventions-hasher.d.ts +0 -7
  176. package/dist/engine/skill-generator/conventions-hasher.js +0 -24
  177. package/dist/engine/universal-rules/rules/agent-teams.d.ts +0 -3
  178. package/dist/engine/universal-rules/rules/agent-teams.js +0 -63
  179. package/dist/tools/clarify-requirements/multiple-choice.d.ts +0 -30
  180. package/dist/tools/clarify-requirements/multiple-choice.js +0 -306
  181. package/dist/tools/clarify-requirements/questions-context.d.ts +0 -9
  182. package/dist/tools/clarify-requirements/questions-context.js +0 -74
  183. package/dist/tools/clarify-requirements/questions.d.ts +0 -16
  184. package/dist/tools/clarify-requirements/questions.js +0 -96
  185. package/dist/tools/clarify-requirements.d.ts +0 -4
  186. package/dist/tools/clarify-requirements.js +0 -314
  187. package/dist/tools/code-graph-handler.d.ts +0 -6
  188. package/dist/tools/code-graph-handler.js +0 -72
  189. package/dist/tools/create-rule.d.ts +0 -4
  190. package/dist/tools/create-rule.js +0 -107
  191. package/dist/tools/feedback-handler.d.ts +0 -7
  192. package/dist/tools/feedback-handler.js +0 -150
  193. package/dist/tools/semantic-search-handler.d.ts +0 -7
  194. package/dist/tools/semantic-search-handler.js +0 -71
  195. package/dist/tools/skill-registry/search.d.ts +0 -11
  196. package/dist/tools/skill-registry/search.js +0 -159
@@ -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.
@@ -1,3 +1,4 @@
1
+ import type { WorkflowSkillGenerationResult } from '../../types/skill-registry.js';
1
2
  import type { FilesystemImportDeps, FilesystemImportFailure, LegacyGuidanceScanResult, PortableIndexReconciliationResult, SkippedLegacyContract } from '../../types/index.js';
2
3
  import type { ToolResult } from '../../types/common/primitives.js';
3
4
  /** Autopilot-first summary of fatal reconciliation failures: what failed, why, and the next action. */
@@ -10,7 +11,7 @@ export declare function describeReconciliationOutcome(reconciliation: PortableIn
10
11
  * SPEC-1716: Build the already-initialized `init_project` result, folding the
11
12
  * legacy-guidance scan's healed paths into the reported repository file changes.
12
13
  */
13
- export declare function buildAlreadyInitializedResult(projectId: string, reconciliation: PortableIndexReconciliationResult, legacyMigratedPaths: readonly string[], refreshedAssets: readonly string[], legacyGuidanceScan: LegacyGuidanceScanResult, projectPath: string): ToolResult;
14
+ export declare function buildAlreadyInitializedResult(projectId: string, reconciliation: PortableIndexReconciliationResult, legacyMigratedPaths: readonly string[], refreshedAssets: readonly string[], legacyGuidanceScan: LegacyGuidanceScanResult, projectPath: string, skillSync?: WorkflowSkillGenerationResult | null): ToolResult;
14
15
  /** The subset of `MigrationRunResult` (migration-runner.ts) needed to report an authorized migration. */
15
16
  interface AuthorizedMigrationSummary {
16
17
  criticalMigrationFailures: unknown[];
@@ -160,14 +160,17 @@ export function describeReconciliationOutcome(reconciliation, repositoryFilesCha
160
160
  * SPEC-1716: Build the already-initialized `init_project` result, folding the
161
161
  * legacy-guidance scan's healed paths into the reported repository file changes.
162
162
  */
163
- export function buildAlreadyInitializedResult(projectId, reconciliation, legacyMigratedPaths, refreshedAssets, legacyGuidanceScan, projectPath) {
163
+ export function buildAlreadyInitializedResult(projectId, reconciliation, legacyMigratedPaths, refreshedAssets, legacyGuidanceScan, projectPath, skillSync = null) {
164
164
  const repositoryFilesChanged = [...refreshedAssets, ...legacyGuidanceScan.healed];
165
165
  const baseText = describeReconciliationOutcome(reconciliation, [...refreshedAssets]);
166
166
  const healedGuidanceSuffix = legacyGuidanceScan.healed.length === 0
167
167
  ? ''
168
168
  : ` Healed stale legacy guidance in: ${legacyGuidanceScan.healed.join(', ')}.`;
169
+ const skillSyncSuffix = skillSync === null
170
+ ? ''
171
+ : ` Refreshed ${String(skillSync.written.length)} workflow skill(s), left ${String(skillSync.userModified.length)} user-modified skill(s) untouched.`;
169
172
  return {
170
- content: [{ type: 'text', text: baseText + healedGuidanceSuffix }],
173
+ content: [{ type: 'text', text: baseText + healedGuidanceSuffix + skillSyncSuffix }],
171
174
  structuredContent: {
172
175
  projectId,
173
176
  ...(reconciliation.failures.length === 0 ? { projectPath } : {}),
@@ -181,6 +184,8 @@ export function buildAlreadyInitializedResult(projectId, reconciliation, legacyM
181
184
  migratedLegacyPaths: legacyMigratedPaths,
182
185
  legacyGuidanceHealed: legacyGuidanceScan.healed,
183
186
  legacyGuidanceWarnings: legacyGuidanceScan.warnings,
187
+ skillsWritten: skillSync?.written.length ?? 0,
188
+ skillsUserModified: skillSync?.userModified.length ?? 0,
184
189
  },
185
190
  ...(reconciliation.failures.length > 0 ? { isError: true } : {}),
186
191
  };
@@ -1,14 +1,3 @@
1
- export declare function generateAgentTeamsRulesContent(): string;
2
- /**
3
- * Write .claude/rules/agent-teams.md to the target project.
4
- * Always overwrites to keep the content up to date.
5
- */
6
- export declare function generateAgentTeamsRules(projectPath: string): Promise<void>;
7
- /**
8
- * Write .claude/rules/agent-teams.md only if it does not exist yet.
9
- * @returns true if the file was created, false if it already existed.
10
- */
11
- export declare function generateAgentTeamsRulesIfMissing(projectPath: string): Promise<boolean>;
12
1
  /**
13
2
  * Write .claude/rules/planu-workflow.md to the target project.
14
3
  * Always overwrites to keep the content up to date.
@@ -18,12 +18,12 @@ Auto-generated by \`init_project\`. Do not edit manually.
18
18
  | implementing | work in progress |
19
19
  | done | implemented + validated |
20
20
 
21
- Flow: \`facilitate → create_spec → challenge_spec → check_readiness → approve → implement → validate (ack) → watch_job (completed) → inspect job.result → done\`
21
+ Flow: \`facilitate → create_spec → challenge_spec → check_readiness → approve → implement → validate (ack) → get_job (poll until completed) → inspect job.result → done\`
22
22
 
23
23
  ## Durable Validation Gate
24
24
 
25
- 1. Call \`validate\` and capture \`operationId\`, \`projectId\`, \`workspaceId\`, and \`cursor\` from the acknowledgement.
26
- 2. Call \`watch_job\` with those identifiers and the latest cursor. Repeat while state is non-terminal.
25
+ 1. Call \`validate\` and capture \`operationId\`, \`projectId\`, and \`workspaceId\` from the acknowledgement.
26
+ 2. Poll \`get_job\` with those identifiers. Repeat while state is non-terminal.
27
27
  3. Require state \`completed\`, then inspect \`job.result.structuredContent\`. Stop and report \`failed\`, \`dead-letter\`, or \`cancelled\`.
28
28
  4. Call \`update_status(done)\` only after the completed result reports \`ready: true\`, \`status: "passing"\`, and passing quality gates.
29
29
 
@@ -60,7 +60,7 @@ Any new feature, bug fix, refactor, integration, or task > 5 min.
60
60
  |------|------|
61
61
  | New feature | \`facilitate("what to build")\` |
62
62
  | Project status | \`planu_status\` |
63
- | Find related specs | \`semantic_search("keywords")\` |
63
+ | Find related specs | \`list_specs\` and scan titles |
64
64
  | List approved work | \`list_specs\` with \`status: approved\` |
65
65
  | Mark done | \`update_status\` → \`done\` |
66
66
  | Verify | \`validate\` |
@@ -102,87 +102,6 @@ Set \`CLAUDE_CODE_SUBAGENT_MODEL=haiku\` in \`.env\` for automatic haiku on all
102
102
  - Keep output < 500 tokens for read operations, < 200 tokens for write confirmations
103
103
  - After every tool call: explain what happened in simple terms
104
104
  `;
105
- const AGENT_TEAMS_RULES_PATH = '.claude/rules/agent-teams.md';
106
- export function generateAgentTeamsRulesContent() {
107
- return `# Agent Teams (MANDATORY when 3+ specs in parallel)
108
-
109
- This rule file is auto-generated by Planu \`init_project\`. Do not edit manually — re-run \`init_project\` to update.
110
-
111
- ## When to Use Agent Teams
112
-
113
- Use Agent Teams when ALL of the following apply:
114
- - 3+ independent specs are ready to implement simultaneously
115
- - Estimated total effort > 8h
116
- - Specs touch different modules/packages (clear file ownership boundaries)
117
- - Monorepo or multi-layer architecture with well-defined interfaces
118
-
119
- ## File Ownership (MANDATORY)
120
-
121
- **Two teammates MUST NEVER modify the same file.** This is non-negotiable.
122
-
123
- - \`plan_team_distribution\` auto-assigns exclusive file ownership per agent
124
- - Review the distribution before spawning — resolve any conflicts first
125
- - If two specs require the same shared file, implement them sequentially, not in parallel
126
-
127
- ## Workflow
128
-
129
- \`\`\`
130
- 1. plan_team_distribution # input: spec IDs → output: file ownership map
131
- 2. generate_teammate_prompt # input: teammate assignment → output: isolated prompt
132
- 3. spawn N agents # claude -p "<prompt>" for each teammate (run in parallel)
133
- 4. validate_team_results # input: projectPath → verifies merged code integrity
134
- \`\`\`
135
-
136
- ## Available Team Patterns
137
-
138
- - **implement-and-test** — one agent implements, another writes tests (zero shared files)
139
- - **full-stack** — frontend and backend agents with a contract-first API boundary
140
- - **research-then-build** — researcher gathers context first, builder implements after
141
- - **parallel-specs** — N agents implement N fully independent specs simultaneously
142
-
143
- ## Quick Reference
144
-
145
- | Goal | Tool |
146
- |------|------|
147
- | Plan team distribution | \`plan_team_distribution\` with spec IDs array |
148
- | Get teammate context | \`generate_teammate_prompt\` with assignment object |
149
- | Validate merged result | \`validate_team_results\` after all agents complete |
150
-
151
- ## Prohibited Patterns
152
-
153
- - NEVER spawn teammates without running \`plan_team_distribution\` first
154
- - NEVER assign the same file to two different teammates
155
- - NEVER skip \`validate_team_results\` after parallel implementation
156
- - NEVER use Agent Teams for 1-2 specs — sequential is faster and safer
157
- `;
158
- }
159
- /**
160
- * Write .claude/rules/agent-teams.md to the target project.
161
- * Always overwrites to keep the content up to date.
162
- */
163
- export async function generateAgentTeamsRules(projectPath) {
164
- const rulesPath = join(projectPath, AGENT_TEAMS_RULES_PATH);
165
- const rulesDir = join(projectPath, '.claude/rules');
166
- await mkdir(rulesDir, { recursive: true });
167
- const content = generateAgentTeamsRulesContent();
168
- assertEnglishOnlyArtifactText(content, 'rule');
169
- await writeFile(rulesPath, content, 'utf-8');
170
- }
171
- /**
172
- * Write .claude/rules/agent-teams.md only if it does not exist yet.
173
- * @returns true if the file was created, false if it already existed.
174
- */
175
- export async function generateAgentTeamsRulesIfMissing(projectPath) {
176
- const rulesPath = join(projectPath, AGENT_TEAMS_RULES_PATH);
177
- try {
178
- await access(rulesPath);
179
- return false; // already exists
180
- }
181
- catch {
182
- await generateAgentTeamsRules(projectPath);
183
- return true;
184
- }
185
- }
186
105
  /**
187
106
  * Write .claude/rules/planu-workflow.md to the target project.
188
107
  * Always overwrites to keep the content up to date.
@@ -22,7 +22,6 @@ export interface ScaffoldWriteResult {
22
22
  planuWorkflowInjected: boolean;
23
23
  planuHooksConfigured: boolean;
24
24
  planuRulesWritten: boolean;
25
- agentTeamsRulesWritten: boolean;
26
25
  modeRulesWritten: boolean;
27
26
  responseStyleRulesWritten: boolean;
28
27
  compactSkillWritten: boolean;
@@ -8,7 +8,7 @@ import { runGitSetup } from './git-setup.js';
8
8
  import { generateAndWriteRules } from './lifecycle-helpers.js';
9
9
  import { generatePlanuSection, injectPlanuSection } from './planu-workflow-generator.js';
10
10
  import { configurePlanuHooks } from './hooks-configurator.js';
11
- import { generateWorkflowRulesIfMissing, generateAgentTeamsRulesIfMissing, generateModeRulesIfMissing, generateResponseStyleRulesIfMissing, } from './rules-generator.js';
11
+ import { generateWorkflowRulesIfMissing, generateModeRulesIfMissing, generateResponseStyleRulesIfMissing, } from './rules-generator.js';
12
12
  import { generateCompactSkillIfMissing } from './skills-writer.js';
13
13
  import { generateFindSkillsIfMissing } from './find-skills-writer.js';
14
14
  import { injectPlanuAutoStage } from '../../engine/git-hook-injector.js';
@@ -120,16 +120,6 @@ export async function runScaffoldWriter(projectPath, projectId, knowledge, recom
120
120
  /* best-effort */
121
121
  }
122
122
  }
123
- // SPEC-291: Write .claude/rules/agent-teams.md if missing (best-effort)
124
- let agentTeamsRulesWritten = false;
125
- if (shouldWriteClaudeAssets) {
126
- try {
127
- agentTeamsRulesWritten = await generateAgentTeamsRulesIfMissing(projectPath);
128
- }
129
- catch {
130
- /* best-effort */
131
- }
132
- }
133
123
  // SPEC-494: Write .claude/rules/planu-modes.md if missing (best-effort)
134
124
  let modeRulesWritten = false;
135
125
  if (shouldWriteClaudeAssets) {
@@ -394,7 +384,6 @@ export async function runScaffoldWriter(projectPath, projectId, knowledge, recom
394
384
  planuWorkflowInjected,
395
385
  planuHooksConfigured,
396
386
  planuRulesWritten,
397
- agentTeamsRulesWritten,
398
387
  modeRulesWritten,
399
388
  responseStyleRulesWritten,
400
389
  compactSkillWritten,
@@ -4,12 +4,6 @@ export interface JobToolIdentityInput {
4
4
  projectId: string;
5
5
  workspaceId?: string;
6
6
  }
7
- export interface WatchJobToolInput extends JobToolIdentityInput {
8
- afterCursor?: string;
9
- timeoutMs?: number;
10
- }
11
7
  export declare function handleGetJob(input: JobToolIdentityInput): Promise<ToolResult>;
12
- export declare function handleWatchJob(input: WatchJobToolInput): Promise<ToolResult>;
13
- export declare function handleCancelJob(input: JobToolIdentityInput): Promise<ToolResult>;
14
8
  export declare function handleRestartJob(input: JobToolIdentityInput): Promise<ToolResult>;
15
9
  //# sourceMappingURL=handlers.d.ts.map
@@ -52,6 +52,7 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
52
52
  });
53
53
  import { DurableJobRuntime, publicJobCursor } from '../../engine/execution/job-runtime.js';
54
54
  import { scheduleValidateJobExecution } from '../../engine/execution/validate-job-executor.js';
55
+ import { schedulePackageHandoffJobExecution } from '../../engine/execution/package-handoff-job-executor.js';
55
56
  import { isValidationReceiptPendingIntent, parseValidationReceiptPendingCheckpoint, } from '../../types/durable-validation.js';
56
57
  import { redactText } from '../../security/redactor.js';
57
58
  import { getRuntimePolicy } from '../../engine/runtime-policy.js';
@@ -97,62 +98,34 @@ export function handleGetJob(input) {
97
98
  __disposeResources(env_1);
98
99
  }
99
100
  }
100
- export async function handleWatchJob(input) {
101
+ export function handleRestartJob(input) {
101
102
  const env_2 = { stack: [], error: void 0, hasError: false };
102
103
  try {
103
104
  const runtime = __addDisposableResource(env_2, new DurableJobRuntime(), false);
104
- const job = await runtime.watch(input);
105
- const observation = publicJob(runtime, job);
106
- return result({ schemaVersion: 1, job: observation, cursor: publicJobCursor(observation) });
107
- }
108
- catch (e_2) {
109
- env_2.error = e_2;
110
- env_2.hasError = true;
111
- }
112
- finally {
113
- __disposeResources(env_2);
114
- }
115
- }
116
- export function handleCancelJob(input) {
117
- const env_3 = { stack: [], error: void 0, hasError: false };
118
- try {
119
- const runtime = __addDisposableResource(env_3, new DurableJobRuntime(), false);
120
- const job = runtime.cancel(input);
121
- const observation = publicJob(runtime, job);
122
- return Promise.resolve(result({ schemaVersion: 1, job: observation, cursor: publicJobCursor(observation) }));
123
- }
124
- catch (e_3) {
125
- env_3.error = e_3;
126
- env_3.hasError = true;
127
- }
128
- finally {
129
- __disposeResources(env_3);
130
- }
131
- }
132
- export function handleRestartJob(input) {
133
- const env_4 = { stack: [], error: void 0, hasError: false };
134
- try {
135
- const runtime = __addDisposableResource(env_4, new DurableJobRuntime(), false);
136
105
  const current = runtime.get(input);
137
106
  const pending = parseValidationReceiptPendingCheckpoint(current.checkpoint, checkpointLimits());
138
107
  if (!pending && isValidationReceiptPendingIntent(current.checkpoint)) {
139
108
  throw new Error('[Planu] Invalid validation receipt checkpoint');
140
109
  }
141
110
  const job = pending ? runtime.restartReceiptPublication(input) : runtime.restart(input);
142
- if (job.payload &&
143
- typeof job.payload === 'object' &&
144
- job.payload.kind === 'validate') {
111
+ const kind = job.payload && typeof job.payload === 'object'
112
+ ? job.payload.kind
113
+ : undefined;
114
+ if (kind === 'validate') {
145
115
  scheduleValidateJobExecution(job.projectId, job.workspaceId);
146
116
  }
117
+ else if (kind === 'package-handoff') {
118
+ schedulePackageHandoffJobExecution(job.projectId, job.workspaceId);
119
+ }
147
120
  const observation = publicJob(runtime, job);
148
121
  return Promise.resolve(result({ schemaVersion: 1, job: observation, cursor: publicJobCursor(observation) }));
149
122
  }
150
- catch (e_4) {
151
- env_4.error = e_4;
152
- env_4.hasError = true;
123
+ catch (e_2) {
124
+ env_2.error = e_2;
125
+ env_2.hasError = true;
153
126
  }
154
127
  finally {
155
- __disposeResources(env_4);
128
+ __disposeResources(env_2);
156
129
  }
157
130
  }
158
131
  //# sourceMappingURL=handlers.js.map
@@ -156,21 +156,6 @@ export async function handleListSpecs(params) {
156
156
  lastModifiedMap.set(spec.id, formatRelativeDate(spec.updatedAt));
157
157
  }
158
158
  }
159
- // SPEC-091: Auto-suggest Agent Teams when 3+ approved specs exist
160
- const approvedSpecs = allSpecs.filter((s) => s.status === 'approved');
161
- let teamSuggestion = null;
162
- if (approvedSpecs.length >= 3) {
163
- teamSuggestion = {
164
- recommended: true,
165
- reason: `${String(approvedSpecs.length)} approved specs can be implemented in parallel using Agent Teams.`,
166
- templateId: 'parallel-specs',
167
- teamSize: Math.min(approvedSpecs.length, 5),
168
- specs: approvedSpecs.map((s) => s.id),
169
- toolCalls: [
170
- `plan_team_distribution({ projectId: "${projectId}", specIds: [${approvedSpecs.map((s) => `"${s.id}"`).join(', ')}], template: "parallel-specs" })`,
171
- ],
172
- };
173
- }
174
159
  // Build spec data — summary mode returns 5 fields, full mode returns all
175
160
  const specsData = detail === 'summary'
176
161
  ? specs.map((s) => ({
@@ -232,11 +217,15 @@ export async function handleListSpecs(params) {
232
217
  totalReviewHours: Math.round(totalReviewHours * 10) / 10,
233
218
  totalCostUsd: Math.round(totalCostUsd * 100) / 100,
234
219
  },
235
- teamSuggestion,
236
220
  message: ti('tools.list_specs.success', { count: String(specs.length) }),
237
221
  });
238
222
  }
239
- const humanSummary = buildListSpecsSummary(allSpecs.length, statusCounts);
223
+ const filterApplied = Boolean(status) || Boolean(type);
224
+ const humanSummary = filterApplied && specs.length === 0
225
+ ? `No plans match the current filter.`
226
+ : filterApplied
227
+ ? buildListSpecsSummary(specs.length, specs.reduce((acc, s) => ({ ...acc, [s.status]: (acc[s.status] ?? 0) + 1 }), {}))
228
+ : buildListSpecsSummary(allSpecs.length, statusCounts);
240
229
  // SPEC-467: Detect branches and include info for LLM branch-awareness
241
230
  let branchInfo = null;
242
231
  if (detail === 'full' && knowledge.projectPath) {
@@ -317,11 +306,7 @@ export async function handleListSpecs(params) {
317
306
  totalReviewHours: Math.round(totalReviewHours * 10) / 10,
318
307
  totalCostUsd: Math.round(totalCostUsd * 100) / 100,
319
308
  },
320
- teamSuggestion: teamSuggestion ?? null,
321
309
  message: ti('tools.list_specs.success', { count: String(specs.length) }),
322
- teamDistributionHint: approvedSpecs.length >= 3
323
- ? `${String(approvedSpecs.length)} specs approved — run plan_team_distribution for parallel assignment`
324
- : undefined,
325
310
  humanSummary,
326
311
  branchInfo: branchInfo && branchInfo.count > 1 ? branchInfo : undefined,
327
312
  autopilotSummary: collector.hasEntries() ? collector.getMessages() : undefined,
@@ -1,4 +1,5 @@
1
- import type { ToolResult, PackageHandoffInput, HandoffPackage } from '../types/index.js';
2
- export declare function formatHandoff(pkg: HandoffPackage): string;
1
+ import type { ToolResult, PackageHandoffInput } from '../types/index.js';
2
+ export { formatHandoff } from '../engine/handoff-format.js';
3
+ /** Public MCP boundary: submit the handoff job and acknowledge without packaging inline. */
3
4
  export declare function handlePackageHandoff(args: PackageHandoffInput): Promise<ToolResult>;
4
5
  //# sourceMappingURL=package-handoff.d.ts.map