@planu/cli 4.14.1 → 5.1.1

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 (452) hide show
  1. package/CHANGELOG.md +82 -0
  2. package/LICENSE +55 -12
  3. package/README.md +10 -2
  4. package/dist/cli/commands/install.d.ts +1 -12
  5. package/dist/cli/commands/install.js +9 -65
  6. package/dist/cli/commands/job.js +4 -3
  7. package/dist/cli/commands/spec.js +12 -3
  8. package/dist/cli/commands/validate.js +2 -2
  9. package/dist/cli/router.js +1 -3
  10. package/dist/config/environment-schema.json +1 -3
  11. package/dist/config/official-sdd-tools.d.ts +4 -0
  12. package/dist/config/official-sdd-tools.js +35 -0
  13. package/dist/config/product-public.d.ts +139 -3
  14. package/dist/config/product-public.js +8 -1
  15. package/dist/config/product-public.json +7 -36
  16. package/dist/config/registries/hosts/codex.json +20 -363
  17. package/dist/config/release-policy.json +84 -2
  18. package/dist/config/runtime-policy.json +12 -1
  19. package/dist/config/skill-templates/planu-resume-work.md +2 -2
  20. package/dist/core/index.d.ts +1 -1
  21. package/dist/core/spec-validator.d.ts +4 -4
  22. package/dist/core/spec-validator.js +33 -19
  23. package/dist/engine/abortable-process-runner.d.ts +20 -2
  24. package/dist/engine/abortable-process-runner.js +243 -74
  25. package/dist/engine/ambiguity-scorer.js +4 -26
  26. package/dist/engine/auth/scope-mapper.js +1 -7
  27. package/dist/engine/autopilot/state-updater.js +4 -4
  28. package/dist/engine/cascade-hooks/hooks/review-enricher.hook.js +9 -6
  29. package/dist/engine/cascade-hooks/state-drift-detector.d.ts +3 -3
  30. package/dist/engine/cascade-hooks/state-drift-detector.js +1 -1
  31. package/dist/engine/ci-generator/planu-config.js +1 -7
  32. package/dist/engine/clarification-gate/gate.d.ts +3 -3
  33. package/dist/engine/code-scanner/layer-scanner.js +6 -22
  34. package/dist/engine/core-bridge.d.ts +3 -3
  35. package/dist/engine/cost-guardrails.d.ts +1 -1
  36. package/dist/engine/cost-guardrails.js +1 -1
  37. package/dist/engine/criterion-identity.d.ts +1 -0
  38. package/dist/engine/criterion-identity.js +7 -0
  39. package/dist/engine/dashboard/data-loader.js +2 -7
  40. package/dist/engine/dashboard/templates-layout.js +0 -3
  41. package/dist/engine/dashboard/templates-project.js +1 -13
  42. package/dist/engine/docs-site-generator/data-collector.d.ts +1 -1
  43. package/dist/engine/docs-site-generator/data-collector.js +7 -28
  44. package/dist/engine/docs-site-generator/tools-renderer.js +3 -10
  45. package/dist/engine/evidence-gates/artifact-reader.d.ts +12 -1
  46. package/dist/engine/evidence-gates/artifact-reader.js +174 -4
  47. package/dist/engine/evidence-gates/evidence-autofill.d.ts +10 -0
  48. package/dist/engine/evidence-gates/evidence-autofill.js +148 -0
  49. package/dist/engine/evidence-gates/evidence-skeletons.d.ts +19 -0
  50. package/dist/engine/evidence-gates/evidence-skeletons.js +69 -0
  51. package/dist/engine/evidence-gates/lifecycle-gate.js +4 -3
  52. package/dist/engine/evidence-gates/reconciliation-freshness.d.ts +11 -0
  53. package/dist/engine/evidence-gates/reconciliation-freshness.js +72 -0
  54. package/dist/engine/evidence-index/done-drift.d.ts +1 -1
  55. package/dist/engine/evidence-index/done-drift.js +40 -18
  56. package/dist/engine/execution/context.js +3 -0
  57. package/dist/engine/execution/durable-job-heartbeat-runtime.d.ts +4 -0
  58. package/dist/engine/execution/durable-job-heartbeat-runtime.js +400 -0
  59. package/dist/engine/execution/job-runtime.d.ts +30 -0
  60. package/dist/engine/execution/job-runtime.js +114 -6
  61. package/dist/engine/execution/operation-journal.js +10 -4
  62. package/dist/engine/execution/public-job-sanitizer.d.ts +4 -0
  63. package/dist/engine/execution/public-job-sanitizer.js +31 -0
  64. package/dist/engine/execution/validate-job-executor.d.ts +12 -1
  65. package/dist/engine/execution/validate-job-executor.js +549 -86
  66. package/dist/engine/execution/validate-job-payload.js +107 -50
  67. package/dist/engine/execution/validate-job-recovery.js +1 -1
  68. package/dist/engine/execution/validate-worker-runtime.d.ts +5 -0
  69. package/dist/engine/execution/validate-worker-runtime.js +90 -2
  70. package/dist/engine/execution/validate-worker-thread.js +17 -24
  71. package/dist/engine/handoff-artifacts/schemas.d.ts +2 -1
  72. package/dist/engine/handoff-artifacts/schemas.js +33 -0
  73. package/dist/engine/handoff-packager.d.ts +19 -0
  74. package/dist/engine/handoff-packager.js +415 -13
  75. package/dist/engine/hooks/effort-configurator.js +1 -1
  76. package/dist/engine/impact-detector/test-break-predictor.js +3 -3
  77. package/dist/engine/impact-detector/tool-registration.js +1 -1
  78. package/dist/engine/implementation-contract/renderer.js +23 -8
  79. package/dist/engine/lifecycle-reconciliation-io.d.ts +11 -0
  80. package/dist/engine/lifecycle-reconciliation-io.js +180 -0
  81. package/dist/engine/lifecycle-reconciliation.d.ts +16 -0
  82. package/dist/engine/lifecycle-reconciliation.js +406 -0
  83. package/dist/engine/local-first/tool-classification.js +2 -0
  84. package/dist/engine/macos-keychain-native-port.d.ts +5 -0
  85. package/dist/engine/macos-keychain-native-port.js +19 -7
  86. package/dist/engine/migrations/remove-commercial-state.d.ts +3 -0
  87. package/dist/engine/migrations/remove-commercial-state.js +343 -0
  88. package/dist/engine/minimality/policy-loader.js +247 -6
  89. package/dist/engine/network-policy.js +1 -0
  90. package/dist/engine/planu-core.darwin-arm64.node.manifest.json +7 -7
  91. package/dist/engine/planu-core.darwin-arm64.node.sbom.json +20 -20
  92. package/dist/engine/planu-core.darwin-x64.node.manifest.json +7 -7
  93. package/dist/engine/planu-core.darwin-x64.node.sbom.json +20 -20
  94. package/dist/engine/planu-core.linux-arm64-gnu.node.manifest.json +7 -7
  95. package/dist/engine/planu-core.linux-arm64-gnu.node.sbom.json +20 -20
  96. package/dist/engine/planu-core.linux-arm64-musl.node.manifest.json +7 -7
  97. package/dist/engine/planu-core.linux-arm64-musl.node.sbom.json +20 -20
  98. package/dist/engine/planu-core.linux-x64-gnu.node.manifest.json +7 -7
  99. package/dist/engine/planu-core.linux-x64-gnu.node.sbom.json +20 -20
  100. package/dist/engine/planu-core.linux-x64-musl.node.manifest.json +7 -7
  101. package/dist/engine/planu-core.linux-x64-musl.node.sbom.json +20 -20
  102. package/dist/engine/planu-core.win32-arm64-msvc.node.manifest.json +7 -7
  103. package/dist/engine/planu-core.win32-arm64-msvc.node.sbom.json +20 -20
  104. package/dist/engine/planu-core.win32-x64-msvc.node.manifest.json +7 -7
  105. package/dist/engine/planu-core.win32-x64-msvc.node.sbom.json +20 -20
  106. package/dist/engine/readiness-checker.d.ts +1 -16
  107. package/dist/engine/readiness-checker.js +27 -88
  108. package/dist/engine/reverse-engineer/api-detector.js +2 -13
  109. package/dist/engine/reverse-engineer/complexity-analyzer.js +2 -13
  110. package/dist/engine/reverse-engineer/config-analyzer.js +2 -13
  111. package/dist/engine/reverse-engineer/dependency-graph.js +2 -13
  112. package/dist/engine/reverse-engineer/test-analyzer.js +2 -13
  113. package/dist/engine/reverse-engineer/walk-ignore.d.ts +3 -0
  114. package/dist/engine/reverse-engineer/walk-ignore.js +26 -0
  115. package/dist/engine/runtime-policy.d.ts +2 -0
  116. package/dist/engine/runtime-policy.js +42 -5
  117. package/dist/engine/runtime-security/rate-limiter.js +0 -1
  118. package/dist/engine/safety/contained-project-file.d.ts +3 -0
  119. package/dist/engine/safety/contained-project-file.js +23 -0
  120. package/dist/engine/scope-boundaries/contradiction-checker.js +63 -1
  121. package/dist/engine/scope-boundaries/scope-validator.js +45 -7
  122. package/dist/engine/session/checkpoint-writer.js +0 -9
  123. package/dist/engine/spec-format/acceptance-criteria.d.ts +6 -2
  124. package/dist/engine/spec-format/acceptance-criteria.js +82 -22
  125. package/dist/engine/spec-format/markdown-sections.d.ts +14 -0
  126. package/dist/engine/spec-format/markdown-sections.js +105 -0
  127. package/dist/engine/spec-format/read-technical-section.js +33 -5
  128. package/dist/engine/spec-format/technical-md-populator.js +3 -2
  129. package/dist/engine/spec-format/text-fences.js +20 -2
  130. package/dist/engine/spec-format/unified-spec-builder.d.ts +7 -0
  131. package/dist/engine/spec-format/unified-spec-builder.js +202 -0
  132. package/dist/engine/spec-migrator/canonical-deduplicator.d.ts +18 -0
  133. package/dist/engine/spec-migrator/canonical-deduplicator.js +479 -0
  134. package/dist/engine/spec-migrator/filesystem-import.d.ts +4 -8
  135. package/dist/engine/spec-migrator/filesystem-import.js +121 -14
  136. package/dist/engine/spec-migrator/frontmatter-parser.js +32 -15
  137. package/dist/engine/spec-migrator/index.d.ts +1 -0
  138. package/dist/engine/spec-migrator/index.js +1 -0
  139. package/dist/engine/spec-state-machine/transition-spec.d.ts +6 -1
  140. package/dist/engine/spec-state-machine/transition-spec.js +10 -1
  141. package/dist/engine/spec-state-syncer.js +1 -1
  142. package/dist/engine/technical-enricher/index.js +16 -8
  143. package/dist/engine/technical-enricher/render-enriched.d.ts +1 -0
  144. package/dist/engine/technical-enricher/render-enriched.js +42 -14
  145. package/dist/engine/telemetry/health-checker.js +53 -17
  146. package/dist/engine/telemetry/telemetry-client.js +26 -8
  147. package/dist/engine/text-signal-boundaries.d.ts +2 -0
  148. package/dist/engine/text-signal-boundaries.js +25 -2
  149. package/dist/engine/time/relative-date.d.ts +3 -0
  150. package/dist/engine/time/relative-date.js +16 -0
  151. package/dist/engine/timing/budget.d.ts +11 -0
  152. package/dist/engine/timing/budget.js +31 -9
  153. package/dist/engine/token-optimizer/analytics.d.ts +1 -1
  154. package/dist/engine/token-optimizer/analytics.js +5 -6
  155. package/dist/engine/usage-tracker/core.d.ts +2 -2
  156. package/dist/engine/usage-tracker/core.js +1 -2
  157. package/dist/engine/usage-tracker/index.d.ts +0 -3
  158. package/dist/engine/usage-tracker/index.js +0 -3
  159. package/dist/engine/usage-tracker/stats.d.ts +2 -2
  160. package/dist/engine/usage-tracker/stats.js +1 -28
  161. package/dist/engine/validation/durable-validation.d.ts +1 -1
  162. package/dist/engine/validation/durable-validation.js +3 -82
  163. package/dist/engine/validation/validation-freshness.d.ts +11 -1
  164. package/dist/engine/validation/validation-freshness.js +231 -91
  165. package/dist/engine/validation/validation-receipt.d.ts +9 -6
  166. package/dist/engine/validation/validation-receipt.js +84 -24
  167. package/dist/engine/validation/validation-source-digest.d.ts +2 -0
  168. package/dist/engine/validation/validation-source-digest.js +86 -0
  169. package/dist/engine/validation/validation-submission.d.ts +5 -4
  170. package/dist/engine/validation/validation-submission.js +25 -11
  171. package/dist/engine/validation/validation-worktree.d.ts +21 -0
  172. package/dist/engine/validation/validation-worktree.js +260 -0
  173. package/dist/engine/validation-impact-planner.d.ts +14 -2
  174. package/dist/engine/validation-impact-planner.js +0 -3
  175. package/dist/engine/validator/dor-dod.d.ts +1 -0
  176. package/dist/engine/validator/dor-dod.js +5 -3
  177. package/dist/engine/validator/extractors.d.ts +1 -5
  178. package/dist/engine/validator/extractors.js +24 -69
  179. package/dist/engine/validator/spec-compliance-runner.d.ts +12 -24
  180. package/dist/engine/validator/spec-compliance-runner.js +429 -211
  181. package/dist/engine/validator.js +35 -22
  182. package/dist/index.js +4 -16
  183. package/dist/resources/usage-stats-resource.js +2 -18
  184. package/dist/security/adapters/linux-secret-service.js +7 -3
  185. package/dist/security/adapters/windows-credential-manager.js +6 -4
  186. package/dist/server/routes/specs.js +13 -1
  187. package/dist/storage/base-store.d.ts +1 -1
  188. package/dist/storage/base-store.js +1 -1
  189. package/dist/storage/feedback-remote.d.ts +2 -3
  190. package/dist/storage/feedback-remote.js +45 -31
  191. package/dist/storage/global-store.d.ts +1 -17
  192. package/dist/storage/global-store.js +1 -42
  193. package/dist/storage/index.d.ts +0 -2
  194. package/dist/storage/index.js +0 -2
  195. package/dist/storage/migrations/canonical-storage.js +124 -11
  196. package/dist/storage/runtime-db.d.ts +9 -0
  197. package/dist/storage/runtime-db.js +64 -8
  198. package/dist/storage/spec-store.d.ts +14 -2
  199. package/dist/storage/spec-store.js +104 -14
  200. package/dist/storage/status-store/atomic-status-write.d.ts +5 -0
  201. package/dist/storage/status-store/atomic-status-write.js +57 -0
  202. package/dist/storage/status-store/file-lock.js +30 -11
  203. package/dist/storage/status-store/self-healing.js +3 -3
  204. package/dist/storage/status-store/version-sync.d.ts +2 -1
  205. package/dist/storage/status-store/version-sync.js +35 -40
  206. package/dist/storage/usage-store.d.ts +1 -5
  207. package/dist/storage/usage-store.js +0 -35
  208. package/dist/tools/auto-update-handler.d.ts +3 -3
  209. package/dist/tools/auto-update-handler.js +3 -3
  210. package/dist/tools/challenge-spec/resilience-challenge-scenarios.d.ts +2 -1
  211. package/dist/tools/challenge-spec/resilience-challenge-scenarios.js +10 -7
  212. package/dist/tools/challenge-spec/scenario-collector.js +1 -1
  213. package/dist/tools/challenge-spec/scenarios-data.js +1 -1
  214. package/dist/tools/challenge-spec/scenarios-utils.d.ts +1 -1
  215. package/dist/tools/challenge-spec/scenarios-utils.js +35 -11
  216. package/dist/tools/challenge-spec-helpers.d.ts +10 -1
  217. package/dist/tools/challenge-spec-helpers.js +63 -22
  218. package/dist/tools/challenge-spec.js +23 -8
  219. package/dist/tools/check-readiness.js +38 -14
  220. package/dist/tools/configure-telemetry.js +30 -2
  221. package/dist/tools/create-spec/spec-builder.d.ts +7 -0
  222. package/dist/tools/create-spec/spec-builder.js +19 -15
  223. package/dist/tools/create-spec.d.ts +1 -0
  224. package/dist/tools/create-spec.js +584 -309
  225. package/dist/tools/git/branch-ops.d.ts +1 -1
  226. package/dist/tools/git/branch-ops.js +3 -2
  227. package/dist/tools/init-project/handler.js +10 -12
  228. package/dist/tools/init-project/host-assets-writer.js +26 -1
  229. package/dist/tools/init-project/lint-scaffolder.d.ts +3 -3
  230. package/dist/tools/init-project/migration-runner.d.ts +2 -4
  231. package/dist/tools/init-project/migration-runner.js +3 -2
  232. package/dist/tools/init-project/portable-index-reconciler.d.ts +4 -0
  233. package/dist/tools/init-project/portable-index-reconciler.js +14 -0
  234. package/dist/tools/init-project/result-builder.js +1 -3
  235. package/dist/tools/jobs/handlers.js +38 -6
  236. package/dist/tools/list-specs.js +5 -26
  237. package/dist/tools/merge-risk-handler.js +2 -2
  238. package/dist/tools/package-handoff.js +2 -0
  239. package/dist/tools/reconcile-spec.js +0 -27
  240. package/dist/tools/register-agent-squad-tools.js +2 -2
  241. package/dist/tools/register-platform-tools/design-stack-tools.js +11 -11
  242. package/dist/tools/register-platform-tools/lifecycle-infra-tools.js +7 -7
  243. package/dist/tools/register-sdd-tools.d.ts +1 -1
  244. package/dist/tools/register-sdd-tools.js +2 -29
  245. package/dist/tools/register-spec-tools/analysis-tools.js +8 -8
  246. package/dist/tools/register-spec-tools/core-spec-tools.js +29 -19
  247. package/dist/tools/safe-handler.d.ts +5 -13
  248. package/dist/tools/safe-handler.js +7 -23
  249. package/dist/tools/schemas/index.d.ts +1 -1
  250. package/dist/tools/schemas/index.js +1 -1
  251. package/dist/tools/schemas/output-schemas.d.ts +0 -23
  252. package/dist/tools/schemas/output-schemas.js +0 -28
  253. package/dist/tools/schemas/spec.d.ts +4 -0
  254. package/dist/tools/schemas/spec.js +3 -0
  255. package/dist/tools/schemas/validate-output-schema.d.ts +11 -0
  256. package/dist/tools/schemas/validate-output-schema.js +7 -0
  257. package/dist/tools/spec-prompt-handler.js +3 -3
  258. package/dist/tools/sync-spec-state-handler.d.ts +1 -1
  259. package/dist/tools/sync-spec-state-handler.js +50 -2
  260. package/dist/tools/tool-entry.d.ts +4 -4
  261. package/dist/tools/tool-entry.js +3 -3
  262. package/dist/tools/tool-registry/core-tools.js +31 -15
  263. package/dist/tools/tool-registry/group-infra.js +27 -110
  264. package/dist/tools/tool-registry/group-quality-compliance.js +26 -26
  265. package/dist/tools/tool-registry/inventory.d.ts +2 -0
  266. package/dist/tools/tool-registry/inventory.js +2 -0
  267. package/dist/tools/tool-registry-helpers.d.ts +3 -3
  268. package/dist/tools/tool-registry-helpers.js +3 -3
  269. package/dist/tools/tool-usage-report/registered-tools.d.ts +1 -1
  270. package/dist/tools/tool-usage-report/registered-tools.js +3 -15
  271. package/dist/tools/update-status/approval-gates.js +3 -0
  272. package/dist/tools/update-status/batch.d.ts +6 -2
  273. package/dist/tools/update-status/batch.js +58 -1
  274. package/dist/tools/update-status/dod-gates.d.ts +16 -1
  275. package/dist/tools/update-status/dod-gates.js +191 -1
  276. package/dist/tools/update-status/done-receipt-verifier.d.ts +8 -0
  277. package/dist/tools/update-status/done-receipt-verifier.js +75 -27
  278. package/dist/tools/update-status/evidence-gate.d.ts +4 -0
  279. package/dist/tools/update-status/evidence-gate.js +103 -3
  280. package/dist/tools/update-status/file-sync.d.ts +4 -3
  281. package/dist/tools/update-status/file-sync.js +57 -6
  282. package/dist/tools/update-status/index.d.ts +25 -1
  283. package/dist/tools/update-status/index.js +292 -78
  284. package/dist/tools/update-status/response-builder.js +3 -3
  285. package/dist/tools/update-status/side-effects.d.ts +2 -0
  286. package/dist/tools/update-status/side-effects.js +2 -2
  287. package/dist/tools/update-status/transition-guard.js +45 -16
  288. package/dist/tools/update-status-actions.d.ts +4 -2
  289. package/dist/tools/update-status-actions.js +16 -14
  290. package/dist/tools/usage-report.js +1 -16
  291. package/dist/tools/usage-stats.js +1 -18
  292. package/dist/tools/usage-tracking.d.ts +4 -0
  293. package/dist/tools/usage-tracking.js +20 -0
  294. package/dist/tools/validate-lint.d.ts +1 -0
  295. package/dist/tools/validate-lint.js +1 -1
  296. package/dist/tools/validate.d.ts +2 -1
  297. package/dist/tools/validate.js +114 -34
  298. package/dist/tools/workspace-dashboard-handler.js +38 -0
  299. package/dist/transports/http-transport.js +6 -8
  300. package/dist/transports/mcp-types.d.ts +0 -2
  301. package/dist/transports/session-context.js +1 -1
  302. package/dist/types/cascade-hooks.d.ts +1 -1
  303. package/dist/types/ci.d.ts +0 -4
  304. package/dist/types/clarification-token.d.ts +1 -1
  305. package/dist/types/claude-code-runtime.d.ts +0 -27
  306. package/dist/types/commercial-migration.d.ts +17 -0
  307. package/dist/types/commercial-migration.js +2 -0
  308. package/dist/types/common/primitives.d.ts +0 -2
  309. package/dist/types/core-bridge.d.ts +4 -10
  310. package/dist/types/dashboard.d.ts +3 -7
  311. package/dist/types/docs.d.ts +0 -1
  312. package/dist/types/durable-job.d.ts +4 -4
  313. package/dist/types/durable-validation.d.ts +100 -2
  314. package/dist/types/durable-validation.js +165 -1
  315. package/dist/types/errors/structured-error.d.ts +3 -3
  316. package/dist/types/estimation.d.ts +2 -0
  317. package/dist/types/evidence-autofill.d.ts +34 -0
  318. package/dist/types/evidence-autofill.js +2 -0
  319. package/dist/types/evidence-gates.d.ts +9 -1
  320. package/dist/types/execution.d.ts +2 -0
  321. package/dist/types/gemini-integration.d.ts +0 -11
  322. package/dist/types/handoff-artifacts.d.ts +41 -0
  323. package/dist/types/hooks-advanced.d.ts +0 -13
  324. package/dist/types/impact-detection.d.ts +2 -2
  325. package/dist/types/index.d.ts +3 -6
  326. package/dist/types/index.js +2 -5
  327. package/dist/types/kiro-integration.d.ts +0 -6
  328. package/dist/types/network-policy.d.ts +1 -1
  329. package/dist/types/project/lint-scaffolder.d.ts +1 -1
  330. package/dist/types/runtime-policy.d.ts +11 -0
  331. package/dist/types/session-safeguard.d.ts +0 -31
  332. package/dist/types/spec/canonical-repair.d.ts +81 -0
  333. package/dist/types/spec/canonical-repair.js +2 -0
  334. package/dist/types/spec/core.d.ts +20 -0
  335. package/dist/types/spec/index.d.ts +1 -0
  336. package/dist/types/spec/index.js +1 -0
  337. package/dist/types/spec/inputs.d.ts +35 -1
  338. package/dist/types/spec-format.d.ts +25 -1
  339. package/dist/types/telemetry.d.ts +4 -1
  340. package/dist/types/transition-log.d.ts +1 -1
  341. package/dist/types/transport.d.ts +0 -2
  342. package/dist/types/usage.d.ts +1 -36
  343. package/dist/types/usage.js +1 -1
  344. package/dist/types/validate-worker.d.ts +6 -0
  345. package/dist/types/validation-receipt.d.ts +1 -1
  346. package/dist/types/validation.d.ts +10 -4
  347. package/package.json +17 -12
  348. package/planu-native.json +1 -1
  349. package/planu-plugin.json +23 -40
  350. package/scripts/lib/pending-release-file.mjs +93 -0
  351. package/src/i18n/messages/en.json +0 -41
  352. package/src/i18n/messages/es.json +0 -41
  353. package/src/i18n/messages/pt.json +0 -41
  354. package/dist/cli/commands/activate.d.ts +0 -14
  355. package/dist/cli/commands/activate.js +0 -174
  356. package/dist/config/license-plans.json +0 -251
  357. package/dist/config/product-public.ts +0 -148
  358. package/dist/config/server-instructions.ts +0 -121
  359. package/dist/config/version-defaults.ts +0 -76
  360. package/dist/config/version.ts +0 -21
  361. package/dist/engine/ai-integration/gemini/settings-generator.d.ts +0 -4
  362. package/dist/engine/ai-integration/gemini/settings-generator.js +0 -195
  363. package/dist/engine/ai-integration/kiro/hooks-generator.d.ts +0 -6
  364. package/dist/engine/ai-integration/kiro/hooks-generator.js +0 -75
  365. package/dist/engine/hooks/full-spectrum-generator.d.ts +0 -32
  366. package/dist/engine/hooks/full-spectrum-generator.js +0 -117
  367. package/dist/engine/license-validator/config-loader.d.ts +0 -5
  368. package/dist/engine/license-validator/config-loader.js +0 -16
  369. package/dist/engine/license-validator/core.d.ts +0 -15
  370. package/dist/engine/license-validator/core.js +0 -151
  371. package/dist/engine/license-validator/fingerprint.d.ts +0 -3
  372. package/dist/engine/license-validator/fingerprint.js +0 -17
  373. package/dist/engine/license-validator/lemon-squeezy.d.ts +0 -5
  374. package/dist/engine/license-validator/lemon-squeezy.js +0 -55
  375. package/dist/engine/license-validator.d.ts +0 -5
  376. package/dist/engine/license-validator.js +0 -6
  377. package/dist/engine/product-intelligence/index.d.ts +0 -7
  378. package/dist/engine/product-intelligence/index.js +0 -211
  379. package/dist/engine/session/auto-save.d.ts +0 -18
  380. package/dist/engine/session/auto-save.js +0 -98
  381. package/dist/engine/session/context-snapshot.d.ts +0 -8
  382. package/dist/engine/session/context-snapshot.js +0 -49
  383. package/dist/engine/session/memory-sync.d.ts +0 -12
  384. package/dist/engine/session/memory-sync.js +0 -34
  385. package/dist/engine/session/session-diff.d.ts +0 -11
  386. package/dist/engine/session/session-diff.js +0 -42
  387. package/dist/engine/session/session-merge.d.ts +0 -12
  388. package/dist/engine/session/session-merge.js +0 -55
  389. package/dist/engine/session-safeguard/checkpoint-runner.d.ts +0 -4
  390. package/dist/engine/session-safeguard/checkpoint-runner.js +0 -70
  391. package/dist/engine/session-safeguard/learnings-buffer.d.ts +0 -15
  392. package/dist/engine/session-safeguard/learnings-buffer.js +0 -91
  393. package/dist/engine/session-safeguard/precompaction-drain.d.ts +0 -10
  394. package/dist/engine/session-safeguard/precompaction-drain.js +0 -82
  395. package/dist/engine/session-safeguard/unpushed-detector.d.ts +0 -7
  396. package/dist/engine/session-safeguard/unpushed-detector.js +0 -59
  397. package/dist/engine/spec-changelog/core.d.ts +0 -16
  398. package/dist/engine/spec-changelog/core.js +0 -176
  399. package/dist/engine/spec-changelog/diff.d.ts +0 -18
  400. package/dist/engine/spec-changelog/diff.js +0 -121
  401. package/dist/engine/spec-changelog/index.d.ts +0 -3
  402. package/dist/engine/spec-changelog/index.js +0 -4
  403. package/dist/engine/trial-engine.d.ts +0 -5
  404. package/dist/engine/trial-engine.js +0 -14
  405. package/dist/engine/usage-tracker/rate-check.d.ts +0 -7
  406. package/dist/engine/usage-tracker/rate-check.js +0 -18
  407. package/dist/engine/usage-tracker/rate-limiter.d.ts +0 -14
  408. package/dist/engine/usage-tracker/rate-limiter.js +0 -73
  409. package/dist/engine/usage-tracker/trial.d.ts +0 -27
  410. package/dist/engine/usage-tracker/trial.js +0 -49
  411. package/dist/engine/webhook/event-handlers.d.ts +0 -25
  412. package/dist/engine/webhook/event-handlers.js +0 -89
  413. package/dist/engine/webhook/index.d.ts +0 -4
  414. package/dist/engine/webhook/index.js +0 -5
  415. package/dist/engine/webhook/server.d.ts +0 -12
  416. package/dist/engine/webhook/server.js +0 -249
  417. package/dist/engine/webhook/signature.d.ts +0 -16
  418. package/dist/engine/webhook/signature.js +0 -49
  419. package/dist/storage/license-store.d.ts +0 -6
  420. package/dist/storage/license-store.js +0 -63
  421. package/dist/storage/session-store.d.ts +0 -20
  422. package/dist/storage/session-store.js +0 -136
  423. package/dist/tools/activate-license.d.ts +0 -6
  424. package/dist/tools/activate-license.js +0 -132
  425. package/dist/tools/checkpoint-handler.d.ts +0 -3
  426. package/dist/tools/checkpoint-handler.js +0 -130
  427. package/dist/tools/export-session.d.ts +0 -3
  428. package/dist/tools/export-session.js +0 -90
  429. package/dist/tools/license-gate.d.ts +0 -18
  430. package/dist/tools/license-gate.js +0 -222
  431. package/dist/tools/license-status.d.ts +0 -3
  432. package/dist/tools/license-status.js +0 -93
  433. package/dist/tools/list-sessions.d.ts +0 -3
  434. package/dist/tools/list-sessions.js +0 -46
  435. package/dist/tools/planu-session-checkpoint.d.ts +0 -6
  436. package/dist/tools/planu-session-checkpoint.js +0 -42
  437. package/dist/tools/restore-session.d.ts +0 -3
  438. package/dist/tools/restore-session.js +0 -71
  439. package/dist/tools/spec-history.d.ts +0 -3
  440. package/dist/tools/spec-history.js +0 -59
  441. package/dist/tools/webhook.d.ts +0 -6
  442. package/dist/tools/webhook.js +0 -150
  443. package/dist/types/changelog.d.ts +0 -49
  444. package/dist/types/changelog.js +0 -3
  445. package/dist/types/licensing.d.ts +0 -109
  446. package/dist/types/licensing.js +0 -4
  447. package/dist/types/product-intelligence.d.ts +0 -60
  448. package/dist/types/product-intelligence.js +0 -3
  449. package/dist/types/session.d.ts +0 -84
  450. package/dist/types/session.js +0 -3
  451. package/dist/types/webhook.d.ts +0 -62
  452. package/dist/types/webhook.js +0 -4
@@ -38,7 +38,7 @@ export function formatBudgetMessage(status) {
38
38
  return msg;
39
39
  }
40
40
  /**
41
- * Enforces budget limits before executing a licensed tool.
41
+ * Enforces engineering budget limits before executing a governed tool.
42
42
  * - If no budget is configured for the spec → no-op (pass through).
43
43
  * - If budget is exhausted → throws an Error to block tool execution.
44
44
  * - If warning threshold is reached → logs a warning but allows execution.
@@ -1,5 +1,6 @@
1
1
  import type { CriterionIdentity, CriterionIdentityOptions } from '../types/criterion-identity.js';
2
2
  export type { CriterionIdentity, CriterionIdentityOptions } from '../types/criterion-identity.js';
3
+ export declare function hasExplicitCriterionId(value: string): boolean;
3
4
  export declare function normalizeCriterionText(value: string): string;
4
5
  export declare function createCriterionIdentity(value: string, options?: CriterionIdentityOptions): CriterionIdentity;
5
6
  export declare function criterionIdentitiesMatch(left: CriterionIdentity, right: CriterionIdentity): boolean;
@@ -1,5 +1,12 @@
1
1
  import { createHash } from 'node:crypto';
2
2
  const CRITERION_ID_PREFIX = /^(AC|AB)\s*-?\s*(\d+)\b\s*[:.)-]?\s*/i;
3
+ export function hasExplicitCriterionId(value) {
4
+ const stripped = value
5
+ .normalize('NFKC')
6
+ .replace(/^[-*+]\s*\[[ xX]\]\s*/, '')
7
+ .trim();
8
+ return CRITERION_ID_PREFIX.test(stripped);
9
+ }
3
10
  export function normalizeCriterionText(value) {
4
11
  return value
5
12
  .normalize('NFKC')
@@ -324,18 +324,13 @@ export async function loadUsageStats() {
324
324
  const raw = await readJsonFile(usageFile);
325
325
  if (!raw) {
326
326
  return {
327
- tier: 'unknown',
328
327
  callsToday: 0,
329
- dailyLimit: null,
330
- trialDaysLeft: null,
331
328
  isAvailable: false,
332
329
  };
333
330
  }
331
+ const today = new Date().toISOString().slice(0, 10);
334
332
  return {
335
- tier: raw.tier ?? 'free',
336
- callsToday: raw.callsToday ?? 0,
337
- dailyLimit: raw.dailyLimit ?? null,
338
- trialDaysLeft: raw.trialDaysLeft ?? null,
333
+ callsToday: (raw.events ?? []).filter((event) => event.timestamp?.startsWith(today)).length,
339
334
  isAvailable: true,
340
335
  };
341
336
  }
@@ -194,9 +194,6 @@ function getPageStyles() {
194
194
  .usage-panel { background: var(--surface); border: 1px solid var(--border);
195
195
  border-radius: var(--radius); padding: 1rem; margin-top: 1.5rem; }
196
196
  .usage-panel h3 { font-size: 0.9rem; font-weight: 600; margin-bottom: 0.75rem; color: var(--text-muted); }
197
- .usage-tier { font-size: 1.1rem; font-weight: 700; color: var(--accent); }
198
- .trial-warning { color: #f59e0b; font-size: 0.82rem; margin-top: 0.35rem; }
199
- .trial-critical { color: #ef4444; font-weight: 600; }
200
197
  .status-indicator.updating { color: #f59e0b; }
201
198
  .shortcuts-overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.7);
202
199
  z-index: 1000; align-items: center; justify-content: center; }
@@ -30,21 +30,9 @@ function renderUsagePanel(usage) {
30
30
  <div style="color:var(--text-muted);font-size:0.85rem">Sin datos de uso disponibles</div>
31
31
  </div>`;
32
32
  }
33
- const tierLabel = usage.tier.charAt(0).toUpperCase() + usage.tier.slice(1);
34
- const limitLabel = usage.dailyLimit !== null ? String(usage.dailyLimit) : '∞';
35
- const callsLabel = `${usage.callsToday} / ${limitLabel}`;
36
- let trialHtml = '';
37
- if (usage.trialDaysLeft !== null) {
38
- const isCritical = usage.trialDaysLeft <= 3;
39
- trialHtml = `<div class="trial-warning ${isCritical ? 'trial-critical' : ''}">
40
- Trial: ${usage.trialDaysLeft} día${usage.trialDaysLeft !== 1 ? 's' : ''} restante${usage.trialDaysLeft !== 1 ? 's' : ''}
41
- </div>`;
42
- }
43
33
  return `<div class="usage-panel">
44
34
  <h3>Uso</h3>
45
- <div class="usage-tier">${escapeHtml(tierLabel)}</div>
46
- <div style="font-size:0.82rem;color:var(--text-muted);margin-top:0.35rem">Llamadas hoy: ${escapeHtml(callsLabel)}</div>
47
- ${trialHtml}
35
+ <div style="font-size:0.82rem;color:var(--text-muted);margin-top:0.35rem">Llamadas hoy: ${String(usage.callsToday)}</div>
48
36
  </div>`;
49
37
  }
50
38
  /** Render the health metrics panel */
@@ -1,5 +1,5 @@
1
1
  import type { DocSpecSummary, ToolEntry, ProjectMetrics } from '../../types/docs.js';
2
2
  export declare function collectSpecs(projectPath: string): Promise<DocSpecSummary[]>;
3
- export declare function collectTools(projectPath: string): ToolEntry[];
3
+ export declare function collectTools(_projectPath: string): ToolEntry[];
4
4
  export declare function collectMetrics(projectPath: string): Promise<ProjectMetrics>;
5
5
  //# sourceMappingURL=data-collector.d.ts.map
@@ -1,8 +1,8 @@
1
1
  // @crash-shield-ignore-file — config/cache reader for Planu-controlled JSON; writer is this codebase, shape guaranteed by build/seed.
2
2
  // SPEC-093: Data collector for docs site generator
3
- import { readFileSync } from 'node:fs';
4
3
  import { readdir, readFile, stat } from 'node:fs/promises';
5
4
  import { join } from 'node:path';
5
+ import { readCanonicalToolNames } from '../../config/official-sdd-tools.js';
6
6
  import { parseFrontmatter } from '../frontmatter-parser.js';
7
7
  const SDD_PHASES = {
8
8
  Initialize: ['init_project', 'init_constitution', 'set_locale'],
@@ -225,33 +225,12 @@ export async function collectSpecs(projectPath) {
225
225
  });
226
226
  return results;
227
227
  }
228
- export function collectTools(projectPath) {
229
- let plans;
230
- try {
231
- const plansPath = join(projectPath, 'src', 'config', 'license-plans.json');
232
- plans = JSON.parse(readFileSync(plansPath, 'utf-8'));
233
- }
234
- catch {
235
- return [];
236
- }
237
- const entries = [];
238
- for (const tool of plans.freeTools ?? []) {
239
- entries.push({
240
- name: tool,
241
- description: tool.replace(/_/g, ' '),
242
- phase: findPhaseForTool(tool),
243
- tier: 'free',
244
- });
245
- }
246
- for (const tool of plans.proTools ?? []) {
247
- entries.push({
248
- name: tool,
249
- description: tool.replace(/_/g, ' '),
250
- phase: findPhaseForTool(tool),
251
- tier: 'pro',
252
- });
253
- }
254
- return entries;
228
+ export function collectTools(_projectPath) {
229
+ return readCanonicalToolNames().map((tool) => ({
230
+ name: tool,
231
+ description: tool.replaceAll('_', ' '),
232
+ phase: findPhaseForTool(tool),
233
+ }));
255
234
  }
256
235
  async function countLinesInDir(dirPath) {
257
236
  let total = 0;
@@ -11,18 +11,11 @@ function groupByPhase(tools) {
11
11
  }
12
12
  return groups;
13
13
  }
14
- function renderTierBadge(tier) {
15
- const cls = tier === 'free' ? 'badge-free' : 'badge-pro';
16
- const label = tier === 'free' ? 'Free' : 'Pro';
17
- return `<span class="tier-badge ${cls}">${label}</span>`;
18
- }
19
14
  export function renderToolsCatalog(tools) {
20
- const freeCount = tools.filter((t) => t.tier === 'free').length;
21
- const proCount = tools.filter((t) => t.tier === 'pro').length;
22
15
  if (tools.length === 0) {
23
16
  return `<div class="tools-catalog">
24
17
  <div class="tools-summary">
25
- <p>Total: 0 | Free: 0 | Pro: 0</p>
18
+ <p>Total: 0</p>
26
19
  </div>
27
20
  <p class="empty">No tools found.</p>
28
21
  </div>`;
@@ -34,7 +27,7 @@ export function renderToolsCatalog(tools) {
34
27
  .map((tool) => {
35
28
  const searchable = `${tool.name} ${tool.description}`.toLowerCase();
36
29
  return ` <div class="tool-card" data-searchable="${searchable}">
37
- <h3>${tool.name} ${renderTierBadge(tool.tier)}</h3>
30
+ <h3>${tool.name}</h3>
38
31
  <p>${tool.description}</p>
39
32
  </div>`;
40
33
  })
@@ -47,7 +40,7 @@ ${cards}
47
40
  .join('\n');
48
41
  return `<div class="tools-catalog">
49
42
  <div class="tools-summary">
50
- <p>Total: ${String(tools.length)} | Free: ${String(freeCount)} | Pro: ${String(proCount)}</p>
43
+ <p>Total: ${String(tools.length)}</p>
51
44
  </div>
52
45
  ${sections}
53
46
  </div>`;
@@ -1,11 +1,22 @@
1
1
  import type { Spec } from '../../types/spec/core.js';
2
- import type { EvidenceArtifacts } from '../../types/evidence-gates.js';
2
+ import type { EvidenceArtifacts, TraceabilityMatrixEvidence } from '../../types/evidence-gates.js';
3
3
  /** Digest of canonical artifact content; the provenance envelope is excluded. */
4
4
  export declare function evidenceArtifactDigest(artifact: unknown): string;
5
5
  export declare function evidenceArtifactCollectionDigest(artifacts: readonly {
6
6
  kind: string;
7
7
  provenance?: unknown;
8
8
  }[]): string;
9
+ /** Verify legacy test-backed evidence without admitting prose-only traceability rows. */
10
+ export declare function traceabilityRowHasCurrentTestEvidence(row: TraceabilityMatrixEvidence['rows'][number], args: {
11
+ projectPath: string;
12
+ }): boolean;
13
+ /** Verify strict command evidence against current repository inputs and the validation ledger. */
14
+ export declare function traceabilityRowHasCurrentCommandEvidence(row: TraceabilityMatrixEvidence['rows'][number], args: {
15
+ projectId: string;
16
+ projectPath: string;
17
+ }): boolean;
18
+ /** SPEC-1356: exported so evidence-autofill (and other producers) target the same path convention. */
19
+ export declare function handoffEvidencePath(projectId: string, specId: string, filename: string): string;
9
20
  export declare function readEvidenceArtifacts(args: {
10
21
  spec: Spec;
11
22
  projectId: string;
@@ -1,12 +1,30 @@
1
1
  import { technologyValue } from '../technology-registry.js';
2
2
  import { readFile } from 'node:fs/promises';
3
+ import { lstatSync, realpathSync } from 'node:fs';
3
4
  import { createHash } from 'node:crypto';
4
- import { join } from 'node:path';
5
+ import { isAbsolute, join, relative, resolve } from 'node:path';
5
6
  import { z } from 'zod';
6
7
  import { projectDataDir } from '../../storage/base-store.js';
8
+ import { computeValidationEvidenceIdentity, computeValidationEvidenceKey, normalizeValidationCommand, readMatchingValidationEvidence, } from '../validation-evidence-ledger.js';
9
+ import { VALIDATION_COMMANDS } from '../validation-impact-planner.js';
7
10
  const DIGEST = /^sha256:[a-f0-9]{64}$/u;
8
11
  const SPEC_ID = /^SPEC-[1-9]\d*$/u;
9
12
  const ISSUER_ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;
13
+ const EVIDENCE_KEY = /^[a-f0-9]{64}$/u;
14
+ const ValidationGateCapabilitySchema = z.enum([
15
+ 'typecheck',
16
+ 'lint',
17
+ 'test-related',
18
+ 'test-full',
19
+ 'contract',
20
+ 'coverage',
21
+ 'migration',
22
+ 'fault-injection',
23
+ 'security',
24
+ 'native',
25
+ 'website',
26
+ 'reproducibility',
27
+ ]);
10
28
  const ProvenanceSchema = z
11
29
  .object({
12
30
  receiptId: z.string().regex(DIGEST),
@@ -69,6 +87,16 @@ const TraceabilityMatrixSchema = z
69
87
  changedFiles: z.array(z.string().min(1)).max(200),
70
88
  validationEvidence: z.string().optional(),
71
89
  reviewerEvidence: z.string().optional(),
90
+ commandEvidence: z
91
+ .object({
92
+ capability: ValidationGateCapabilitySchema,
93
+ command: z.string().min(1),
94
+ scope: z.array(z.string().min(1)).min(1).max(200),
95
+ relevantPaths: z.array(z.string().min(1)).min(1).max(200).optional(),
96
+ evidenceKey: z.string().regex(EVIDENCE_KEY),
97
+ })
98
+ .strict()
99
+ .optional(),
72
100
  })
73
101
  .strict())
74
102
  .max(1000),
@@ -118,10 +146,95 @@ export function evidenceArtifactCollectionDigest(artifacts) {
118
146
  .map((artifact) => ({ kind: artifact.kind, digest: evidenceArtifactDigest(artifact) }))
119
147
  .sort((left, right) => left.kind.localeCompare(right.kind)));
120
148
  }
149
+ function safeRepositoryPath(path) {
150
+ const normalized = path.trim().replaceAll('\\', '/').replace(/^\.\//u, '');
151
+ return (normalized.length > 0 &&
152
+ !normalized.startsWith('/') &&
153
+ !/^[A-Za-z]:/u.test(normalized) &&
154
+ normalized
155
+ .split('/')
156
+ .every((segment) => segment.length > 0 && segment !== '.' && segment !== '..'));
157
+ }
158
+ function repositoryEvidencePathsAreCurrent(row, projectPath, additionalPaths = []) {
159
+ let repositoryRoot;
160
+ try {
161
+ repositoryRoot = realpathSync(projectPath);
162
+ }
163
+ catch {
164
+ return false;
165
+ }
166
+ const paths = [
167
+ ...row.changedFiles,
168
+ ...(row.testEvidence ?? []),
169
+ ...(row.contractEvidence ?? []),
170
+ ...additionalPaths,
171
+ ];
172
+ return (paths.length > 0 &&
173
+ paths.every((path) => {
174
+ if (!safeRepositoryPath(path)) {
175
+ return false;
176
+ }
177
+ const candidate = resolve(repositoryRoot, path);
178
+ try {
179
+ if (lstatSync(candidate).isSymbolicLink()) {
180
+ return false;
181
+ }
182
+ const realPath = realpathSync(candidate);
183
+ const relativePath = relative(repositoryRoot, realPath);
184
+ return (relativePath.length > 0 &&
185
+ relativePath.split(/[\\/]/u)[0] !== '..' &&
186
+ !isAbsolute(relativePath));
187
+ }
188
+ catch {
189
+ return false;
190
+ }
191
+ }));
192
+ }
193
+ function isExecutableTestPath(path) {
194
+ return /(?:^|\/)[^/]+\.(?:test|spec)\.[cm]?[jt]sx?$/u.test(path.replaceAll('\\', '/'));
195
+ }
196
+ /** Verify legacy test-backed evidence without admitting prose-only traceability rows. */
197
+ export function traceabilityRowHasCurrentTestEvidence(row, args) {
198
+ return (row.commandEvidence === undefined &&
199
+ row.changedFiles.length > 0 &&
200
+ (row.testEvidence?.length ?? 0) > 0 &&
201
+ row.testEvidence?.every(isExecutableTestPath) === true &&
202
+ Boolean(row.validationEvidence?.trim()) &&
203
+ Boolean(row.reviewerEvidence?.trim()) &&
204
+ repositoryEvidencePathsAreCurrent(row, args.projectPath));
205
+ }
206
+ /** Verify strict command evidence against current repository inputs and the validation ledger. */
207
+ export function traceabilityRowHasCurrentCommandEvidence(row, args) {
208
+ const evidence = row.commandEvidence;
209
+ const expectedCommand = evidence
210
+ ? VALIDATION_COMMANDS[evidence.capability]
211
+ : undefined;
212
+ if (!evidence ||
213
+ !expectedCommand ||
214
+ normalizeValidationCommand(evidence.command) !== normalizeValidationCommand(expectedCommand)) {
215
+ return false;
216
+ }
217
+ const repositoryPaths = [...(evidence.relevantPaths ?? [])];
218
+ if (row.changedFiles.length === 0 ||
219
+ !repositoryEvidencePathsAreCurrent(row, args.projectPath, repositoryPaths) ||
220
+ evidence.scope.some((path) => !safeRepositoryPath(path))) {
221
+ return false;
222
+ }
223
+ const input = {
224
+ projectPath: args.projectPath,
225
+ capability: evidence.capability,
226
+ command: evidence.command,
227
+ scope: evidence.scope,
228
+ ...(evidence.relevantPaths === undefined ? {} : { relevantPaths: evidence.relevantPaths }),
229
+ };
230
+ const currentKey = computeValidationEvidenceKey(computeValidationEvidenceIdentity(input));
231
+ return (currentKey === evidence.evidenceKey &&
232
+ readMatchingValidationEvidence(args.projectId, input)?.status === 'passed');
233
+ }
121
234
  const ARTIFACT_HINTS = {
122
235
  'Discovery evidence': 'Expected discovery.json with { version: 1, rules: string[], examples: [{ rule, example }], openQuestions: [{ question, status, resolution? }], outOfScope: string[], glossary: [{ term, meaning }] }.',
123
236
  'Task plan evidence': 'Expected task-plan.json with { version: 1, tasks: [{ id, title, acceptanceCriteria: string[], status: "pending"|"doing"|"done" }] }. Acceptance criteria may be full text or stable IDs such as AC1 when they map to the canonical criteria order.',
124
- 'Traceability matrix evidence': 'Expected traceability-matrix.json with { version: 1, rows: [{ acceptanceCriterion, scenario?, testEvidence?, contractEvidence?, manualEvidence?, changedFiles: string[], validationEvidence?, reviewerEvidence? }] }.',
237
+ 'Traceability matrix evidence': 'Expected traceability-matrix.json with { version: 1, rows: [{ acceptanceCriterion, scenario?, testEvidence?, contractEvidence?, manualEvidence?, changedFiles: string[], validationEvidence?, reviewerEvidence?, commandEvidence?: { capability, command, scope, relevantPaths?, evidenceKey } }] }.',
125
238
  'contract-validation-api.json': 'Expected filename contract-validation-api.json with { version: 1, kind: "api", passed: boolean, reportPath?, summary? }.',
126
239
  'contract-validation-graphql.json': 'Expected filename contract-validation-graphql.json with { version: 1, kind: "graphql", passed: boolean, reportPath?, summary? }.',
127
240
  'contract-validation-event.json': 'Expected filename contract-validation-event.json with { version: 1, kind: "event", passed: boolean, reportPath?, summary? }.',
@@ -131,7 +244,58 @@ const ARTIFACT_HINTS = {
131
244
  function artifactHint(label) {
132
245
  return ARTIFACT_HINTS[label] ?? '';
133
246
  }
134
- function handoffEvidencePath(projectId, specId, filename) {
247
+ /**
248
+ * SPEC-1356 / AC5: compact JSON literal per artifact kind, appended verbatim to
249
+ * schema-validation errors so a retrying caller sees the exact expected shape
250
+ * instead of re-deriving it from prose.
251
+ */
252
+ const ARTIFACT_EXAMPLES = {
253
+ 'Discovery evidence': JSON.stringify({
254
+ version: 1,
255
+ rules: ['Rule text'],
256
+ examples: [{ rule: 'Rule text', example: 'Example text' }],
257
+ openQuestions: [{ question: 'Open question?', status: 'open' }],
258
+ outOfScope: ['Not in scope item'],
259
+ glossary: [{ term: 'Term', meaning: 'Meaning' }],
260
+ }),
261
+ 'Task plan evidence': JSON.stringify({
262
+ version: 1,
263
+ tasks: [{ id: 'T1', title: 'Task title', acceptanceCriteria: ['AC1'], status: 'pending' }],
264
+ }),
265
+ 'Traceability matrix evidence': JSON.stringify({
266
+ version: 1,
267
+ rows: [
268
+ {
269
+ acceptanceCriterion: 'AC text',
270
+ testEvidence: ['tests/example.test.ts'],
271
+ changedFiles: ['src/example.ts'],
272
+ validationEvidence: 'validate passed with score 100',
273
+ reviewerEvidence: 'planu-implementation-reviewer approved',
274
+ },
275
+ ],
276
+ }),
277
+ // Contract kinds are derived from the artifact filenames so no
278
+ // configurable technology literal is hardcoded here (audit:hardcodes).
279
+ ...Object.fromEntries([
280
+ 'contract-validation-api.json',
281
+ 'contract-validation-graphql.json',
282
+ 'contract-validation-event.json',
283
+ 'contract-validation-ui.json',
284
+ 'contract-validation-mcp.json',
285
+ ].map((label) => [
286
+ label,
287
+ JSON.stringify({
288
+ version: 1,
289
+ kind: label.slice('contract-validation-'.length, -'.json'.length),
290
+ passed: true,
291
+ }),
292
+ ])),
293
+ };
294
+ function artifactExample(label) {
295
+ return ARTIFACT_EXAMPLES[label] ?? '';
296
+ }
297
+ /** SPEC-1356: exported so evidence-autofill (and other producers) target the same path convention. */
298
+ export function handoffEvidencePath(projectId, specId, filename) {
135
299
  return join(projectDataDir(projectId), 'handoffs', specId, filename);
136
300
  }
137
301
  async function readUnknown(paths) {
@@ -160,7 +324,13 @@ async function readOptional(args) {
160
324
  }
161
325
  const parsed = args.schema.safeParse(found.value);
162
326
  if (!parsed.success) {
163
- args.invalidArtifacts.push(`${args.label} is invalid at ${found.path}: ${parsed.error.issues.map((issue) => issue.message).join('; ')} ${artifactHint(args.label)}`.trim());
327
+ // SPEC-1356 / AC5: surface every Zod issue (field path + message), not just the
328
+ // first one, so a single retry can fix every constraint violation at once.
329
+ const allIssues = parsed.error.issues
330
+ .map((issue) => `${issue.path.length > 0 ? issue.path.join('.') : '(root)'}: ${issue.message}`)
331
+ .join('; ');
332
+ const example = artifactExample(args.label);
333
+ args.invalidArtifacts.push(`${args.label} is invalid at ${found.path}: ${allIssues} ${artifactHint(args.label)}${example ? ` Expected shape example: ${example}` : ''}`.trim());
164
334
  return undefined;
165
335
  }
166
336
  return parsed.data;
@@ -0,0 +1,10 @@
1
+ import type { AutofillTraceabilityMatrixArgs, AutofillTraceabilityMatrixResult } from '../../types/evidence-autofill.js';
2
+ /**
3
+ * Generate `traceability-matrix.json` in the handoff evidence store when it does
4
+ * not already exist. Never overwrites an existing file — if one is present this
5
+ * is a no-op that reports `already-exists`. Tolerates every failure by returning
6
+ * a typed non-throwing result; callers must never let this crash a lifecycle
7
+ * transition.
8
+ */
9
+ export declare function autofillTraceabilityMatrix(args: AutofillTraceabilityMatrixArgs): Promise<AutofillTraceabilityMatrixResult>;
10
+ //# sourceMappingURL=evidence-autofill.d.ts.map
@@ -0,0 +1,148 @@
1
+ // engine/evidence-gates/evidence-autofill.ts — SPEC-1356: automated lifecycle evidence pipeline
2
+ //
3
+ // Generates traceability-matrix.json in the handoff evidence store when it is
4
+ // missing, so a `done` transition never fails purely because nobody hand-wrote
5
+ // the traceability artifact.
6
+ //
7
+ // ORDERING CAVEAT (documented per SPEC-1356 T-A3): writing traceability-matrix.json
8
+ // *after* `validate` has already computed and bound durable validation receipts
9
+ // would make those bindings stale relative to the newly-written evidence — the
10
+ // receipt would be certifying a repository state that does not include this file.
11
+ // This module does NOT attempt to re-run or re-bind validation. Instead, callers
12
+ // (see `src/tools/update-status/index.ts`) MUST treat a write from this module as
13
+ // "evidence created, not yet bound": when autofill actually writes the file, the
14
+ // caller must block the `done` transition with a message telling the operator to
15
+ // re-run `validate` once so the freshly-created evidence gets bound, then retry
16
+ // `done`. This is the simpler, safe choice given SPEC-1356 could not fully verify
17
+ // that skipping straight through to the done gates after autofill would keep
18
+ // receipt bindings correct in every code path (reconciliation, forced bypass,
19
+ // legacy harnesses, etc.).
20
+ import { execFile } from 'node:child_process';
21
+ import { existsSync } from 'node:fs';
22
+ import { isAbsolute, join, resolve } from 'node:path';
23
+ import { promisify } from 'node:util';
24
+ import { extractAcceptanceCriteriaTexts } from '../spec-format/acceptance-criteria.js';
25
+ import { parseFrontmatterScenarios } from '../validator/spec-compliance-runner.js';
26
+ import { extractCanonicalFileOwnership } from '../handoff-packager.js';
27
+ import { handoffEvidencePath } from './artifact-reader.js';
28
+ import { atomicWriteFile } from '../safety/atomic-write-file.js';
29
+ import { ValidationReportV1Schema } from '../handoff-artifacts/schemas.js';
30
+ import { projectDataDir } from '../../storage/base-store.js';
31
+ import { readFile } from 'node:fs/promises';
32
+ import { reportClassifiedDegradation } from '../../errors/classified-degradation.js';
33
+ const execFileAsync = promisify(execFile);
34
+ const defaultExec = async (command, args, options) => {
35
+ const { stdout } = await execFileAsync(command, args, { cwd: options.cwd, encoding: 'utf-8' });
36
+ return stdout;
37
+ };
38
+ /** Best-effort `git diff --name-only <mergeBase>...HEAD`; never throws. */
39
+ async function computeChangedFilesFromGit(projectPath, exec, baseBranch) {
40
+ try {
41
+ const mergeBaseOut = await exec('git', ['merge-base', 'HEAD', baseBranch], {
42
+ cwd: projectPath,
43
+ });
44
+ const mergeBase = mergeBaseOut.trim();
45
+ if (!mergeBase) {
46
+ return [];
47
+ }
48
+ const diffOut = await exec('git', ['diff', '--name-only', `${mergeBase}...HEAD`], {
49
+ cwd: projectPath,
50
+ });
51
+ return diffOut
52
+ .split('\n')
53
+ .map((line) => line.trim())
54
+ .filter((line) => line.length > 0);
55
+ }
56
+ catch (error) {
57
+ /* reliability-optional: EVIDENCE_AUTOFILL_GIT_DIFF — falls back to ## Files ownership */
58
+ reportClassifiedDegradation('EVIDENCE_AUTOFILL_GIT_DIFF', error);
59
+ return [];
60
+ }
61
+ }
62
+ function filterExistingRepoFiles(projectPath, paths) {
63
+ return paths.filter((path) => {
64
+ if (isAbsolute(path)) {
65
+ return false;
66
+ }
67
+ try {
68
+ return existsSync(resolve(projectPath, path));
69
+ }
70
+ catch {
71
+ return false;
72
+ }
73
+ });
74
+ }
75
+ /** Best-effort read + sha256 summary of the persisted validation report, for prose evidence. */
76
+ async function readValidationReportSummary(projectId, specId) {
77
+ const reportPath = join(projectDataDir(projectId), 'handoffs', specId, 'validation-report.json');
78
+ try {
79
+ const raw = await readFile(reportPath, 'utf-8');
80
+ const parsed = ValidationReportV1Schema.safeParse(JSON.parse(raw));
81
+ if (!parsed.success) {
82
+ return {};
83
+ }
84
+ const { score, reviewer } = parsed.data;
85
+ return {
86
+ validationEvidence: `Validated by handoffs/${specId}/validation-report.json (score=${score ?? 'n/a'}).`,
87
+ reviewerEvidence: `Reviewed by ${reviewer.agent} (${reviewer.kind}), verdict=${reviewer.verdict}.`,
88
+ };
89
+ }
90
+ catch {
91
+ return {};
92
+ }
93
+ }
94
+ /**
95
+ * Generate `traceability-matrix.json` in the handoff evidence store when it does
96
+ * not already exist. Never overwrites an existing file — if one is present this
97
+ * is a no-op that reports `already-exists`. Tolerates every failure by returning
98
+ * a typed non-throwing result; callers must never let this crash a lifecycle
99
+ * transition.
100
+ */
101
+ export async function autofillTraceabilityMatrix(args) {
102
+ const targetPath = handoffEvidencePath(args.projectId, args.specId, 'traceability-matrix.json');
103
+ try {
104
+ if (existsSync(targetPath)) {
105
+ return { written: false, reason: 'already-exists' };
106
+ }
107
+ const criteria = extractAcceptanceCriteriaTexts(args.specBody);
108
+ if (criteria.length === 0) {
109
+ return { written: false, reason: 'no-criteria' };
110
+ }
111
+ const scenarios = parseFrontmatterScenarios(args.specBody);
112
+ const exec = args.exec ?? defaultExec;
113
+ const baseBranch = args.baseBranch ?? 'main';
114
+ const gitChangedFiles = args.projectPath
115
+ ? await computeChangedFilesFromGit(args.projectPath, exec, baseBranch)
116
+ : [];
117
+ const ownership = extractCanonicalFileOwnership(args.specBody);
118
+ const ownershipFiles = [...ownership.toCreate, ...ownership.toModify, ...ownership.toTest];
119
+ const rawChangedFiles = gitChangedFiles.length > 0 ? gitChangedFiles : ownershipFiles;
120
+ const changedFiles = args.projectPath
121
+ ? filterExistingRepoFiles(args.projectPath, rawChangedFiles)
122
+ : rawChangedFiles;
123
+ const { validationEvidence, reviewerEvidence } = await readValidationReportSummary(args.projectId, args.specId);
124
+ const rows = criteria.map((acceptanceCriterion, index) => {
125
+ const testPaths = scenarios[index]?.tests?.map((test) => test.path) ?? [];
126
+ return {
127
+ acceptanceCriterion,
128
+ ...(testPaths.length > 0 ? { testEvidence: testPaths } : {}),
129
+ changedFiles,
130
+ ...(validationEvidence ? { validationEvidence } : {}),
131
+ ...(reviewerEvidence ? { reviewerEvidence } : {}),
132
+ };
133
+ });
134
+ const payload = { version: 1, rows };
135
+ await atomicWriteFile(targetPath, JSON.stringify(payload, null, 2));
136
+ return { written: true, path: targetPath, rowCount: rows.length };
137
+ }
138
+ catch (error) {
139
+ /* reliability-optional: EVIDENCE_AUTOFILL_WRITE — caller proceeds without autofill */
140
+ reportClassifiedDegradation('EVIDENCE_AUTOFILL_WRITE', error);
141
+ return {
142
+ written: false,
143
+ reason: 'write-failed',
144
+ error: error instanceof Error ? error.message : String(error),
145
+ };
146
+ }
147
+ }
148
+ //# sourceMappingURL=evidence-autofill.js.map
@@ -0,0 +1,19 @@
1
+ import type { Spec } from '../../types/spec/core.js';
2
+ import type { DiscoveryEvidence, TaskPlanEvidence } from '../../types/evidence-gates.js';
3
+ /** Build a strict-schema discovery.json skeleton grounded in the spec's own grounding metadata. */
4
+ export declare function generateDiscoverySkeleton(args: {
5
+ spec: Spec;
6
+ body: string | null;
7
+ }): DiscoveryEvidence;
8
+ /** Build a strict-schema task-plan.json skeleton with one pending task per canonical criterion. */
9
+ export declare function generateTaskPlanSkeleton(args: {
10
+ criteria: string[];
11
+ }): TaskPlanEvidence;
12
+ /** Persist an auto-generated evidence skeleton to the external handoff store. */
13
+ export declare function writeEvidenceSkeleton(args: {
14
+ projectId: string;
15
+ specId: string;
16
+ filename: string;
17
+ artifact: DiscoveryEvidence | TaskPlanEvidence;
18
+ }): Promise<string>;
19
+ //# sourceMappingURL=evidence-skeletons.d.ts.map