@planu/cli 5.7.4 → 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 (208) hide show
  1. package/CHANGELOG.md +85 -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/registries/legacy-guidance.json +26 -0
  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 +1 -1
  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/lifecycle-gate.js +7 -4
  38. package/dist/engine/evidence-index/index-builder.js +21 -4
  39. package/dist/engine/execution/job-runtime.js +1 -1
  40. package/dist/engine/execution/package-handoff-job-executor.d.ts +22 -0
  41. package/dist/engine/execution/package-handoff-job-executor.js +490 -0
  42. package/dist/engine/execution/validate-job-executor.js +20 -8
  43. package/dist/engine/git/exec-git.d.ts +4 -0
  44. package/dist/engine/git/exec-git.js +14 -0
  45. package/dist/engine/handoff-artifacts/implementation-review-reader.js +15 -2
  46. package/dist/engine/handoff-artifacts/schemas.d.ts +2 -0
  47. package/dist/engine/handoff-artifacts/schemas.js +1 -0
  48. package/dist/engine/handoff-format.d.ts +36 -0
  49. package/dist/engine/handoff-format.js +314 -0
  50. package/dist/engine/handoff-packager.d.ts +5 -3
  51. package/dist/engine/handoff-packager.js +89 -32
  52. package/dist/engine/host-tool-filter.js +20 -49
  53. package/dist/engine/human-summary.js +14 -3
  54. package/dist/engine/implementation-contract/common.d.ts +8 -3
  55. package/dist/engine/implementation-contract/common.js +9 -6
  56. package/dist/engine/implementation-contract/evaluator.js +4 -6
  57. package/dist/engine/implementation-contract/renderer.js +18 -23
  58. package/dist/engine/project-health-checker.js +2 -2
  59. package/dist/engine/readiness-checker.js +27 -0
  60. package/dist/engine/reconcile/apply-changes.js +4 -0
  61. package/dist/engine/reconcile/propagate-mirrors.d.ts +3 -0
  62. package/dist/engine/reconcile/propagate-mirrors.js +311 -0
  63. package/dist/engine/self-healing/healer.js +12 -5
  64. package/dist/engine/self-healing/strategies/lint-fix.d.ts +1 -1
  65. package/dist/engine/self-healing/strategies/lint-fix.js +4 -1
  66. package/dist/engine/self-healing/strategies/test-fix.d.ts +4 -3
  67. package/dist/engine/self-healing/strategies/test-fix.js +32 -14
  68. package/dist/engine/self-healing/strategies/typescript-fix.d.ts +1 -1
  69. package/dist/engine/self-healing/strategies/typescript-fix.js +28 -10
  70. package/dist/engine/session/checkpoint-writer.js +8 -4
  71. package/dist/engine/session/session-tracker.d.ts +5 -16
  72. package/dist/engine/session/session-tracker.js +29 -26
  73. package/dist/engine/session-state/writer.js +3 -11
  74. package/dist/engine/skill-generator/workflow-skill-generator.d.ts +4 -2
  75. package/dist/engine/skill-generator/workflow-skill-generator.js +113 -38
  76. package/dist/engine/spec-format/bdd-parser.d.ts +1 -11
  77. package/dist/engine/spec-format/bdd-parser.js +40 -11
  78. package/dist/engine/spec-format/lean-spec-generator.js +30 -10
  79. package/dist/engine/spec-format/retired-scaffold.d.ts +3 -0
  80. package/dist/engine/spec-format/retired-scaffold.js +5 -0
  81. package/dist/engine/spec-format/technical-md-populator.d.ts +1 -0
  82. package/dist/engine/spec-format/technical-md-populator.js +27 -0
  83. package/dist/engine/spec-format/unified-spec-builder.d.ts +1 -0
  84. package/dist/engine/spec-format/unified-spec-builder.js +30 -20
  85. package/dist/engine/spec-grounding/contract.js +115 -1
  86. package/dist/engine/spec-migrator/fold-technical.js +60 -19
  87. package/dist/engine/spec-migrator/placeholder-technical.d.ts +2 -0
  88. package/dist/engine/spec-migrator/placeholder-technical.js +18 -0
  89. package/dist/engine/spec-quality/generic-output-gate.js +37 -3
  90. package/dist/engine/technical-enricher/index.js +4 -1
  91. package/dist/engine/type-safety-gate.js +3 -11
  92. package/dist/engine/universal-rules/catalog.js +0 -2
  93. package/dist/engine/universal-rules/rules/planu-workflow.js +1 -1
  94. package/dist/engine/validation/durable-validation.d.ts +3 -2
  95. package/dist/engine/validation/durable-validation.js +106 -40
  96. package/dist/engine/validation/validation-freshness.d.ts +3 -2
  97. package/dist/engine/validation/validation-freshness.js +22 -16
  98. package/dist/engine/validation/validation-worktree.js +34 -0
  99. package/dist/hosts/claude-code/ux/mcp-prompts.js +8 -8
  100. package/dist/index.js +3 -17
  101. package/dist/resources/process.js +38 -65
  102. package/dist/storage/session-state-store.js +2 -0
  103. package/dist/tools/challenge-spec/scenarios-utils.js +2 -2
  104. package/dist/tools/configure-checkpoint-policy.js +3 -3
  105. package/dist/tools/create-spec-helpers.js +2 -5
  106. package/dist/tools/create-spec.js +21 -4
  107. package/dist/tools/facilitate.js +3 -6
  108. package/dist/tools/git/branch-ops.js +16 -4
  109. package/dist/tools/github-release-handler.js +1 -20
  110. package/dist/tools/heal-spec-docs.js +1 -13
  111. package/dist/tools/init-project/agents-md-writer.js +6 -6
  112. package/dist/tools/init-project/claude-md-generator.d.ts +0 -1
  113. package/dist/tools/init-project/claude-md-generator.js +0 -35
  114. package/dist/tools/init-project/handler.js +24 -49
  115. package/dist/tools/init-project/legacy-guidance-scanner.d.ts +12 -0
  116. package/dist/tools/init-project/legacy-guidance-scanner.js +176 -0
  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 +21 -1
  120. package/dist/tools/init-project/portable-index-reconciler.js +66 -0
  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/jobs/handlers.d.ts +0 -6
  126. package/dist/tools/jobs/handlers.js +13 -40
  127. package/dist/tools/list-specs.js +6 -21
  128. package/dist/tools/package-handoff.d.ts +3 -2
  129. package/dist/tools/package-handoff.js +153 -427
  130. package/dist/tools/reconcile-session-safeguard-hook.js +22 -15
  131. package/dist/tools/register-sdd-tools.js +0 -23
  132. package/dist/tools/register-spec-tools/core-spec-tools.js +18 -27
  133. package/dist/tools/schemas/index.d.ts +1 -1
  134. package/dist/tools/schemas/index.js +1 -1
  135. package/dist/tools/schemas/output-schemas.d.ts +1 -18
  136. package/dist/tools/schemas/output-schemas.js +1 -11
  137. package/dist/tools/schemas/package-handoff-output-schema.d.ts +40 -0
  138. package/dist/tools/schemas/package-handoff-output-schema.js +68 -0
  139. package/dist/tools/schemas/validate-output-schema.d.ts +1 -2
  140. package/dist/tools/schemas/validate-output-schema.js +3 -2
  141. package/dist/tools/session-checkpoint.js +2 -2
  142. package/dist/tools/skill-registry/index.d.ts +0 -1
  143. package/dist/tools/skill-registry/index.js +0 -1
  144. package/dist/tools/sync-spec-state-handler.d.ts +2 -2
  145. package/dist/tools/sync-spec-state-handler.js +23 -3
  146. package/dist/tools/tool-registry/core-tools.js +1 -140
  147. package/dist/tools/tool-registry/group-infra.js +2 -39
  148. package/dist/tools/tool-registry/group-quality-compliance.js +9 -1
  149. package/dist/tools/update-status/batch.js +17 -0
  150. package/dist/tools/update-status/dod-gates.js +14 -1
  151. package/dist/tools/update-status/done-receipt-verifier.d.ts +22 -0
  152. package/dist/tools/update-status/done-receipt-verifier.js +56 -26
  153. package/dist/tools/update-status/evidence-gate.js +10 -21
  154. package/dist/tools/update-status/file-sync.d.ts +1 -0
  155. package/dist/tools/update-status/file-sync.js +6 -0
  156. package/dist/tools/update-status/index.d.ts +6 -0
  157. package/dist/tools/update-status/index.js +39 -44
  158. package/dist/tools/update-status-actions.js +2 -7
  159. package/dist/tools/validate.js +34 -28
  160. package/dist/transports/oauth-validator.js +12 -1
  161. package/dist/transports/transport-factory.d.ts +2 -1
  162. package/dist/transports/transport-factory.js +19 -0
  163. package/dist/types/common/primitives.d.ts +2 -0
  164. package/dist/types/durable-job.d.ts +45 -0
  165. package/dist/types/durable-validation.d.ts +1 -1
  166. package/dist/types/evidence-autofill.d.ts +13 -1
  167. package/dist/types/handoff-artifacts.d.ts +2 -1
  168. package/dist/types/index.d.ts +1 -0
  169. package/dist/types/index.js +1 -0
  170. package/dist/types/legacy-guidance.d.ts +20 -0
  171. package/dist/types/legacy-guidance.js +3 -0
  172. package/dist/types/readiness.d.ts +8 -1
  173. package/dist/types/reconcile.d.ts +6 -0
  174. package/dist/types/skill-registry.d.ts +26 -1
  175. package/dist/types/spec/core.d.ts +5 -0
  176. package/dist/types/spec/inputs.d.ts +2 -2
  177. package/dist/types/spec-format.d.ts +11 -1
  178. package/dist/types/spec-grounding.d.ts +12 -0
  179. package/dist/types/ssr-migration.d.ts +1 -1
  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
@@ -9,7 +9,6 @@ import { registerDesignStackTools } from './register-platform-tools/design-stack
9
9
  import { registerQualityComplianceGroupTools } from './tool-registry/group-quality-compliance.js';
10
10
  import { registerInfraGroupTools } from './tool-registry/group-infra.js';
11
11
  import { safe } from './safe-handler.js';
12
- import { handleCreateRule } from './create-rule.js';
13
12
  import { handleCreateSkill } from './create-skill.js';
14
13
  import { handleReconcileUniversalRules } from './reconcile-universal-rules.js';
15
14
  import { registerBumpSpecVersionTool } from './bump-spec-version.js';
@@ -43,28 +42,6 @@ function registerOnly(server, names, register) {
43
42
  register(scopedServer);
44
43
  }
45
44
  function registerUniversalRulesTools(s) {
46
- s.registerTool('create_rule', {
47
- description: 'Create a host-aware rule file for a Planu project. For Claude Code, writes to `.claude/rules/{name}.md`. For Codex, inserts a delimited block in `AGENTS.md`. For Gemini, inserts a delimited block in `.gemini/conventions.md`. Use host: "auto" to detect the current host automatically.',
48
- inputSchema: {
49
- projectPath: z
50
- .string()
51
- .describe('Absolute path to the project root where the rule will be written'),
52
- name: z
53
- .string()
54
- .min(1)
55
- .describe('Rule identifier — kebab-case, no extension (e.g. "team-style").'),
56
- content: z.string().min(1).describe('Markdown body of the rule (no frontmatter required)'),
57
- host: z
58
- .enum(['claude-code', 'codex', 'gemini', 'auto'])
59
- .default('auto')
60
- .describe('Target host or auto-detection.'),
61
- overwriteExisting: z
62
- .boolean()
63
- .optional()
64
- .describe('When true, overwrite an existing file with different content.'),
65
- },
66
- annotations: { readOnlyHint: false, destructiveHint: false, title: 'Create Rule' },
67
- }, safe((args) => handleCreateRule(args)));
68
45
  s.registerTool('create_skill', {
69
46
  description: 'Create a host-aware skill for a Planu project. For Claude Code, writes to `.claude/skills/{name}/SKILL.md`. For Codex, inserts a skill block in `AGENTS.md`. For Gemini, writes to `.gemini/skills/{name}.md`. Use host: "auto" to detect the current host automatically.',
70
47
  inputSchema: {
@@ -7,7 +7,6 @@ import { handleSetLocale } from '../set-locale.js';
7
7
  import { handleInitProject } from '../init-project.js';
8
8
  import { handleSetWorkMode } from '../set-work-mode-handler.js';
9
9
  import { handleInitConstitution } from '../init-constitution.js';
10
- import { handleClarifyRequirements } from '../clarify-requirements.js';
11
10
  import { handleCreateSpec } from '../create-spec.js';
12
11
  import { handleListSpecs } from '../list-specs.js';
13
12
  import { handleUpdateStatus } from '../update-status.js';
@@ -159,32 +158,6 @@ export function registerCoreSpecTools(server) {
159
158
  .describe('Manual principles to include'),
160
159
  },
161
160
  }, safeTracked('init_constitution', async (args) => handleInitConstitution(args)));
162
- // 4. clarify_requirements
163
- server.registerTool('clarify_requirements', {
164
- description: t('tools.clarify_requirements.description'),
165
- inputSchema: {
166
- projectId: z.string().max(500).describe('Project ID'),
167
- topic: z.string().max(500).describe('The topic or feature to clarify'),
168
- context: z
169
- .string()
170
- .max(10_000)
171
- .optional()
172
- .describe('Additional context about the requirement'),
173
- maxQuestions: z
174
- .number()
175
- .optional()
176
- .describe('Maximum number of questions to generate (default: 5)'),
177
- sessionId: z
178
- .string()
179
- .max(500)
180
- .optional()
181
- .describe('Existing clarification session to resume with user-confirmed answers.'),
182
- answers: z
183
- .record(z.string(), z.string())
184
- .optional()
185
- .describe('Explicit user-confirmed answers keyed by clarification question ID.'),
186
- },
187
- }, safeTracked('clarify_requirements', async (args) => handleClarifyRequirements(args, server)));
188
161
  // 5. create_spec
189
162
  server.registerTool('create_spec', {
190
163
  description: t('tools.create_spec.description'),
@@ -432,6 +405,24 @@ export function registerCoreSpecTools(server) {
432
405
  .max(10_000)
433
406
  .optional()
434
407
  .describe('Optional notes for each transition.'),
408
+ evidence: z
409
+ .record(z.string(), z.object({
410
+ modelTierUsed: z
411
+ .enum(['max', 'implementation', 'review'])
412
+ .optional()
413
+ .describe('Model tier used for this spec.'),
414
+ modelId: z.string().optional().describe('Model ID used for this spec.'),
415
+ contextHash: z.string().optional().describe('Context hash for this spec.'),
416
+ handoffPath: z.string().optional().describe('Handoff artifact path for this spec.'),
417
+ handoffArtifactId: z
418
+ .string()
419
+ .optional()
420
+ .describe('Handoff artifact ID for this spec.'),
421
+ reviewedBy: z.string().optional().describe('Reviewer identity for this spec.'),
422
+ arbitratedBy: z.string().optional().describe('Arbitrator identity for this spec.'),
423
+ }))
424
+ .optional()
425
+ .describe('Per-spec model-routing evidence keyed by spec ID. Required for status approved or implementing: each entry supplies modelTierUsed, modelId, contextHash and handoffPath for that spec.'),
435
426
  },
436
427
  }, safeTracked('update_status_batch', async (args) => handleUpdateStatusBatch(args)));
437
428
  // 8. estimate
@@ -16,7 +16,7 @@ export { TokenIntelligencePeriodEnum, TokenIntelligenceGroupByEnum, TokenIntelli
16
16
  export { ProjectGraphActionEnum, ProjectGraphQueryKindEnum } from './project-graph.js';
17
17
  export { ConfigureLLMProvidersActionEnum, LoadBalancingStrategyEnum, } from './llm-provider-schemas.js';
18
18
  export { PluginActionEnum } from './plugins-schemas.js';
19
- export { ListSpecsOutputSchema, EstimateOutputSchema, ValidateOutputSchema, CheckReadinessOutputSchema, } from './output-schemas.js';
19
+ export { ListSpecsOutputSchema, EstimateOutputSchema, ValidateOutputSchema, CheckReadinessOutputSchema, PackageHandoffOutputSchema, } from './output-schemas.js';
20
20
  export { CreatePRFromSpecSchema, PRStatusSchema, ReviewPRSchema, CreateReleaseSchema, GenerateChangelogSchema, } from './github.js';
21
21
  export { SkillSearchInputSchema, SkillInstallInputSchema } from './skill-registry-schemas.js';
22
22
  export { EcosystemStatusInputSchema } from './ecosystem-schemas.js';
@@ -17,7 +17,7 @@ export { TokenIntelligencePeriodEnum, TokenIntelligenceGroupByEnum, TokenIntelli
17
17
  export { ProjectGraphActionEnum, ProjectGraphQueryKindEnum } from './project-graph.js';
18
18
  export { ConfigureLLMProvidersActionEnum, LoadBalancingStrategyEnum, } from './llm-provider-schemas.js';
19
19
  export { PluginActionEnum } from './plugins-schemas.js';
20
- export { ListSpecsOutputSchema, EstimateOutputSchema, ValidateOutputSchema, CheckReadinessOutputSchema, } from './output-schemas.js';
20
+ export { ListSpecsOutputSchema, EstimateOutputSchema, ValidateOutputSchema, CheckReadinessOutputSchema, PackageHandoffOutputSchema, } from './output-schemas.js';
21
21
  export { CreatePRFromSpecSchema, PRStatusSchema, ReviewPRSchema, CreateReleaseSchema, GenerateChangelogSchema, } from './github.js';
22
22
  export { SkillSearchInputSchema, SkillInstallInputSchema } from './skill-registry-schemas.js';
23
23
  export { EcosystemStatusInputSchema } from './ecosystem-schemas.js';
@@ -33,16 +33,7 @@ export declare const ListSpecsOutputSchema: {
33
33
  totalReviewHours: z.ZodNumber;
34
34
  totalCostUsd: z.ZodNumber;
35
35
  }, z.core.$strip>;
36
- teamSuggestion: z.ZodNullable<z.ZodObject<{
37
- recommended: z.ZodBoolean;
38
- reason: z.ZodString;
39
- templateId: z.ZodString;
40
- teamSize: z.ZodNumber;
41
- specs: z.ZodArray<z.ZodString>;
42
- toolCalls: z.ZodArray<z.ZodString>;
43
- }, z.core.$strip>>;
44
36
  message: z.ZodString;
45
- teamDistributionHint: z.ZodOptional<z.ZodString>;
46
37
  humanSummary: z.ZodOptional<z.ZodString>;
47
38
  branchInfo: z.ZodOptional<z.ZodObject<{
48
39
  current: z.ZodString;
@@ -126,16 +117,7 @@ export declare const ListSpecsOutputObjectSchema: z.ZodObject<{
126
117
  totalReviewHours: z.ZodNumber;
127
118
  totalCostUsd: z.ZodNumber;
128
119
  }, z.core.$strip>;
129
- teamSuggestion: z.ZodNullable<z.ZodObject<{
130
- recommended: z.ZodBoolean;
131
- reason: z.ZodString;
132
- templateId: z.ZodString;
133
- teamSize: z.ZodNumber;
134
- specs: z.ZodArray<z.ZodString>;
135
- toolCalls: z.ZodArray<z.ZodString>;
136
- }, z.core.$strip>>;
137
120
  message: z.ZodString;
138
- teamDistributionHint: z.ZodOptional<z.ZodString>;
139
121
  humanSummary: z.ZodOptional<z.ZodString>;
140
122
  branchInfo: z.ZodOptional<z.ZodObject<{
141
123
  current: z.ZodString;
@@ -217,6 +199,7 @@ export declare const EstimateOutputSchema: {
217
199
  calibrationApplied: z.ZodOptional<z.ZodNullable<z.ZodString>>;
218
200
  };
219
201
  export { ValidateCompletionOutputSchema, ValidateOutputSchema } from './validate-output-schema.js';
202
+ export { PackageHandoffOutputSchema } from './package-handoff-output-schema.js';
220
203
  export declare const CheckReadinessOutputSchema: {
221
204
  specId: z.ZodString;
222
205
  score: z.ZodNumber;
@@ -39,18 +39,7 @@ export const ListSpecsOutputSchema = {
39
39
  totalReviewHours: z.number(),
40
40
  totalCostUsd: z.number(),
41
41
  }),
42
- teamSuggestion: z
43
- .object({
44
- recommended: z.boolean(),
45
- reason: z.string(),
46
- templateId: z.string(),
47
- teamSize: z.number(),
48
- specs: z.array(z.string()),
49
- toolCalls: z.array(z.string()),
50
- })
51
- .nullable(),
52
42
  message: z.string(),
53
- teamDistributionHint: z.string().optional(),
54
43
  humanSummary: z.string().optional(),
55
44
  branchInfo: z
56
45
  .object({
@@ -142,6 +131,7 @@ export const EstimateOutputSchema = {
142
131
  };
143
132
  // ── validate ────────────────────────────────────────────────────────────────
144
133
  export { ValidateCompletionOutputSchema, ValidateOutputSchema } from './validate-output-schema.js';
134
+ export { PackageHandoffOutputSchema } from './package-handoff-output-schema.js';
145
135
  // ── check_readiness ─────────────────────────────────────────────────────────
146
136
  export const CheckReadinessOutputSchema = {
147
137
  specId: z.string(),
@@ -0,0 +1,40 @@
1
+ import { z } from 'zod';
2
+ /** Exact public structured-output contract for the package_handoff MCP tool submission ack. */
3
+ export declare const PackageHandoffOutputSchema: {
4
+ schemaVersion: z.ZodLiteral<1>;
5
+ operationId: z.ZodString;
6
+ projectId: z.ZodString;
7
+ workspaceId: z.ZodString;
8
+ state: z.ZodEnum<{
9
+ accepted: "accepted";
10
+ cancelled: "cancelled";
11
+ checkpointed: "checkpointed";
12
+ completed: "completed";
13
+ "dead-letter": "dead-letter";
14
+ failed: "failed";
15
+ running: "running";
16
+ }>;
17
+ submittedAt: z.ZodISODateTime;
18
+ attachedAt: z.ZodISODateTime;
19
+ reused: z.ZodBoolean;
20
+ cursor: z.ZodString;
21
+ queue: z.ZodObject<{
22
+ status: z.ZodEnum<{
23
+ active: "active";
24
+ queued: "queued";
25
+ terminal: "terminal";
26
+ }>;
27
+ position: z.ZodNullable<z.ZodNumber>;
28
+ aheadCount: z.ZodNumber;
29
+ capacity: z.ZodNumber;
30
+ remainingBudgetMs: z.ZodNumber;
31
+ }, z.core.$strip>;
32
+ terminalStates: z.ZodTuple<[z.ZodLiteral<"completed">, z.ZodLiteral<"failed">, z.ZodLiteral<"cancelled">, z.ZodLiteral<"dead-letter">], null>;
33
+ resultSchema: z.ZodLiteral<"package-handoff-completion/v1">;
34
+ observation: z.ZodObject<{
35
+ get: z.ZodLiteral<"get_job">;
36
+ restart: z.ZodLiteral<"restart_job">;
37
+ }, z.core.$strip>;
38
+ recoveryAction: z.ZodOptional<z.ZodLiteral<"restart_job">>;
39
+ };
40
+ //# sourceMappingURL=package-handoff-output-schema.d.ts.map
@@ -0,0 +1,68 @@
1
+ import { z } from 'zod';
2
+ /** Exact public structured-output contract for the package_handoff MCP tool submission ack. */
3
+ export const PackageHandoffOutputSchema = {
4
+ schemaVersion: z.literal(1).describe('Ack schema version.'),
5
+ operationId: z
6
+ .string()
7
+ .min(1)
8
+ .max(128)
9
+ .describe('Deterministic durable job id, form handoff-<sha256 hex>.'),
10
+ projectId: z.string().min(1).max(128).describe('Canonical project identity.'),
11
+ workspaceId: z.string().min(1).max(128).describe('Durable job workspace scope.'),
12
+ state: z
13
+ .enum([
14
+ 'accepted',
15
+ 'running',
16
+ 'checkpointed',
17
+ 'completed',
18
+ 'failed',
19
+ 'cancelled',
20
+ 'dead-letter',
21
+ ])
22
+ .describe('Current durable job state at submission or reuse time.'),
23
+ submittedAt: z.iso.datetime().describe('When this job was first accepted.'),
24
+ attachedAt: z.iso.datetime().describe('When this request attached to the job.'),
25
+ reused: z
26
+ .boolean()
27
+ .describe('True when this request attached to an existing job instead of inserting a new one.'),
28
+ cursor: z
29
+ .string()
30
+ .regex(/^[a-f0-9]{64}$/)
31
+ .describe('Content-derived observation cursor.'),
32
+ queue: z.object({
33
+ status: z.enum(['active', 'queued', 'terminal']).describe('Queue lifecycle bucket.'),
34
+ position: z
35
+ .number()
36
+ .int()
37
+ .positive()
38
+ .nullable()
39
+ .describe('1-based queue position, null once terminal.'),
40
+ aheadCount: z
41
+ .number()
42
+ .int()
43
+ .nonnegative()
44
+ .describe('Jobs ahead of this one in the same scope.'),
45
+ capacity: z.number().int().positive().describe('Worker concurrency capacity for this scope.'),
46
+ remainingBudgetMs: z.number().int().nonnegative().describe('Remaining execution budget in ms.'),
47
+ }),
48
+ terminalStates: z
49
+ .tuple([
50
+ z.literal('completed'),
51
+ z.literal('failed'),
52
+ z.literal('cancelled'),
53
+ z.literal('dead-letter'),
54
+ ])
55
+ .describe('The states get_job should treat as terminal.'),
56
+ resultSchema: z
57
+ .literal('package-handoff-completion/v1')
58
+ .describe('Result payload schema id once completed.'),
59
+ observation: z.object({
60
+ get: z.literal('get_job').describe('Tool to poll for job progress and result.'),
61
+ restart: z.literal('restart_job').describe('Tool to reactivate a terminal-failed job.'),
62
+ }),
63
+ recoveryAction: z
64
+ .literal('restart_job')
65
+ .optional()
66
+ .describe('Present when the reused job ended terminal-failed/cancelled/dead-letter and needs restart_job.'),
67
+ };
68
+ //# sourceMappingURL=package-handoff-output-schema.js.map
@@ -252,6 +252,7 @@ export declare const ValidateOutputSchema: {
252
252
  }>;
253
253
  submittedAt: z.ZodISODateTime;
254
254
  attachedAt: z.ZodISODateTime;
255
+ reused: z.ZodBoolean;
255
256
  cursor: z.ZodString;
256
257
  queue: z.ZodObject<{
257
258
  status: z.ZodEnum<{
@@ -268,8 +269,6 @@ export declare const ValidateOutputSchema: {
268
269
  resultSchema: z.ZodLiteral<"validate-completion/v1">;
269
270
  observation: z.ZodObject<{
270
271
  get: z.ZodLiteral<"get_job">;
271
- watch: z.ZodLiteral<"watch_job">;
272
- cancel: z.ZodLiteral<"cancel_job">;
273
272
  restart: z.ZodLiteral<"restart_job">;
274
273
  }, z.core.$strip>;
275
274
  };
@@ -197,6 +197,9 @@ export const ValidateOutputSchema = {
197
197
  state: z.enum(['accepted', 'running', 'checkpointed']),
198
198
  submittedAt: z.iso.datetime(),
199
199
  attachedAt: z.iso.datetime(),
200
+ reused: z
201
+ .boolean()
202
+ .describe('True when this request attached to an already-running validation job instead of dispatching new work.'),
200
203
  cursor: z.string().regex(/^[a-f0-9]{64}$/),
201
204
  queue: z.object({
202
205
  status: z.enum(['active', 'queued', 'terminal']),
@@ -214,8 +217,6 @@ export const ValidateOutputSchema = {
214
217
  resultSchema: z.literal('validate-completion/v1'),
215
218
  observation: z.object({
216
219
  get: z.literal('get_job'),
217
- watch: z.literal('watch_job'),
218
- cancel: z.literal('cancel_job'),
219
220
  restart: z.literal('restart_job'),
220
221
  }),
221
222
  };
@@ -1,5 +1,5 @@
1
1
  // tools/session-checkpoint.ts — Manual trigger for session checkpoint (SPEC-563).
2
- import { sessionTracker } from '../engine/session/session-tracker.js';
2
+ import { getSessionTracker } from '../engine/session/session-tracker.js';
3
3
  import { writeCheckpoint } from '../engine/session/checkpoint-writer.js';
4
4
  import { compactResult } from './output-formatter.js';
5
5
  /**
@@ -7,7 +7,7 @@ import { compactResult } from './output-formatter.js';
7
7
  * Writes a checkpoint immediately regardless of the call-count threshold.
8
8
  */
9
9
  export async function handleSessionCheckpoint(args) {
10
- const snapshot = sessionTracker.getSnapshot();
10
+ const snapshot = getSessionTracker(args.projectPath).getSnapshot();
11
11
  await writeCheckpoint(args.projectPath, snapshot);
12
12
  return compactResult(`Session checkpoint written to ${args.projectPath}/planu/.runtime/session-context.md\n` +
13
13
  `Calls recorded: ${String(snapshot.callCount)}, ` +
@@ -1,3 +1,2 @@
1
- export { handleSkillSearch } from './search.js';
2
1
  export { handleSkillInstall } from './install.js';
3
2
  //# sourceMappingURL=index.d.ts.map
@@ -1,4 +1,3 @@
1
1
  // tools/skill-registry/index.ts — Barrel for skill registry tool handlers (SPEC-150)
2
- export { handleSkillSearch } from './search.js';
3
2
  export { handleSkillInstall } from './install.js';
4
3
  //# sourceMappingURL=index.js.map
@@ -1,10 +1,10 @@
1
1
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import type { SyncReport } from '../types/index.js';
2
+ import type { SyncReport, SyncSpecStateOptions } from '../types/index.js';
3
3
  /**
4
4
  * Sync spec state for a single project.
5
5
  * Reads YAML frontmatter from spec.md files and reconciles divergences into the store.
6
6
  */
7
- export declare function syncSpecState(projectPath: string, projectId: string): Promise<SyncReport>;
7
+ export declare function syncSpecState(projectPath: string, projectId: string, options?: SyncSpecStateOptions): Promise<SyncReport>;
8
8
  /**
9
9
  * Startup sync: iterates all registered projects and calls syncSpecState for each.
10
10
  * Non-blocking — errors are logged but not propagated.
@@ -20,7 +20,8 @@ import { readFile, stat } from 'node:fs/promises';
20
20
  * Sync spec state for a single project.
21
21
  * Reads YAML frontmatter from spec.md files and reconciles divergences into the store.
22
22
  */
23
- export async function syncSpecState(projectPath, projectId) {
23
+ export async function syncSpecState(projectPath, projectId, options = {}) {
24
+ const { applyTransitions = true } = options;
24
25
  let dataEntries;
25
26
  try {
26
27
  const specs = await listSpecs(projectId);
@@ -109,6 +110,14 @@ export async function syncSpecState(projectPath, projectId) {
109
110
  report.synced += 1;
110
111
  continue;
111
112
  }
113
+ if (!applyTransitions) {
114
+ report.rejected.push({ specId, reason: refusalReason });
115
+ const idx = report.divergences.findIndex((d) => d.specId === specId);
116
+ if (idx !== -1) {
117
+ report.divergences.splice(idx, 1);
118
+ }
119
+ continue;
120
+ }
112
121
  try {
113
122
  const result = await handleUpdateStatus({
114
123
  specId,
@@ -205,13 +214,24 @@ export async function startupSync() {
205
214
  }
206
215
  await Promise.all(projects.map(async (project) => {
207
216
  try {
208
- await syncSpecState(project.path, project.hash);
217
+ const report = await syncSpecState(project.path, project.hash, {
218
+ applyTransitions: false,
219
+ });
220
+ if (report.rejected.length > 0) {
221
+ console.error(`[Planu] startupSync: ${project.path} has ${report.rejected.length} spec status divergence(s) reported read-only:`, report.rejected);
222
+ }
209
223
  }
210
224
  catch (err) {
211
225
  console.error(`[Planu] startupSync: failed to sync project ${project.path}:`, err);
212
226
  }
213
227
  try {
214
- await cleanEphemeralArtifacts({ projectPath: project.path, dryRun: false });
228
+ const cleanupResult = await cleanEphemeralArtifacts({
229
+ projectPath: project.path,
230
+ dryRun: true,
231
+ });
232
+ if (cleanupResult.wouldDelete.length > 0) {
233
+ console.error(`[Planu] startupSync: ${project.path} has ${cleanupResult.wouldDelete.length} ephemeral artifact(s) that would be deleted (run housekeeping-sweep to apply):`, cleanupResult.wouldDelete);
234
+ }
215
235
  }
216
236
  catch (err) {
217
237
  console.error(`[Planu] startupSync: failed to clean spec artifacts ${project.path}:`, err);
@@ -38,14 +38,13 @@ import { handleIdeConfig } from '../ide-config-handler.js';
38
38
  import { IdeTargetEnum, IdeConfigScopeEnum } from '../schemas/ide-config.js';
39
39
  import { handleReconcileSpecLiving } from '../reconcile-spec-living-handler.js';
40
40
  import { handleSecurityReport } from '../security-report-handler.js';
41
- import { handleFeedbackStatus, handleResolveFeedback, handleSubmitFeedback, handleSyncFeedback, handleTriageFeedback, } from '../feedback-handler.js';
42
41
  import { handleDogfoodWatch } from '../dogfood-watch.js';
43
42
  import { SecurityReportTimeRangeEnum, SecurityReportFormatEnum, } from '../schemas/runtime-security.js';
44
43
  import { RenderSpecForProviderInputSchema, handleRenderSpecForProvider, } from '../render-spec-for-provider.js';
45
44
  import { handleTriageRequest, TriageRequestInputSchema } from '../triage-request.js';
46
45
  import { handleStoragePaths } from '../storage-paths-handler.js';
47
46
  import { handleStorageExport, handleStorageImport } from '../storage-bundle-handler.js';
48
- import { handleCancelJob, handleGetJob, handleRestartJob, handleWatchJob, } from '../jobs/handlers.js';
47
+ import { handleGetJob, handleRestartJob } from '../jobs/handlers.js';
49
48
  // ── Registry ─────────────────────────────────────────────────────────────────
50
49
  const coreToolsRegistry = [
51
50
  {
@@ -81,48 +80,6 @@ const coreToolsRegistry = [
81
80
  wrap: 'safe',
82
81
  group: 'infrastructure',
83
82
  },
84
- {
85
- name: 'watch_job',
86
- description: 'Wait up to 30 seconds for a durable Planu job to change or reach a terminal state.',
87
- schema: {
88
- operationId: z.string().trim().min(1).max(128),
89
- projectId: z.string().trim().min(1).max(128),
90
- workspaceId: z.string().trim().min(1).max(128).optional(),
91
- afterCursor: z
92
- .string()
93
- .regex(/^[a-f0-9]{64}$/)
94
- .optional(),
95
- timeoutMs: z.number().int().min(0).max(30_000).optional(),
96
- },
97
- handler: handleWatchJob,
98
- annotations: {
99
- title: 'Watch Durable Job',
100
- readOnlyHint: true,
101
- destructiveHint: false,
102
- openWorldHint: false,
103
- },
104
- wrap: 'safe',
105
- group: 'infrastructure',
106
- },
107
- {
108
- name: 'cancel_job',
109
- description: 'Durably cancel a Planu job and fence any worker that still holds its former lease.',
110
- schema: {
111
- operationId: z.string().trim().min(1).max(128),
112
- projectId: z.string().trim().min(1).max(128),
113
- workspaceId: z.string().trim().min(1).max(128).optional(),
114
- },
115
- handler: handleCancelJob,
116
- annotations: {
117
- title: 'Cancel Durable Job',
118
- readOnlyHint: false,
119
- destructiveHint: true,
120
- idempotentHint: true,
121
- openWorldHint: false,
122
- },
123
- wrap: 'safe',
124
- group: 'infrastructure',
125
- },
126
83
  {
127
84
  name: 'restart_job',
128
85
  description: 'Restart a cancelled or failed durable job and schedule its typed executor.',
@@ -899,102 +856,6 @@ const coreToolsRegistry = [
899
856
  wrap: 'tracked',
900
857
  group: 'core',
901
858
  },
902
- // ── feedback hub (SPEC-188, SPEC-1100) ───────────────────────────────────
903
- {
904
- name: 'submit_feedback',
905
- description: 'Submit user feedback or a bug report to Planu Feedback Hub. Always persists locally first, then attempts privacy-bounded remote registration with the central feedback intake.',
906
- schema: {
907
- type: z
908
- .enum(['bug', 'feature', 'suggestion', 'dx'])
909
- .describe('Feedback type: bug | feature | suggestion | dx'),
910
- title: z.string().min(1).max(200).describe('Short feedback title'),
911
- description: z.string().min(1).max(5000).describe('Detailed feedback description'),
912
- context: z
913
- .object({
914
- projectPath: z.string().max(4096).optional(),
915
- currentFile: z.string().max(4096).optional(),
916
- errorMessage: z.string().max(2000).optional(),
917
- stack: z.string().max(8000).optional(),
918
- })
919
- .optional()
920
- .describe('Optional local-only context; sensitive path fields are not sent remotely.'),
921
- },
922
- handler: async (args) => handleSubmitFeedback(args),
923
- annotations: {
924
- title: 'Submit Feedback',
925
- readOnlyHint: false,
926
- destructiveHint: false,
927
- openWorldHint: true,
928
- },
929
- wrap: 'tracked',
930
- group: 'feedback',
931
- },
932
- {
933
- name: 'triage_feedback',
934
- description: 'Group pending local feedback by similarity so maintainers can decide whether to create specs, merge duplicates, or dismiss items.',
935
- schema: {
936
- filter: z
937
- .enum(['bug', 'feature', 'suggestion', 'dx'])
938
- .optional()
939
- .describe('Optional feedback type filter'),
940
- },
941
- handler: async (args) => Promise.resolve(handleTriageFeedback(args)),
942
- annotations: { title: 'Triage Feedback', readOnlyHint: true },
943
- wrap: 'tracked',
944
- group: 'feedback',
945
- },
946
- {
947
- name: 'resolve_feedback',
948
- description: 'Mark a local feedback item as resolved and optionally link it to a Planu spec, PR URL, and resolution notes.',
949
- schema: {
950
- feedbackId: z.string().min(1).max(50).describe('Local feedback ID, e.g. FB-001'),
951
- specId: z.string().max(50).optional().describe('Optional linked Planu spec ID'),
952
- prUrl: z.url().optional().describe('Optional pull request URL'),
953
- notes: z.string().max(2000).optional().describe('Optional resolution notes'),
954
- },
955
- handler: async (args) => handleResolveFeedback(args),
956
- annotations: { title: 'Resolve Feedback', readOnlyHint: false, destructiveHint: false },
957
- wrap: 'tracked',
958
- group: 'feedback',
959
- },
960
- {
961
- name: 'sync_feedback',
962
- description: 'Retry remote Supabase registration for local feedback entries whose delivery is pending or failed. Does not accept remote row IDs or perform direct SQL/Data API writes.',
963
- schema: {
964
- projectPath: z.string().max(4096).optional().describe('Absolute path to project root'),
965
- includeSynced: z
966
- .boolean()
967
- .optional()
968
- .describe('When true, also reprocess entries already marked synced. Default false.'),
969
- limit: z
970
- .number()
971
- .int()
972
- .positive()
973
- .max(500)
974
- .optional()
975
- .describe('Maximum number of local entries to process.'),
976
- },
977
- handler: async (args) => handleSyncFeedback(args),
978
- annotations: {
979
- title: 'Sync Feedback',
980
- readOnlyHint: false,
981
- destructiveHint: false,
982
- openWorldHint: true,
983
- },
984
- wrap: 'tracked',
985
- group: 'feedback',
986
- },
987
- {
988
- name: 'feedback_status',
989
- description: 'Show aggregate local feedback totals and remote delivery health without exposing descriptions, file paths, user identifiers, or secrets.',
990
- schema: {
991
- projectPath: z.string().max(4096).optional().describe('Absolute path to project root'),
992
- },
993
- handler: async (args) => Promise.resolve(handleFeedbackStatus(args)),
994
- annotations: { title: 'Feedback Status', readOnlyHint: true },
995
- wrap: 'tracked',
996
- group: 'feedback',
997
- },
998
859
  {
999
860
  name: 'dogfood_watch',
1000
861
  description: 'Analyze recent local Planu runtime evidence and surface actionable dogfooding gaps such as repeated tool failures, persisted version drift, guard fallback leakage, and stale local compatibility mirrors.',