@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
package/CHANGELOG.md CHANGED
@@ -1,3 +1,88 @@
1
+ ## [5.7.6] - 2026-09-01
2
+
3
+ ### Features
4
+ - feat(skills): refresh first-party workflow skills on re-init with content-bound markers
5
+
6
+ ### Bug Fixes
7
+ - fix(pre-push): replace process substitution with POSIX-portable loops in select-tests
8
+ - fix(pre-push): fully fragment cli-spawn literal to stop test self-match
9
+ - fix(pre-push): route unmapped tests/ helpers and src JSON to referencing suites
10
+ - fix(types): break spec-format circular import with shared ModelTierUsed primitive
11
+ - fix(skills): validate legacy marker hash, always emit skill-sync counts, tighten tests
12
+ - fix(reconcile-spec): correct mirror propagation gaps found in review
13
+ - fix(reconcile-spec): propagate section rewrites to frontmatter and contract mirrors
14
+ - fix(validation): check payloads before writing provenance sidecars
15
+ - fix(validation): skip provenance sidecars for absent evidence artifacts and refuse sentinel rebinds
16
+ - fix(hooks): pass mirror test paths to vitest without the bare separator
17
+ - fix(evidence-gates): repair legacy traceability matrices missing evidence fields
18
+ - fix(spec-quality): bound trailing H3 subsection at the next H2 heading
19
+ - fix(spec-format): close 3 review blockers in SPEC-1435 filler retirement
20
+ - fix(spec-format): retire constant filler from renderer and gate the retired vocabulary
21
+ - fix(list-specs): describe zero filtered matches instead of the global empty state
22
+ - fix(list-specs): align in-progress counts between humanSummary and byStatus
23
+ - fix(package-handoff): satisfy reliability gate in stage deadline catch
24
+ - fix(package-handoff): close 6 review blockers in durable executor
25
+ - fix(package-handoff): make handoff durable, timeout-safe and observable
26
+ - fix(tools): purge remaining phantom tool references from SPEC-1721 emitters
27
+ - fix: correct coverage-exclude parser and dedupe pathExists
28
+ - fix(validate): classify non-ENOENT stale-prefix probe failures as degradation
29
+ - fix(validate): self-heal stale worktree specPath and classify VALIDATION_STALE_SPEC_PATH
30
+ - fix(update-status): realign store on done-freeze drift without rewriting frozen spec files
31
+ - fix(pre-push): location-first classification, copy-record parsing, and truncated-stream fail-closed
32
+ - fix(pre-push): NUL-safe test selection with bounded scripts lane and fail-closed classification
33
+ - fix(git-ops): real-repo handler tests and routed test spawners after implementation review
34
+ - fix(git-ops): expose structured branch results instead of parsing rendered markdown
35
+ - fix(release): drop detached develop-to-main auto-merge for instructions-only mirror sync
36
+ - fix(update-status): batch accepts per-spec model-routing evidence for guarded statuses
37
+ - fix(validate): report restart timestamps and shape hints for missing evidence artifacts
38
+ - fix(review-gates): enforce implementation-review independence fail-closed via reviewer sessionId (SPEC-1576)
39
+ - fix(session-safeguard): honour session opt-out, refuse no-upstream branches, and run the pre-push gate
40
+ - fix(self-healing): bound shell executions with timeouts and lockfile package-manager detection
41
+ - fix(transports): refuse unauthenticated non-loopback HTTP and make api-key compare timing-safe
42
+ - fix(engines): lower Node engines floor to verified LTS >=22.13.0
43
+ - fix(release): abort clears the ledger when HEAD is already at the release base
44
+ - fix(release): refuse abort when untracked work occupies a restore path and harden abort tests
45
+ - fix(release): abort preserves uncommitted work or refuses on bump-owned overlap for SPEC-1398
46
+ - fix(session,enricher): per-project checkpoint trackers and preview-only review enrichment for SPEC-1409
47
+ - fix(startup): harden keybindings call-site assertion and strip narrative test comments (SPEC-1402 review)
48
+ - fix(startup): make MCP startup read-only for user-owned state (SPEC-1402)
49
+ - fix(spec-format): admit plus-bullet marker in single-line criterion regex
50
+ - fix(challenge-spec): drop bare load token from scale capability signal
51
+ - fix(ambiguity-scorer): preserve token boundaries and word count in literal-span masking
52
+ - fix(ambiguity-scorer): exempt quoted and backticked literal spans from vague-unit matching
53
+ - fix(spec-format): address SPEC-1439 review blockers
54
+ - fix(spec-format): stop persisting frontmatter scenarios scavenged from prose
55
+ - fix(spec-grounding): tighten YAML fallback signaling and per-section scoping
56
+ - fix(spec-grounding): parse grounding frontmatter with YAML parser and legacy regex fallback
57
+ - fix(spec-format): anchor inline TEST markers to their own scenario in bdd frontmatter
58
+ - fix(evidence-index): resolve line-citation suffixes via literal-first stat fallback in pathRecord
59
+ - fix(validation): visible reuse marker and discriminated freshness-barrier rejections (SPEC-1494)
60
+ - fix(update-status): actionable stale-bindings rejection and AC2 next-action assertion (SPEC-1372)
61
+ - fix(update-status): harden autofill classifier and receipt rebind fallback
62
+ - fix(update-status): rebind autofilled traceability and regenerate stale matrices (SPEC-1372)
63
+ - fix(package-handoff): gate ownership fallback on the whole bullet, name exact reason codes
64
+ - fix(package-handoff): accept prose ownership descriptions and name rejected paths in blockers
65
+
66
+ ### Refactoring
67
+ - refactor(tools): purge MCP surface to the 19-tool value core (SPEC-1721)
68
+
69
+ ### Chores
70
+ - chore(website): refresh product proof
71
+ - chore(planu): SPEC-1597 implementing checkpoint
72
+ - chore(planu): SPEC-1439 implementing checkpoint
73
+ - chore(planu): SPEC-1452 implementing checkpoint
74
+
75
+
76
+ ## [5.7.5] - 2026-08-31
77
+
78
+ ### Bug Fixes
79
+ - fix(init-project): address implementation review blockers for SPEC-1716
80
+ - fix(init-project): neutralize stale legacy guidance and fold divergent technical.md residuals
81
+
82
+ ### Chores
83
+ - chore(planu): discard 29 triaged drafts and record SPEC-1716 cycle state
84
+
85
+
1
86
  ## [5.7.4] - 2026-08-31
2
87
 
3
88
  ### Bug Fixes
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  **The high-performance SDD stack for AI coding agents.**
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@planu/cli?color=blue&label=npm)](https://www.npmjs.com/package/@planu/cli)
6
- ![Node](https://img.shields.io/badge/node-%3E%3D24.0.0-green)
6
+ ![Node](https://img.shields.io/badge/node-%3E%3D22.13.0-green)
7
7
  ![Rust](https://img.shields.io/badge/core-rust-orange)
8
8
  ![License](https://img.shields.io/badge/license-proprietary-blue)
9
9
 
@@ -21,7 +21,7 @@ Planu is a Spec Driven Development stack for AI coding agents: an MCP server and
21
21
  - **Local change detection** — observes project changes without requiring a hosted configuration service.
22
22
  - **Unified Spec Format** — Requirements and technical details in a single, context-efficient `spec.md`.
23
23
  - **Atomic Integrity** — Indestructible writes and **Freeze-on-done** immutability (P0).
24
- - **32 official MCP tools** for the public SDD surface, with advanced workflows kept in skills, CLI commands, and internal pipelines.
24
+ - **19 official MCP tools** for the public SDD surface, with advanced workflows kept in skills, CLI commands, and internal pipelines.
25
25
  - **Multi-agent compatible** — Optimized for Claude Code, Cursor, Windsurf, and Gemini CLI.
26
26
 
27
27
  ---
@@ -41,7 +41,7 @@ Add to your MCP client config (Claude Desktop: `~/Library/Application Support/Cl
41
41
  }
42
42
  ```
43
43
 
44
- **Requirements:** Node.js >= 24. The native Rust core is bundled and auto-detected for macOS (Intel/M1), Linux, and Windows.
44
+ **Requirements:** Node.js >= 22.13. The native Rust core is bundled and auto-detected for macOS (Intel/M1), Linux, and Windows.
45
45
 
46
46
  **Upgrade safety:** stop every running Planu process before upgrading. Current releases use a single transactional SQLite lock authority with monotonic fencing; concurrent mixed-version execution is intentionally unsupported because older file-lock clients cannot participate in the same atomic protocol.
47
47
 
@@ -1 +1 @@
1
- {"schemaVersion":1,"commit":"bae55ef85d50f56c6406a9a52291bdff9fcca4e3"}
1
+ {"schemaVersion":1,"commit":"1eaa28a4fbc0df47b8b62c888bbb34446c05810e"}
@@ -1,10 +1,25 @@
1
- // cli/commands/package-handoff.ts — planu package-handoff <specId> (SPEC-1621)
1
+ // cli/commands/package-handoff.ts — planu package-handoff <specId> (SPEC-1621, durable poll SPEC-1240)
2
2
  import { parseArgs } from 'node:util';
3
3
  import { resolve } from 'node:path';
4
4
  import { handlePackageHandoff } from '../../tools/package-handoff.js';
5
+ import { handleGetJob } from '../../tools/jobs/handlers.js';
5
6
  import { formatToolResult } from '../formatter.js';
6
7
  import { detectProjectId } from '../project-detector.js';
7
8
  import { red } from '../colors.js';
9
+ const TERMINAL_STATES = new Set(['completed', 'failed', 'cancelled', 'dead-letter']);
10
+ const POLL_INTERVAL_MS = 250;
11
+ const POLL_BUDGET_MS = 60_000;
12
+ async function pollToTerminal(operationId, projectId, workspaceId) {
13
+ const deadlineAt = Date.now() + POLL_BUDGET_MS;
14
+ for (;;) {
15
+ const jobResult = await handleGetJob({ operationId, projectId, workspaceId });
16
+ const job = jobResult.structuredContent.job;
17
+ if (TERMINAL_STATES.has(job.state) || Date.now() >= deadlineAt) {
18
+ return job;
19
+ }
20
+ await new Promise((res) => setTimeout(res, POLL_INTERVAL_MS));
21
+ }
22
+ }
8
23
  export const packageHandoffCommand = {
9
24
  name: 'package-handoff',
10
25
  description: 'Generate the operational handoff package artifact for a spec',
@@ -28,13 +43,23 @@ export const packageHandoffCommand = {
28
43
  const projectPath = values['project-path'];
29
44
  const projectId = values['project-id'] ??
30
45
  detectProjectId(projectPath ? resolve(projectPath) : undefined);
31
- const result = await handlePackageHandoff({ projectId, specId });
32
- if (result.isError) {
33
- process.stderr.write(`${red(formatToolResult(result, flags))}\n`);
46
+ const submission = await handlePackageHandoff({ projectId, specId });
47
+ if (submission.isError) {
48
+ process.stderr.write(`${red(formatToolResult(submission, flags))}\n`);
49
+ process.exitCode = 1;
50
+ return;
51
+ }
52
+ const ack = submission.structuredContent;
53
+ const job = await pollToTerminal(ack.operationId, projectId, ack.workspaceId);
54
+ if (job.state !== 'completed') {
55
+ const hint = ack.recoveryAction
56
+ ? ' Run restart_job (or resubmit) to retry.'
57
+ : ' Run get_job to inspect the failure, or resubmit.';
58
+ process.stderr.write(`${red(`Handoff job ${ack.operationId} ended as ${job.state}.`)}${job.error ? ` ${job.error}` : ''}${hint}\n`);
34
59
  process.exitCode = 1;
35
60
  return;
36
61
  }
37
- const output = formatToolResult(result, flags);
62
+ const output = formatToolResult(job.result, flags);
38
63
  if (output) {
39
64
  process.stdout.write(output + '\n');
40
65
  }
@@ -12,7 +12,18 @@
12
12
  ]
13
13
  },
14
14
  "hipaa": {
15
- "keywords": ["health", "medical", "patient", "phi", "ehr", "clinical", "diagnosis", "treatment", "hipaa", "healthcare"],
15
+ "keywords": [
16
+ "health",
17
+ "medical",
18
+ "patient",
19
+ "phi",
20
+ "ehr",
21
+ "clinical",
22
+ "diagnosis",
23
+ "treatment",
24
+ "hipaa",
25
+ "healthcare"
26
+ ],
16
27
  "criteria": [
17
28
  "Protected Health Information (PHI) is encrypted at rest using AES-256 or equivalent",
18
29
  "PHI transmission is secured with TLS 1.2+ encryption",
@@ -24,7 +35,19 @@
24
35
  ]
25
36
  },
26
37
  "pci-dss": {
27
- "keywords": ["payment", "card", "credit", "debit", "checkout", "billing", "stripe", "transaction", "pci", "cvv", "pan"],
38
+ "keywords": [
39
+ "payment",
40
+ "card",
41
+ "credit",
42
+ "debit",
43
+ "checkout",
44
+ "billing",
45
+ "stripe",
46
+ "transaction",
47
+ "pci",
48
+ "cvv",
49
+ "pan"
50
+ ],
28
51
  "criteria": [
29
52
  "Cardholder data (PAN, CVV) is never stored in plaintext",
30
53
  "Payment card data is masked in logs and UI displays",
@@ -36,7 +59,17 @@
36
59
  ]
37
60
  },
38
61
  "soc2": {
39
- "keywords": ["security", "availability", "confidentiality", "integrity", "audit", "compliance", "soc2", "soc 2", "trust"],
62
+ "keywords": [
63
+ "security",
64
+ "availability",
65
+ "confidentiality",
66
+ "integrity",
67
+ "audit",
68
+ "compliance",
69
+ "soc2",
70
+ "soc 2",
71
+ "trust"
72
+ ],
40
73
  "criteria": [
41
74
  "Access control policy is documented and enforced with least-privilege principle",
42
75
  "System availability is monitored with defined SLA targets and incident response",
@@ -85,6 +85,20 @@
85
85
  "sensitivity": "private",
86
86
  "default": null
87
87
  },
88
+ {
89
+ "name": "PLANU_HANDOFF_CORE_BUDGET_MS",
90
+ "type": "number",
91
+ "scope": "runtime",
92
+ "sensitivity": "public",
93
+ "default": null
94
+ },
95
+ {
96
+ "name": "PLANU_HANDOFF_ENRICHMENT_BUDGET_MS",
97
+ "type": "number",
98
+ "scope": "runtime",
99
+ "sensitivity": "public",
100
+ "default": null
101
+ },
88
102
  {
89
103
  "name": "PLANU_HOST",
90
104
  "type": "string",
@@ -141,6 +155,13 @@
141
155
  "sensitivity": "private",
142
156
  "default": null
143
157
  },
158
+ {
159
+ "name": "PLANU_PRE_PUSH_SCRIPTS_LANE",
160
+ "type": "boolean",
161
+ "scope": "test",
162
+ "sensitivity": "public",
163
+ "default": null
164
+ },
144
165
  {
145
166
  "name": "PLANU_PROJECT_DATA_DIR",
146
167
  "type": "string",
@@ -6,21 +6,28 @@ mkdir -p "$(dirname "$log")"
6
6
  {
7
7
  echo "[$(date -u +%FT%TZ)] PreCompaction safeguard fired"
8
8
  cd "${CLAUDE_PROJECT_DIR:-.}" || exit 0
9
- current=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "")
10
- case "$current" in
11
- ""|HEAD|main|master|develop|release|production)
12
- # SPEC-1379: never autopush protected branches mirrors PROTECTED_BRANCHES
13
- # in src/engine/session-safeguard/autopush.ts. --no-verify below is safe
14
- # ONLY because of this guard; remove one, remove both.
15
- echo "skip: protected or detached ($current)"
16
- ;;
17
- *)
18
- # No --force: the remote rejects any non-fast-forward push, so this can
19
- # never overwrite remote history. --end-of-options hardens against
20
- # refnames that start with a dash.
21
- git push --no-verify --end-of-options origin "$current" 2>&1 || echo "push failed or nothing to push"
22
- ;;
23
- esac
9
+ if [ -n "${PLANU_NO_AUTOPUSH:-}" ] || [ -f "${CLAUDE_PROJECT_DIR:-.}/.claude/no-autopush" ]; then
10
+ echo "skip: autopush opt-out active"
11
+ else
12
+ current=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "")
13
+ case "$current" in
14
+ ""|HEAD|main|master|develop|release|production)
15
+ # SPEC-1379: never autopush protected branches mirrors PROTECTED_BRANCHES
16
+ # in src/engine/session-safeguard/autopush.ts.
17
+ echo "skip: protected or detached ($current)"
18
+ ;;
19
+ *)
20
+ if git rev-parse --verify --quiet "refs/remotes/origin/$current" >/dev/null; then
21
+ # No --force: the remote rejects any non-fast-forward push, so this can
22
+ # never overwrite remote history. --end-of-options hardens against
23
+ # refnames that start with a dash.
24
+ git push --end-of-options origin "$current" 2>&1 || echo "push failed or nothing to push"
25
+ else
26
+ echo "skip: no upstream for $current (no-upstream)"
27
+ fi
28
+ ;;
29
+ esac
30
+ fi
24
31
  } >> "$log" 2>&1
25
32
 
26
33
  exit 0
@@ -1,4 +1,4 @@
1
1
  /** Single editable authority for the official local SDD tool surface. */
2
- export declare const OFFICIAL_SDD_TOOL_NAMES: readonly ['planu_status', 'session_checkpoint', 'facilitate', 'init_project', 'clarify_requirements', 'create_spec', 'list_specs', 'challenge_spec', 'check_readiness', 'update_status', 'update_status_batch', 'request_changes', 'estimate', 'package_handoff', 'validate', 'get_job', 'watch_job', 'cancel_job', 'restart_job', 'reconcile_spec', 'create_rule', 'create_skill', 'skill_search', 'configure_code_graph', 'code_graph_status', 'submit_feedback', 'triage_feedback', 'resolve_feedback', 'sync_feedback', 'feedback_status', 'bump_spec_version', 'migrate_legacy_spec'];
2
+ export declare const OFFICIAL_SDD_TOOL_NAMES: readonly ['init_project', 'facilitate', 'create_spec', 'list_specs', 'update_status', 'update_status_batch', 'validate', 'challenge_spec', 'check_readiness', 'bump_spec_version', 'reconcile_spec', 'migrate_legacy_spec', 'package_handoff', 'planu_status', 'session_checkpoint', 'estimate', 'request_changes', 'get_job', 'restart_job'];
3
3
  export declare function readCanonicalToolNames(): string[];
4
4
  //# sourceMappingURL=official-sdd-tools.d.ts.map
@@ -1,37 +1,24 @@
1
1
  /** Single editable authority for the official local SDD tool surface. */
2
2
  export const OFFICIAL_SDD_TOOL_NAMES = [
3
- 'planu_status',
4
- 'session_checkpoint',
5
- 'facilitate',
6
3
  'init_project',
7
- 'clarify_requirements',
4
+ 'facilitate',
8
5
  'create_spec',
9
6
  'list_specs',
10
- 'challenge_spec',
11
- 'check_readiness',
12
7
  'update_status',
13
8
  'update_status_batch',
14
- 'request_changes',
15
- 'estimate',
16
- 'package_handoff',
17
9
  'validate',
18
- 'get_job',
19
- 'watch_job',
20
- 'cancel_job',
21
- 'restart_job',
22
- 'reconcile_spec',
23
- 'create_rule',
24
- 'create_skill',
25
- 'skill_search',
26
- 'configure_code_graph',
27
- 'code_graph_status',
28
- 'submit_feedback',
29
- 'triage_feedback',
30
- 'resolve_feedback',
31
- 'sync_feedback',
32
- 'feedback_status',
10
+ 'challenge_spec',
11
+ 'check_readiness',
33
12
  'bump_spec_version',
13
+ 'reconcile_spec',
34
14
  'migrate_legacy_spec',
15
+ 'package_handoff',
16
+ 'planu_status',
17
+ 'session_checkpoint',
18
+ 'estimate',
19
+ 'request_changes',
20
+ 'get_job',
21
+ 'restart_job',
35
22
  ];
36
23
  export function readCanonicalToolNames() {
37
24
  return [...OFFICIAL_SDD_TOOL_NAMES];
@@ -3,42 +3,26 @@
3
3
  "name": "Codex",
4
4
  "capabilities": { "interactiveUI": false, "askUserQuestion": false, "freeTier": false, "mcpFull": true },
5
5
  "supportedTools": [
6
- "planu_status",
7
- "session_checkpoint",
8
- "facilitate",
9
6
  "init_project",
10
- "clarify_requirements",
7
+ "facilitate",
11
8
  "create_spec",
12
9
  "list_specs",
13
- "challenge_spec",
14
- "check_readiness",
15
10
  "update_status",
16
11
  "update_status_batch",
17
- "request_changes",
18
- "estimate",
19
- "package_handoff",
20
12
  "validate",
21
- "get_job",
22
- "watch_job",
23
- "cancel_job",
24
- "restart_job",
25
- "reconcile_spec",
26
- "create_rule",
27
- "create_skill",
28
- "skill_search",
29
- "configure_code_graph",
30
- "code_graph_status",
31
- "submit_feedback",
32
- "triage_feedback",
33
- "resolve_feedback",
34
- "sync_feedback",
35
- "feedback_status",
13
+ "challenge_spec",
14
+ "check_readiness",
36
15
  "bump_spec_version",
37
- "migrate_legacy_spec"
16
+ "reconcile_spec",
17
+ "migrate_legacy_spec",
18
+ "package_handoff",
19
+ "planu_status",
20
+ "session_checkpoint",
21
+ "estimate",
22
+ "request_changes",
23
+ "get_job",
24
+ "restart_job"
38
25
  ],
39
- "unsupportedTools": ["challenge_spec", "red_team"],
40
- "restrictedTools": {
41
- "challenge_spec": "Requires interactive UI — use planu_facilitate instead",
42
- "approve_spec": "Requires reviewer token — use planu_facilitate instead"
43
- }
26
+ "unsupportedTools": [],
27
+ "restrictedTools": {}
44
28
  }
@@ -9,12 +9,7 @@
9
9
  "planMode": true,
10
10
  "nativeHooks": true
11
11
  },
12
- "workspaceMarkers": [
13
- "opencode.json",
14
- ".opencode/",
15
- "~/.opencode/",
16
- "OPENCODE_HOME"
17
- ],
12
+ "workspaceMarkers": ["opencode.json", ".opencode/", "~/.opencode/", "OPENCODE_HOME"],
18
13
  "supportedTools": [
19
14
  "list_specs",
20
15
  "validate",
@@ -0,0 +1,26 @@
1
+ {
2
+ "hostSurfaceFiles": [
3
+ "CLAUDE.md",
4
+ "AGENTS.md",
5
+ ".cursorrules",
6
+ ".windsurfrules",
7
+ ".github/copilot-instructions.md",
8
+ ".clinerules",
9
+ ".cursor/rules/planu.mdc",
10
+ ".agents/skills/planu-sdd.md"
11
+ ],
12
+ "hostSurfaceDirectories": [{ "dir": ".claude/rules", "extension": ".md" }],
13
+ "legacyFilenameAllowlist": [
14
+ ".claude/rules/sdd-planu.md",
15
+ ".claude/rules/planu-workflow.md",
16
+ ".cursor/rules/planu.mdc",
17
+ ".agents/skills/planu-sdd.md"
18
+ ],
19
+ "managedByMarkers": ["Auto-generated by Planu", "Auto-generated by `init_project`", "managed-by: planu"],
20
+ "contradictoryPhrases": [
21
+ "spec.md + technical.md + progress.md",
22
+ "technical.md — architecture",
23
+ "keep technical.md and progress.md"
24
+ ],
25
+ "replacementGuidance": "Specs live in `planu/specs/SPEC-XXX-slug/spec.md`. Technical planning, file ownership, and progress live inline in `## Technical`, `## Files`, and `## Progress` sections. Do not create standalone technical.md or progress.md files."
26
+ }
@@ -87,27 +87,6 @@ export const SERVER_INSTRUCTIONS = [
87
87
  '- When creating multiple specs at once, present ALL specs for review and let the user approve/reject each one individually.',
88
88
  '- The reviewNotes field stores a history of all feedback — implementers can see what was requested and why.',
89
89
  '',
90
- 'SKILL DISCOVERY — proactive search, mandatory in these situations:',
91
- '1. AFTER init_project: call skill_search for EACH technology in the detected stack.',
92
- ' - Use the actual detected values: language, framework, database, key stack entries.',
93
- ' - Works for ANY stack: Python, Go, Rust, Java, Ruby, PHP, .NET — not just JavaScript.',
94
- ' - Example: stack has [Django, PostgreSQL, Celery] → call skill_search("django"), skill_search("postgresql").',
95
- ' - Example: stack has [Next.js, Tailwind, Prisma] → call skill_search("nextjs"), skill_search("prisma").',
96
- ' - Present the top 5 results grouped by technology and offer to install the most relevant.',
97
- ' - ALSO search for design/marketing skills when the project has brand or product signals:',
98
- ' * Signals: projectPath contains "landing"/"marketing"/"brand", stack has "website"/"saas"/"startup",',
99
- ' apps[] has marketing-named entries, or README mentions logo/brand/landing.',
100
- ' * When detected: call skill_search("logo design"), skill_search("banner design"),',
101
- ' skill_search("brand identity"), skill_search("og image"), skill_search("favicon generator").',
102
- ' * Present these alongside technical skills — visual assets matter as much as code.',
103
- '2. BEFORE implementing any repeatable pattern: call skill_search with the pattern name.',
104
- ' - "add authentication" → skill_search("authentication " + detected_framework)',
105
- ' - "setup CI/CD" → skill_search("github actions") or skill_search("gitlab ci")',
106
- '3. When the user mentions any technology by name: call skill_search with that term.',
107
- '- If a matching skill is found: show it, offer to install with skill_install.',
108
- '- If no skill found: proceed normally and note there are no community skills for that technology yet.',
109
- '- Explain: "Skills are community-curated guides that encode best practices for this technology."',
110
- '',
111
90
  'RESPONSE FORMAT — MANDATORY for all tool results:',
112
91
  '- NEVER show raw JSON.stringify output to the user — always format as readable markdown',
113
92
  '- Use emojis for visual hierarchy: ✅ success, ⚠️ warning, ❌ error, 🚀 next steps, 📊 stats',
@@ -67,17 +67,14 @@ Do not create either when the information is one-off, speculative, or already co
67
67
  - explicit trigger
68
68
  - concrete steps or constraints
69
69
  - verification command when applicable
70
- 4. Use Planu host-aware tools:
71
- - `create_rule` for mandatory constraints
72
- - `create_skill` for reusable workflows
73
- 5. Use `host: "auto"` unless the user explicitly targets a host.
74
- 6. Prefer updating an existing Planu-owned asset over creating a duplicate.
70
+ 4. Write the rule or skill file directly to the target host path (e.g. `.claude/rules/`, `.claude/skills/`).
71
+ 5. Prefer updating an existing Planu-owned asset over creating a duplicate.
75
72
 
76
73
  ## Quality bar
77
74
 
78
75
  - Rules must be enforceable and written as constraints.
79
76
  - Skills must describe when to invoke, what to inspect, what to do, and what output to produce.
80
- - Do not reference legacy MCP tools that are not part of the 14-tool public core.
77
+ - Do not reference legacy MCP tools that are not part of the 19-tool public core.
81
78
  - Do not create broad "misc" skills.
82
79
  - Do not preserve dead workflows "just in case".
83
80
 
@@ -23,8 +23,8 @@ Use this skill once a spec is `approved` and implementation is about to begin.
23
23
 
24
24
  The normative tool-call sequence for this phase:
25
25
 
26
- 1. **Package the handoff** — call `package_handoff` to build the operating contract for the implementer: objective, BDD acceptance criteria, files to modify/create, ownership, test plan, risks, out-of-scope, current state, next action. Persist it outside chat history
27
- 2. **Move to implementing** — call `update_status(implementing)` only after the handoff package exists
26
+ 1. **Package the handoff** — call `package_handoff` to submit a durable job that builds the operating contract for the implementer: objective, BDD acceptance criteria, files to modify/create, ownership, test plan, risks, out-of-scope, current state, next action. Poll it to completion with `get_job` (use `restart_job` if it ends failed); the package is persisted outside chat history
27
+ 2. **Move to implementing** — call `update_status(implementing)` only after `get_job` reports the handoff package as completed
28
28
  3. **Isolate the work** — implement inside an isolated git worktree created from the current base branch, never on the shared checkout
29
29
  4. **Write revert-proof tests** — for every guard or fix, write the test first, revert the source change and watch the test fail, then restore the source and confirm it passes. Report the observed failure output, not just the final green run
30
30
  5. **No narrative comments** — code is self-documenting; no step-by-step comments, no `(SPEC-NNNN: ...)` rationale blocks, no TODO/FIXME markers
@@ -21,7 +21,7 @@ Use this skill when you want a thorough, multi-perspective code review:
21
21
  - Before merging a large or risky PR (>200 LOC changed)
22
22
  - When a PR touches security-sensitive code (auth, payments, data access)
23
23
  - When a reviewer is unavailable and you need a comprehensive analysis
24
- - When the default `review_pr` output is insufficient and you need specialist depth
24
+ - When a single-pass review is insufficient and you need specialist depth
25
25
 
26
26
  **Trigger phrases**: "panel review", "thorough review", "5-agent review", "deep review", "run the specialist panel"
27
27
 
@@ -31,13 +31,8 @@ Use this skill when all done specs are merged to main and you want to publish a
31
31
 
32
32
  1. **Check state** — calls `planu_status` to confirm no specs are `implementing` or `review`
33
33
  2. **Determine version bump** — analyzes commits since last release: `feat` → minor, `fix` → patch, breaking changes → major
34
- 3. **Generate changelog** — calls `generate_changelog` to create the release notes
35
- 4. **Create release** — calls `create_release({ version, notes })` which:
36
- - Bumps `package.json` version
37
- - Writes `CHANGELOG.md` entry
38
- - Creates git tag `vX.Y.Z`
39
- - Publishes to npm (`npm publish --access public`)
40
- - Pushes tag to origin
34
+ 3. **Run the local gate** — run `pnpm check:preflight` and fix anything it flags
35
+ 4. **Release** — run `pnpm release:local`, which bumps `package.json`, writes the `CHANGELOG.md` entry, tags the commit, publishes to npm, and pushes the tag
41
36
  5. **Confirm** — reports the published version and npm URL
42
37
 
43
38
  ## Usage
@@ -25,10 +25,10 @@ Use this skill after implementation is complete, before marking a spec as done,
25
25
 
26
26
  1. **Find active spec** — calls `planu_status` to identify the current `implementing` spec
27
27
  2. **Submit validation** — call `validate({ specId })` and capture its durable acknowledgement: `operationId`, `projectId`, `workspaceId`, and `cursor`
28
- 3. **Wait for completion** — call `watch_job` with those identifiers and the latest cursor; repeat while state is non-terminal
28
+ 3. **Wait for completion** — poll `get_job` with those identifiers and the latest cursor; repeat while state is non-terminal
29
29
  4. **Inspect the result** — require state `completed`, then read `job.result.structuredContent`; stop and report `failed`, `dead-letter`, or `cancelled` jobs
30
- 5. **Health check** — call `spec_health_check({ specId })` for structural quality
31
- 6. **Auto-fix** — call `auto_fix_validation` for automatically fixable issues, then submit and await a new validation job
30
+ 5. **Fix gaps** — for each failing criterion, fix the underlying code or test
31
+ 6. **Re-validate** — call `validate({ specId })` again and poll `get_job` until it reaches a terminal state; use `restart_job` if the job itself failed or was cancelled rather than the criteria
32
32
  7. **Report** — present a structured pass/fail report from the completed job result
33
33
 
34
34
  ## Output format
@@ -3,7 +3,11 @@
3
3
  "description": "Full CRUD REST API for a domain entity with validation, pagination, and error handling",
4
4
  "variables": [
5
5
  { "name": "entity", "description": "Name of the domain entity (e.g. Product, User, Order)", "default": "Entity" },
6
- { "name": "base_path", "description": "Base URL path for the resource (e.g. /api/products)", "default": "/api/entities" },
6
+ {
7
+ "name": "base_path",
8
+ "description": "Base URL path for the resource (e.g. /api/products)",
9
+ "default": "/api/entities"
10
+ },
7
11
  { "name": "id_type", "description": "Type of the entity ID field (uuid, number)", "default": "uuid" }
8
12
  ],
9
13
  "tags": ["crud", "rest-api", "backend", "database"]
@@ -5,7 +5,11 @@
5
5
  { "name": "provider", "description": "Cloud storage provider (s3, gcs, r2)", "default": "s3" },
6
6
  { "name": "bucket_name", "description": "Name of the storage bucket", "default": "uploads" },
7
7
  { "name": "max_size_mb", "description": "Maximum allowed file size in megabytes", "default": "10" },
8
- { "name": "allowed_types", "description": "Comma-separated list of allowed MIME types", "default": "image/jpeg,image/png,application/pdf" }
8
+ {
9
+ "name": "allowed_types",
10
+ "description": "Comma-separated list of allowed MIME types",
11
+ "default": "image/jpeg,image/png,application/pdf"
12
+ }
9
13
  ],
10
14
  "tags": ["file-upload", "s3", "storage", "backend"]
11
15
  }
@@ -4,7 +4,11 @@
4
4
  "variables": [
5
5
  { "name": "currency", "description": "Default currency code (e.g. usd, eur)", "default": "usd" },
6
6
  { "name": "plan_name", "description": "Name of the subscription plan or product", "default": "Pro Plan" },
7
- { "name": "webhook_endpoint", "description": "Path for the Stripe webhook endpoint", "default": "/api/webhooks/stripe" }
7
+ {
8
+ "name": "webhook_endpoint",
9
+ "description": "Path for the Stripe webhook endpoint",
10
+ "default": "/api/webhooks/stripe"
11
+ }
8
12
  ],
9
13
  "tags": ["payments", "stripe", "subscriptions", "backend"]
10
14
  }