@planu/cli 4.14.1 → 5.0.0

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 (424) hide show
  1. package/CHANGELOG.md +35 -1
  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 +2 -2
  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 +1 -1
  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 +10 -1
  46. package/dist/engine/evidence-gates/artifact-reader.js +115 -2
  47. package/dist/engine/evidence-gates/lifecycle-gate.js +4 -3
  48. package/dist/engine/evidence-gates/reconciliation-freshness.d.ts +11 -0
  49. package/dist/engine/evidence-gates/reconciliation-freshness.js +72 -0
  50. package/dist/engine/evidence-index/done-drift.d.ts +1 -1
  51. package/dist/engine/evidence-index/done-drift.js +40 -18
  52. package/dist/engine/execution/context.js +3 -0
  53. package/dist/engine/execution/durable-job-heartbeat-runtime.d.ts +4 -0
  54. package/dist/engine/execution/durable-job-heartbeat-runtime.js +400 -0
  55. package/dist/engine/execution/job-runtime.d.ts +30 -0
  56. package/dist/engine/execution/job-runtime.js +114 -6
  57. package/dist/engine/execution/public-job-sanitizer.d.ts +4 -0
  58. package/dist/engine/execution/public-job-sanitizer.js +31 -0
  59. package/dist/engine/execution/validate-job-executor.d.ts +12 -1
  60. package/dist/engine/execution/validate-job-executor.js +549 -86
  61. package/dist/engine/execution/validate-job-payload.js +107 -50
  62. package/dist/engine/execution/validate-job-recovery.js +1 -1
  63. package/dist/engine/execution/validate-worker-runtime.d.ts +5 -0
  64. package/dist/engine/execution/validate-worker-runtime.js +90 -2
  65. package/dist/engine/execution/validate-worker-thread.js +17 -24
  66. package/dist/engine/handoff-artifacts/schemas.d.ts +2 -1
  67. package/dist/engine/handoff-artifacts/schemas.js +33 -0
  68. package/dist/engine/handoff-packager.d.ts +19 -0
  69. package/dist/engine/handoff-packager.js +415 -13
  70. package/dist/engine/hooks/effort-configurator.js +1 -1
  71. package/dist/engine/impact-detector/test-break-predictor.js +3 -3
  72. package/dist/engine/impact-detector/tool-registration.js +1 -1
  73. package/dist/engine/implementation-contract/renderer.js +23 -8
  74. package/dist/engine/lifecycle-reconciliation-io.d.ts +11 -0
  75. package/dist/engine/lifecycle-reconciliation-io.js +180 -0
  76. package/dist/engine/lifecycle-reconciliation.d.ts +16 -0
  77. package/dist/engine/lifecycle-reconciliation.js +406 -0
  78. package/dist/engine/local-first/tool-classification.js +2 -0
  79. package/dist/engine/macos-keychain-native-port.d.ts +5 -0
  80. package/dist/engine/macos-keychain-native-port.js +19 -7
  81. package/dist/engine/migrations/remove-commercial-state.d.ts +3 -0
  82. package/dist/engine/migrations/remove-commercial-state.js +343 -0
  83. package/dist/engine/network-policy.js +1 -0
  84. package/dist/engine/planu-core.darwin-arm64.node.manifest.json +7 -7
  85. package/dist/engine/planu-core.darwin-arm64.node.sbom.json +10 -10
  86. package/dist/engine/planu-core.darwin-x64.node.manifest.json +7 -7
  87. package/dist/engine/planu-core.darwin-x64.node.sbom.json +10 -10
  88. package/dist/engine/planu-core.linux-arm64-gnu.node.manifest.json +7 -7
  89. package/dist/engine/planu-core.linux-arm64-gnu.node.sbom.json +10 -10
  90. package/dist/engine/planu-core.linux-arm64-musl.node.manifest.json +7 -7
  91. package/dist/engine/planu-core.linux-arm64-musl.node.sbom.json +10 -10
  92. package/dist/engine/planu-core.linux-x64-gnu.node.manifest.json +7 -7
  93. package/dist/engine/planu-core.linux-x64-gnu.node.sbom.json +10 -10
  94. package/dist/engine/planu-core.linux-x64-musl.node.manifest.json +7 -7
  95. package/dist/engine/planu-core.linux-x64-musl.node.sbom.json +10 -10
  96. package/dist/engine/planu-core.win32-arm64-msvc.node.manifest.json +7 -7
  97. package/dist/engine/planu-core.win32-arm64-msvc.node.sbom.json +10 -10
  98. package/dist/engine/planu-core.win32-x64-msvc.node.manifest.json +7 -7
  99. package/dist/engine/planu-core.win32-x64-msvc.node.sbom.json +10 -10
  100. package/dist/engine/readiness-checker.d.ts +1 -16
  101. package/dist/engine/readiness-checker.js +27 -88
  102. package/dist/engine/runtime-policy.d.ts +2 -0
  103. package/dist/engine/runtime-policy.js +42 -5
  104. package/dist/engine/runtime-security/rate-limiter.js +0 -1
  105. package/dist/engine/safety/contained-project-file.d.ts +3 -0
  106. package/dist/engine/safety/contained-project-file.js +23 -0
  107. package/dist/engine/scope-boundaries/contradiction-checker.js +63 -1
  108. package/dist/engine/scope-boundaries/scope-validator.js +45 -7
  109. package/dist/engine/session/checkpoint-writer.js +0 -9
  110. package/dist/engine/spec-format/acceptance-criteria.d.ts +6 -2
  111. package/dist/engine/spec-format/acceptance-criteria.js +77 -18
  112. package/dist/engine/spec-format/markdown-sections.d.ts +14 -0
  113. package/dist/engine/spec-format/markdown-sections.js +105 -0
  114. package/dist/engine/spec-format/read-technical-section.js +33 -5
  115. package/dist/engine/spec-format/technical-md-populator.js +3 -2
  116. package/dist/engine/spec-format/unified-spec-builder.d.ts +7 -0
  117. package/dist/engine/spec-format/unified-spec-builder.js +202 -0
  118. package/dist/engine/spec-migrator/canonical-deduplicator.d.ts +18 -0
  119. package/dist/engine/spec-migrator/canonical-deduplicator.js +479 -0
  120. package/dist/engine/spec-migrator/filesystem-import.d.ts +4 -8
  121. package/dist/engine/spec-migrator/filesystem-import.js +121 -14
  122. package/dist/engine/spec-migrator/frontmatter-parser.js +32 -15
  123. package/dist/engine/spec-migrator/index.d.ts +1 -0
  124. package/dist/engine/spec-migrator/index.js +1 -0
  125. package/dist/engine/spec-state-machine/transition-spec.d.ts +6 -1
  126. package/dist/engine/spec-state-machine/transition-spec.js +10 -1
  127. package/dist/engine/technical-enricher/index.js +16 -8
  128. package/dist/engine/technical-enricher/render-enriched.d.ts +1 -0
  129. package/dist/engine/technical-enricher/render-enriched.js +42 -14
  130. package/dist/engine/telemetry/health-checker.js +53 -17
  131. package/dist/engine/telemetry/telemetry-client.js +26 -8
  132. package/dist/engine/text-signal-boundaries.d.ts +2 -0
  133. package/dist/engine/text-signal-boundaries.js +25 -2
  134. package/dist/engine/time/relative-date.d.ts +3 -0
  135. package/dist/engine/time/relative-date.js +16 -0
  136. package/dist/engine/timing/budget.d.ts +11 -0
  137. package/dist/engine/timing/budget.js +27 -9
  138. package/dist/engine/token-optimizer/analytics.d.ts +1 -1
  139. package/dist/engine/token-optimizer/analytics.js +5 -6
  140. package/dist/engine/usage-tracker/core.d.ts +2 -2
  141. package/dist/engine/usage-tracker/core.js +1 -2
  142. package/dist/engine/usage-tracker/index.d.ts +0 -3
  143. package/dist/engine/usage-tracker/index.js +0 -3
  144. package/dist/engine/usage-tracker/stats.d.ts +2 -2
  145. package/dist/engine/usage-tracker/stats.js +1 -28
  146. package/dist/engine/validation/durable-validation.d.ts +1 -1
  147. package/dist/engine/validation/durable-validation.js +3 -82
  148. package/dist/engine/validation/validation-freshness.d.ts +11 -1
  149. package/dist/engine/validation/validation-freshness.js +231 -91
  150. package/dist/engine/validation/validation-receipt.d.ts +9 -6
  151. package/dist/engine/validation/validation-receipt.js +84 -24
  152. package/dist/engine/validation/validation-source-digest.d.ts +2 -0
  153. package/dist/engine/validation/validation-source-digest.js +86 -0
  154. package/dist/engine/validation/validation-submission.d.ts +5 -4
  155. package/dist/engine/validation/validation-submission.js +25 -11
  156. package/dist/engine/validation/validation-worktree.d.ts +21 -0
  157. package/dist/engine/validation/validation-worktree.js +260 -0
  158. package/dist/engine/validation-impact-planner.d.ts +14 -2
  159. package/dist/engine/validation-impact-planner.js +0 -3
  160. package/dist/engine/validator/dor-dod.d.ts +1 -0
  161. package/dist/engine/validator/dor-dod.js +5 -3
  162. package/dist/engine/validator/extractors.d.ts +1 -5
  163. package/dist/engine/validator/extractors.js +24 -69
  164. package/dist/engine/validator/spec-compliance-runner.d.ts +12 -24
  165. package/dist/engine/validator/spec-compliance-runner.js +429 -211
  166. package/dist/engine/validator.js +35 -22
  167. package/dist/index.js +4 -16
  168. package/dist/resources/usage-stats-resource.js +2 -18
  169. package/dist/security/adapters/linux-secret-service.js +7 -3
  170. package/dist/security/adapters/windows-credential-manager.js +6 -4
  171. package/dist/server/routes/specs.js +10 -0
  172. package/dist/storage/base-store.d.ts +1 -1
  173. package/dist/storage/base-store.js +1 -1
  174. package/dist/storage/feedback-remote.d.ts +2 -3
  175. package/dist/storage/feedback-remote.js +45 -31
  176. package/dist/storage/global-store.d.ts +1 -17
  177. package/dist/storage/global-store.js +1 -42
  178. package/dist/storage/index.d.ts +0 -2
  179. package/dist/storage/index.js +0 -2
  180. package/dist/storage/migrations/canonical-storage.js +124 -11
  181. package/dist/storage/runtime-db.d.ts +9 -0
  182. package/dist/storage/runtime-db.js +64 -8
  183. package/dist/storage/spec-store.d.ts +14 -2
  184. package/dist/storage/spec-store.js +104 -14
  185. package/dist/storage/status-store/atomic-status-write.d.ts +5 -0
  186. package/dist/storage/status-store/atomic-status-write.js +57 -0
  187. package/dist/storage/status-store/file-lock.js +30 -11
  188. package/dist/storage/status-store/self-healing.js +3 -3
  189. package/dist/storage/status-store/version-sync.d.ts +2 -1
  190. package/dist/storage/status-store/version-sync.js +35 -40
  191. package/dist/storage/usage-store.d.ts +1 -5
  192. package/dist/storage/usage-store.js +0 -35
  193. package/dist/tools/auto-update-handler.d.ts +3 -3
  194. package/dist/tools/auto-update-handler.js +3 -3
  195. package/dist/tools/challenge-spec/resilience-challenge-scenarios.d.ts +2 -1
  196. package/dist/tools/challenge-spec/resilience-challenge-scenarios.js +10 -7
  197. package/dist/tools/challenge-spec/scenario-collector.js +1 -1
  198. package/dist/tools/challenge-spec/scenarios-data.js +1 -1
  199. package/dist/tools/challenge-spec/scenarios-utils.d.ts +1 -1
  200. package/dist/tools/challenge-spec/scenarios-utils.js +35 -11
  201. package/dist/tools/challenge-spec.js +5 -5
  202. package/dist/tools/check-readiness.js +1 -1
  203. package/dist/tools/configure-telemetry.js +30 -2
  204. package/dist/tools/create-spec/spec-builder.js +0 -11
  205. package/dist/tools/create-spec.d.ts +1 -0
  206. package/dist/tools/create-spec.js +444 -239
  207. package/dist/tools/git/branch-ops.d.ts +1 -1
  208. package/dist/tools/git/branch-ops.js +3 -2
  209. package/dist/tools/init-project/handler.js +10 -12
  210. package/dist/tools/init-project/host-assets-writer.js +26 -1
  211. package/dist/tools/init-project/lint-scaffolder.d.ts +3 -3
  212. package/dist/tools/init-project/migration-runner.d.ts +2 -4
  213. package/dist/tools/init-project/migration-runner.js +3 -2
  214. package/dist/tools/init-project/portable-index-reconciler.d.ts +4 -0
  215. package/dist/tools/init-project/portable-index-reconciler.js +14 -0
  216. package/dist/tools/init-project/result-builder.js +1 -3
  217. package/dist/tools/jobs/handlers.js +38 -6
  218. package/dist/tools/list-specs.js +5 -26
  219. package/dist/tools/merge-risk-handler.js +2 -2
  220. package/dist/tools/package-handoff.js +2 -0
  221. package/dist/tools/reconcile-spec.js +0 -27
  222. package/dist/tools/register-agent-squad-tools.js +2 -2
  223. package/dist/tools/register-platform-tools/design-stack-tools.js +11 -11
  224. package/dist/tools/register-platform-tools/lifecycle-infra-tools.js +7 -7
  225. package/dist/tools/register-sdd-tools.d.ts +1 -1
  226. package/dist/tools/register-sdd-tools.js +2 -29
  227. package/dist/tools/register-spec-tools/analysis-tools.js +8 -8
  228. package/dist/tools/register-spec-tools/core-spec-tools.js +17 -8
  229. package/dist/tools/safe-handler.d.ts +5 -13
  230. package/dist/tools/safe-handler.js +7 -23
  231. package/dist/tools/schemas/index.d.ts +1 -1
  232. package/dist/tools/schemas/index.js +1 -1
  233. package/dist/tools/schemas/output-schemas.d.ts +0 -23
  234. package/dist/tools/schemas/output-schemas.js +0 -28
  235. package/dist/tools/schemas/spec.d.ts +4 -0
  236. package/dist/tools/schemas/spec.js +3 -0
  237. package/dist/tools/schemas/validate-output-schema.d.ts +11 -0
  238. package/dist/tools/schemas/validate-output-schema.js +7 -0
  239. package/dist/tools/spec-prompt-handler.js +3 -3
  240. package/dist/tools/sync-spec-state-handler.d.ts +1 -1
  241. package/dist/tools/sync-spec-state-handler.js +1 -1
  242. package/dist/tools/tool-entry.d.ts +4 -4
  243. package/dist/tools/tool-entry.js +3 -3
  244. package/dist/tools/tool-registry/core-tools.js +31 -15
  245. package/dist/tools/tool-registry/group-infra.js +27 -110
  246. package/dist/tools/tool-registry/group-quality-compliance.js +26 -26
  247. package/dist/tools/tool-registry/inventory.d.ts +2 -0
  248. package/dist/tools/tool-registry/inventory.js +2 -0
  249. package/dist/tools/tool-registry-helpers.d.ts +3 -3
  250. package/dist/tools/tool-registry-helpers.js +3 -3
  251. package/dist/tools/tool-usage-report/registered-tools.d.ts +1 -1
  252. package/dist/tools/tool-usage-report/registered-tools.js +3 -15
  253. package/dist/tools/update-status/approval-gates.js +3 -0
  254. package/dist/tools/update-status/done-receipt-verifier.js +40 -27
  255. package/dist/tools/update-status/evidence-gate.js +36 -1
  256. package/dist/tools/update-status/file-sync.d.ts +2 -1
  257. package/dist/tools/update-status/file-sync.js +57 -6
  258. package/dist/tools/update-status/index.d.ts +2 -0
  259. package/dist/tools/update-status/index.js +95 -58
  260. package/dist/tools/update-status/response-builder.js +3 -3
  261. package/dist/tools/update-status/side-effects.d.ts +2 -0
  262. package/dist/tools/update-status/side-effects.js +2 -2
  263. package/dist/tools/update-status/transition-guard.js +32 -15
  264. package/dist/tools/update-status-actions.d.ts +4 -2
  265. package/dist/tools/update-status-actions.js +16 -14
  266. package/dist/tools/usage-report.js +1 -16
  267. package/dist/tools/usage-stats.js +1 -18
  268. package/dist/tools/usage-tracking.d.ts +4 -0
  269. package/dist/tools/usage-tracking.js +20 -0
  270. package/dist/tools/validate-lint.d.ts +1 -0
  271. package/dist/tools/validate-lint.js +1 -1
  272. package/dist/tools/validate.d.ts +2 -1
  273. package/dist/tools/validate.js +114 -34
  274. package/dist/transports/http-transport.js +6 -8
  275. package/dist/transports/mcp-types.d.ts +0 -2
  276. package/dist/transports/session-context.js +1 -1
  277. package/dist/types/cascade-hooks.d.ts +1 -1
  278. package/dist/types/ci.d.ts +0 -4
  279. package/dist/types/clarification-token.d.ts +1 -1
  280. package/dist/types/claude-code-runtime.d.ts +0 -27
  281. package/dist/types/commercial-migration.d.ts +17 -0
  282. package/dist/types/commercial-migration.js +2 -0
  283. package/dist/types/common/primitives.d.ts +0 -2
  284. package/dist/types/core-bridge.d.ts +4 -10
  285. package/dist/types/dashboard.d.ts +3 -7
  286. package/dist/types/docs.d.ts +0 -1
  287. package/dist/types/durable-job.d.ts +4 -4
  288. package/dist/types/durable-validation.d.ts +100 -2
  289. package/dist/types/durable-validation.js +165 -1
  290. package/dist/types/errors/structured-error.d.ts +3 -3
  291. package/dist/types/estimation.d.ts +2 -0
  292. package/dist/types/evidence-gates.d.ts +9 -1
  293. package/dist/types/execution.d.ts +2 -0
  294. package/dist/types/gemini-integration.d.ts +0 -11
  295. package/dist/types/handoff-artifacts.d.ts +41 -0
  296. package/dist/types/hooks-advanced.d.ts +0 -13
  297. package/dist/types/impact-detection.d.ts +2 -2
  298. package/dist/types/index.d.ts +2 -6
  299. package/dist/types/index.js +1 -5
  300. package/dist/types/kiro-integration.d.ts +0 -6
  301. package/dist/types/network-policy.d.ts +1 -1
  302. package/dist/types/project/lint-scaffolder.d.ts +1 -1
  303. package/dist/types/runtime-policy.d.ts +11 -0
  304. package/dist/types/session-safeguard.d.ts +0 -31
  305. package/dist/types/spec/canonical-repair.d.ts +81 -0
  306. package/dist/types/spec/canonical-repair.js +2 -0
  307. package/dist/types/spec/core.d.ts +14 -0
  308. package/dist/types/spec/index.d.ts +1 -0
  309. package/dist/types/spec/index.js +1 -0
  310. package/dist/types/spec/inputs.d.ts +29 -0
  311. package/dist/types/spec-format.d.ts +24 -0
  312. package/dist/types/telemetry.d.ts +4 -1
  313. package/dist/types/transport.d.ts +0 -2
  314. package/dist/types/usage.d.ts +1 -36
  315. package/dist/types/usage.js +1 -1
  316. package/dist/types/validate-worker.d.ts +6 -0
  317. package/dist/types/validation-receipt.d.ts +1 -1
  318. package/dist/types/validation.d.ts +2 -2
  319. package/package.json +16 -12
  320. package/planu-native.json +1 -1
  321. package/planu-plugin.json +23 -40
  322. package/scripts/lib/pending-release-file.mjs +93 -0
  323. package/src/i18n/messages/en.json +0 -41
  324. package/src/i18n/messages/es.json +0 -41
  325. package/src/i18n/messages/pt.json +0 -41
  326. package/dist/cli/commands/activate.d.ts +0 -14
  327. package/dist/cli/commands/activate.js +0 -174
  328. package/dist/config/license-plans.json +0 -251
  329. package/dist/config/product-public.ts +0 -148
  330. package/dist/config/server-instructions.ts +0 -121
  331. package/dist/config/version-defaults.ts +0 -76
  332. package/dist/config/version.ts +0 -21
  333. package/dist/engine/ai-integration/gemini/settings-generator.d.ts +0 -4
  334. package/dist/engine/ai-integration/gemini/settings-generator.js +0 -195
  335. package/dist/engine/ai-integration/kiro/hooks-generator.d.ts +0 -6
  336. package/dist/engine/ai-integration/kiro/hooks-generator.js +0 -75
  337. package/dist/engine/hooks/full-spectrum-generator.d.ts +0 -32
  338. package/dist/engine/hooks/full-spectrum-generator.js +0 -117
  339. package/dist/engine/license-validator/config-loader.d.ts +0 -5
  340. package/dist/engine/license-validator/config-loader.js +0 -16
  341. package/dist/engine/license-validator/core.d.ts +0 -15
  342. package/dist/engine/license-validator/core.js +0 -151
  343. package/dist/engine/license-validator/fingerprint.d.ts +0 -3
  344. package/dist/engine/license-validator/fingerprint.js +0 -17
  345. package/dist/engine/license-validator/lemon-squeezy.d.ts +0 -5
  346. package/dist/engine/license-validator/lemon-squeezy.js +0 -55
  347. package/dist/engine/license-validator.d.ts +0 -5
  348. package/dist/engine/license-validator.js +0 -6
  349. package/dist/engine/product-intelligence/index.d.ts +0 -7
  350. package/dist/engine/product-intelligence/index.js +0 -211
  351. package/dist/engine/session/auto-save.d.ts +0 -18
  352. package/dist/engine/session/auto-save.js +0 -98
  353. package/dist/engine/session/context-snapshot.d.ts +0 -8
  354. package/dist/engine/session/context-snapshot.js +0 -49
  355. package/dist/engine/session/memory-sync.d.ts +0 -12
  356. package/dist/engine/session/memory-sync.js +0 -34
  357. package/dist/engine/session/session-diff.d.ts +0 -11
  358. package/dist/engine/session/session-diff.js +0 -42
  359. package/dist/engine/session/session-merge.d.ts +0 -12
  360. package/dist/engine/session/session-merge.js +0 -55
  361. package/dist/engine/session-safeguard/checkpoint-runner.d.ts +0 -4
  362. package/dist/engine/session-safeguard/checkpoint-runner.js +0 -70
  363. package/dist/engine/session-safeguard/learnings-buffer.d.ts +0 -15
  364. package/dist/engine/session-safeguard/learnings-buffer.js +0 -91
  365. package/dist/engine/session-safeguard/precompaction-drain.d.ts +0 -10
  366. package/dist/engine/session-safeguard/precompaction-drain.js +0 -82
  367. package/dist/engine/session-safeguard/unpushed-detector.d.ts +0 -7
  368. package/dist/engine/session-safeguard/unpushed-detector.js +0 -59
  369. package/dist/engine/spec-changelog/core.d.ts +0 -16
  370. package/dist/engine/spec-changelog/core.js +0 -176
  371. package/dist/engine/spec-changelog/diff.d.ts +0 -18
  372. package/dist/engine/spec-changelog/diff.js +0 -121
  373. package/dist/engine/spec-changelog/index.d.ts +0 -3
  374. package/dist/engine/spec-changelog/index.js +0 -4
  375. package/dist/engine/trial-engine.d.ts +0 -5
  376. package/dist/engine/trial-engine.js +0 -14
  377. package/dist/engine/usage-tracker/rate-check.d.ts +0 -7
  378. package/dist/engine/usage-tracker/rate-check.js +0 -18
  379. package/dist/engine/usage-tracker/rate-limiter.d.ts +0 -14
  380. package/dist/engine/usage-tracker/rate-limiter.js +0 -73
  381. package/dist/engine/usage-tracker/trial.d.ts +0 -27
  382. package/dist/engine/usage-tracker/trial.js +0 -49
  383. package/dist/engine/webhook/event-handlers.d.ts +0 -25
  384. package/dist/engine/webhook/event-handlers.js +0 -89
  385. package/dist/engine/webhook/index.d.ts +0 -4
  386. package/dist/engine/webhook/index.js +0 -5
  387. package/dist/engine/webhook/server.d.ts +0 -12
  388. package/dist/engine/webhook/server.js +0 -249
  389. package/dist/engine/webhook/signature.d.ts +0 -16
  390. package/dist/engine/webhook/signature.js +0 -49
  391. package/dist/storage/license-store.d.ts +0 -6
  392. package/dist/storage/license-store.js +0 -63
  393. package/dist/storage/session-store.d.ts +0 -20
  394. package/dist/storage/session-store.js +0 -136
  395. package/dist/tools/activate-license.d.ts +0 -6
  396. package/dist/tools/activate-license.js +0 -132
  397. package/dist/tools/checkpoint-handler.d.ts +0 -3
  398. package/dist/tools/checkpoint-handler.js +0 -130
  399. package/dist/tools/export-session.d.ts +0 -3
  400. package/dist/tools/export-session.js +0 -90
  401. package/dist/tools/license-gate.d.ts +0 -18
  402. package/dist/tools/license-gate.js +0 -222
  403. package/dist/tools/license-status.d.ts +0 -3
  404. package/dist/tools/license-status.js +0 -93
  405. package/dist/tools/list-sessions.d.ts +0 -3
  406. package/dist/tools/list-sessions.js +0 -46
  407. package/dist/tools/planu-session-checkpoint.d.ts +0 -6
  408. package/dist/tools/planu-session-checkpoint.js +0 -42
  409. package/dist/tools/restore-session.d.ts +0 -3
  410. package/dist/tools/restore-session.js +0 -71
  411. package/dist/tools/spec-history.d.ts +0 -3
  412. package/dist/tools/spec-history.js +0 -59
  413. package/dist/tools/webhook.d.ts +0 -6
  414. package/dist/tools/webhook.js +0 -150
  415. package/dist/types/changelog.d.ts +0 -49
  416. package/dist/types/changelog.js +0 -3
  417. package/dist/types/licensing.d.ts +0 -109
  418. package/dist/types/licensing.js +0 -4
  419. package/dist/types/product-intelligence.d.ts +0 -60
  420. package/dist/types/product-intelligence.js +0 -3
  421. package/dist/types/session.d.ts +0 -84
  422. package/dist/types/session.js +0 -3
  423. package/dist/types/webhook.d.ts +0 -62
  424. package/dist/types/webhook.js +0 -4
@@ -1,8 +1,8 @@
1
- import type { FileHash, FileMetadata, SpecAnnotation, DriftResult, PlanuCore, DuplicateRawBlockRs, DuplicateBlockLocationRs, FastGrepMatch, FileContent, SpecBriefRs, AmbiguousCriterionRs, GapsLogChainResultRs, SearchResult, VectorNode, ProjectGraphSourceFileRs, TsRelationRs, GraphNodeInputRs, GraphEdgeInputRs, AffectedNodeRs, ShortestPathResultRs, CompactGraphSliceRs, CompactGraphEdgesRs, ProjectGraphLimitsPolicyRs, ResolvedProjectGraphLimitsRs, NativeRuntimeHandshake, NativeRuntimeCompatibility, NativeArtifactManifest, NativeLoadDiagnostic } from '../types/core-bridge.js';
1
+ import type { FileHash, FileMetadata, SpecAnnotation, DriftResult, PlanuCore, DuplicateRawBlockRs, DuplicateBlockLocationRs, FastGrepMatch, FileContent, SpecBriefRs, AmbiguousCriterionRs, GapsLogChainResultRs, NativeVectorSearchResult, VectorNode, ProjectGraphSourceFileRs, TsRelationRs, GraphNodeInputRs, GraphEdgeInputRs, AffectedNodeRs, ShortestPathResultRs, CompactGraphSliceRs, CompactGraphEdgesRs, ProjectGraphLimitsPolicyRs, ResolvedProjectGraphLimitsRs, NativeRuntimeHandshake, NativeRuntimeCompatibility, NativeArtifactManifest, NativeLoadDiagnostic } from '../types/core-bridge.js';
2
2
  import type { MacOSKeychainNativePort } from '../types/security.js';
3
3
  import { negotiateNativeRuntime, NATIVE_CAPABILITY_ABI, NATIVE_NODE_API_ABI, NATIVE_PROTOCOL_ABI, RUNTIME_STORAGE_SCHEMA } from './native-runtime-handshake.js';
4
4
  export { negotiateNativeRuntime, NATIVE_CAPABILITY_ABI, NATIVE_NODE_API_ABI, NATIVE_PROTOCOL_ABI, RUNTIME_STORAGE_SCHEMA, };
5
- export type { FileHash, FileMetadata, SpecAnnotation, DriftResult, PlanuCore, DuplicateRawBlockRs, DuplicateBlockLocationRs, FastGrepMatch, FileContent, SpecBriefRs, AmbiguousCriterionRs, GapsLogChainResultRs, SearchResult, VectorNode, ProjectGraphSourceFileRs, TsRelationRs, GraphNodeInputRs, GraphEdgeInputRs, AffectedNodeRs, ShortestPathResultRs, CompactGraphSliceRs, CompactGraphEdgesRs, ProjectGraphLimitsPolicyRs, ResolvedProjectGraphLimitsRs, NativeRuntimeHandshake, NativeRuntimeCompatibility, NativeArtifactManifest, NativeLoadDiagnostic as LoadDiagnostic, };
5
+ export type { FileHash, FileMetadata, SpecAnnotation, DriftResult, PlanuCore, DuplicateRawBlockRs, DuplicateBlockLocationRs, FastGrepMatch, FileContent, SpecBriefRs, AmbiguousCriterionRs, GapsLogChainResultRs, NativeVectorSearchResult, VectorNode, ProjectGraphSourceFileRs, TsRelationRs, GraphNodeInputRs, GraphEdgeInputRs, AffectedNodeRs, ShortestPathResultRs, CompactGraphSliceRs, CompactGraphEdgesRs, ProjectGraphLimitsPolicyRs, ResolvedProjectGraphLimitsRs, NativeRuntimeHandshake, NativeRuntimeCompatibility, NativeArtifactManifest, NativeLoadDiagnostic as LoadDiagnostic, };
6
6
  export declare function currentNativePackageName(): string | null;
7
7
  /** Main-thread port for async Keychain calls; never accepts override or unverified native code. */
8
8
  export declare function requireMacOSKeychainNativePort(): MacOSKeychainNativePort;
@@ -23,7 +23,7 @@ export declare function fastScanSpecs(rootPath: string): SpecBriefRs[] | null;
23
23
  export declare function fastVerifyGapsChain(filePath: string): GapsLogChainResultRs;
24
24
  export declare function fastAppendGapEntry(filePath: string, id: string, timestamp: string, specId: string, description: string, severity: string, affectedSpecs: string[]): string;
25
25
  export declare function fastCosineSimilarity(v1: number[], v2: number[]): number;
26
- export declare function fastHnswSearchFlat(query: number[], nodes: VectorNode[], topK: number): SearchResult[];
26
+ export declare function fastHnswSearchFlat(query: number[], nodes: VectorNode[], topK: number): NativeVectorSearchResult[];
27
27
  export declare function fastHmacSign(secret: string, data: string): string;
28
28
  export declare function fastHmacVerify(secret: string, data: string, signature: string): boolean;
29
29
  export declare function fastScanProjectGraphSources(rootPath: string, policy: ProjectGraphLimitsPolicyRs, overrides?: Partial<ResolvedProjectGraphLimitsRs>): ProjectGraphSourceFileRs[];
@@ -9,7 +9,7 @@ export declare function computeBudgetStatus(budget: SpecBudget): SpecBudgetStatu
9
9
  */
10
10
  export declare function formatBudgetMessage(status: SpecBudgetStatus): string;
11
11
  /**
12
- * Enforces budget limits before executing a licensed tool.
12
+ * Enforces engineering budget limits before executing a governed tool.
13
13
  * - If no budget is configured for the spec → no-op (pass through).
14
14
  * - If budget is exhausted → throws an Error to block tool execution.
15
15
  * - If warning threshold is reached → logs a warning but allows execution.
@@ -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,20 @@
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;
9
18
  export declare function readEvidenceArtifacts(args: {
10
19
  spec: Spec;
11
20
  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? }.',
@@ -1,5 +1,5 @@
1
1
  import { evidenceArtifactCollectionDigest, evidenceArtifactDigest } from './artifact-reader.js';
2
- import { hasAnyAffirmedMatch } from '../text-signal-boundaries.js';
2
+ import { hasAnyAffirmedMatch, stripMetaAnalysisText, stripNonContractText, } from '../text-signal-boundaries.js';
3
3
  import { createCriterionIdentity } from '../criterion-identity.js';
4
4
  const CONTRACT_HINTS = {
5
5
  api: [
@@ -10,7 +10,8 @@ const CONTRACT_HINTS = {
10
10
  ],
11
11
  graphql: [/\b(?:graphql|gql)\s+(?:api|schema|resolver|contract)\b/i, /\bschema\.graphql\b/i],
12
12
  event: [
13
- /\b(?:event|message)\s+(?:contract|schema|producer|consumer|handler|queue|topic)\b/i,
13
+ /\bevent\s+(?:contract|schema|producer|consumer|handler|queue|topic)\b/i,
14
+ /\bmessage\s+(?:schema|producer|consumer|handler|queue|topic)\b/i,
14
15
  /\b(?:message\s+broker|kafka|rabbitmq|pubsub|webhook\s+(?:delivery|contract|payload))\b/i,
15
16
  ],
16
17
  ui: [/\b(?:ui|component|screen|design)\s+contract\b/i],
@@ -76,7 +77,7 @@ function provenanceIssues(artifacts, context) {
76
77
  });
77
78
  }
78
79
  export function inferRequiredContractEvidence(spec, criteria) {
79
- const text = `${spec.title} ${spec.tags.join(' ')} ${criteria.join(' ')}`;
80
+ const text = stripMetaAnalysisText(stripNonContractText([spec.title, ...spec.tags, ...criteria].join('\n')));
80
81
  const required = [];
81
82
  for (const [kind, patterns] of Object.entries(CONTRACT_HINTS)) {
82
83
  if (hasAnyAffirmedMatch(text, [...patterns])) {
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Returns only project-relative IDs. Old evidence is rejected cumulatively: a
3
+ * later receipt cannot revive a digest superseded by an earlier receipt.
4
+ */
5
+ export declare function checkReconciliationFreshness(args: {
6
+ projectId: string;
7
+ specId: string;
8
+ }): Promise<{
9
+ artifactId: string;
10
+ }[]>;
11
+ //# sourceMappingURL=reconciliation-freshness.d.ts.map
@@ -0,0 +1,72 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { lstat, readFile, readdir } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { projectDataDir } from '../../storage/base-store.js';
5
+ import { readCommittedReconciliations } from '../lifecycle-reconciliation.js';
6
+ const BASE_ARTIFACTS = [
7
+ 'spec.lock.json',
8
+ 'review_feedback.md',
9
+ 'task-plan.json',
10
+ 'implementation-report.json',
11
+ 'validation-report.json',
12
+ 'traceability-matrix.json',
13
+ 'context-package.json',
14
+ ];
15
+ function sha256(bytes) {
16
+ return `sha256:${createHash('sha256').update(bytes).digest('hex')}`;
17
+ }
18
+ /**
19
+ * Returns only project-relative IDs. Old evidence is rejected cumulatively: a
20
+ * later receipt cannot revive a digest superseded by an earlier receipt.
21
+ */
22
+ export async function checkReconciliationFreshness(args) {
23
+ const receipts = await readCommittedReconciliations(args.projectId, args.specId);
24
+ const tombstones = new Set(receipts.flatMap((receipt) => receipt.supersededArtifacts.flatMap((artifact) => artifact.sha256 ? [`${artifact.artifactId}\0${artifact.sha256}`] : [])));
25
+ if (tombstones.size === 0) {
26
+ return [];
27
+ }
28
+ const root = projectDataDir(args.projectId);
29
+ const handoff = join(root, 'handoffs', args.specId);
30
+ const candidates = [
31
+ ...BASE_ARTIFACTS.map((name) => ({
32
+ artifactId: `handoffs/${args.specId}/${name}`,
33
+ path: join(handoff, name),
34
+ })),
35
+ { artifactId: `handoffs/${args.specId}.md`, path: join(root, 'handoffs', `${args.specId}.md`) },
36
+ ];
37
+ try {
38
+ const names = await readdir(handoff);
39
+ for (const artifactName of names) {
40
+ if (/^contract-validation-[A-Za-z0-9_-]+\.json$/u.test(artifactName)) {
41
+ candidates.push({
42
+ artifactId: `handoffs/${args.specId}/${artifactName}`,
43
+ path: join(handoff, artifactName),
44
+ });
45
+ }
46
+ }
47
+ }
48
+ catch (error) {
49
+ if (!(error instanceof Error && 'code' in error && error.code === 'ENOENT')) {
50
+ throw error;
51
+ }
52
+ }
53
+ const stale = [];
54
+ for (const candidate of candidates) {
55
+ try {
56
+ const stat = await lstat(candidate.path);
57
+ if (stat.isSymbolicLink() || !stat.isFile()) {
58
+ continue;
59
+ }
60
+ if (tombstones.has(`${candidate.artifactId}\0${sha256(await readFile(candidate.path))}`)) {
61
+ stale.push({ artifactId: candidate.artifactId });
62
+ }
63
+ }
64
+ catch (error) {
65
+ if (!(error instanceof Error && 'code' in error && error.code === 'ENOENT')) {
66
+ throw error;
67
+ }
68
+ }
69
+ }
70
+ return stale;
71
+ }
72
+ //# sourceMappingURL=reconciliation-freshness.js.map
@@ -1,6 +1,6 @@
1
1
  import type { EvidenceGateIssue, SpecEvidenceIndex } from '../../types/index.js';
2
2
  export declare function checkDoneDriftContract(args: {
3
3
  index: SpecEvidenceIndex;
4
- groundedTechnicalPaths: readonly string[];
4
+ approvedScopePaths: readonly string[];
5
5
  }): EvidenceGateIssue[];
6
6
  //# sourceMappingURL=done-drift.d.ts.map
@@ -1,3 +1,8 @@
1
+ import { normalizeChangedFilePath } from '../handoff-packager.js';
2
+ function normalizedChangedFile(value) {
3
+ const normalized = normalizeChangedFilePath(value);
4
+ return normalized.status === 'valid' ? normalized.path : null;
5
+ }
1
6
  export function checkDoneDriftContract(args) {
2
7
  const issues = [];
3
8
  const uncovered = args.index.criteria.filter((entry) => {
@@ -14,33 +19,50 @@ export function checkDoneDriftContract(args) {
14
19
  }
15
20
  const staleOrInvalid = args.index.criteria.flatMap((entry) => entry.evidence
16
21
  .filter((record) => record.status === 'stale' || record.status === 'invalid')
17
- .map((record) => `${entry.criterion}: ${record.value} (${record.status})`));
22
+ .map((record) => {
23
+ if (record.kind !== 'changed-file') {
24
+ return `${entry.criterion}: ${record.value} (${record.status})`;
25
+ }
26
+ const normalized = normalizedChangedFile(record.value);
27
+ return normalized
28
+ ? `${entry.criterion}: ${normalized} (${record.status})`
29
+ : `${entry.criterion}: invalid changed-file (${record.status})`;
30
+ }));
18
31
  if (staleOrInvalid.length > 0) {
19
32
  issues.push({
20
33
  code: 'done_drift_stale_evidence',
21
34
  message: `Done drift check found stale or invalid evidence: ${staleOrInvalid.join('; ')}`,
22
35
  });
23
36
  }
24
- const grounded = new Set(args.groundedTechnicalPaths);
25
- if (grounded.size > 0) {
26
- const unapproved = args.index.criteria.flatMap((entry) => {
27
- const hasScopeAmendment = entry.evidence.some((record) => record.kind === 'reviewer' && /scope amendment|approved scope/i.test(record.value));
28
- if (hasScopeAmendment) {
37
+ const approvedScopePaths = args.approvedScopePaths.flatMap((path) => {
38
+ const normalized = normalizedChangedFile(path);
39
+ return normalized ? [normalized] : [];
40
+ });
41
+ const approved = new Set(approvedScopePaths);
42
+ const unapproved = args.index.criteria.flatMap((entry) => {
43
+ const hasScopeAmendment = entry.evidence.some((record) => record.kind === 'reviewer' && /scope amendment|approved scope/i.test(record.value));
44
+ if (hasScopeAmendment) {
45
+ return [];
46
+ }
47
+ return entry.evidence.flatMap((record) => {
48
+ if (record.kind !== 'changed-file' ||
49
+ (record.status !== 'valid' && record.status !== 'missing')) {
29
50
  return [];
30
51
  }
31
- return entry.evidence
32
- .filter((record) => record.kind === 'changed-file' && !grounded.has(record.value))
33
- .map((record) => `${entry.criterion}: ${record.value}`);
52
+ const normalized = normalizedChangedFile(record.value);
53
+ return normalized && approved.has(normalized)
54
+ ? []
55
+ : [`${entry.criterion}: ${normalized ?? 'invalid changed-file path'}`];
56
+ });
57
+ });
58
+ if (unapproved.length > 0) {
59
+ const approvedHint = approvedScopePaths.length > 0
60
+ ? ` Approved canonical paths: ${approvedScopePaths.join(', ')}.`
61
+ : ' No approved canonical paths were found in the approved spec.';
62
+ issues.push({
63
+ code: 'done_drift_unapproved_scope',
64
+ message: `Done drift check found changed files outside approved canonical scope: ${unapproved.join('; ')}.${approvedHint} Add the file to approved canonical ownership or include reviewerEvidence with an approved scope amendment.`,
34
65
  });
35
- if (unapproved.length > 0) {
36
- const groundedHint = args.groundedTechnicalPaths.length > 0
37
- ? ` Grounded technical paths: ${args.groundedTechnicalPaths.join(', ')}.`
38
- : ' No grounded technical paths were found in the approved spec.';
39
- issues.push({
40
- code: 'done_drift_unapproved_scope',
41
- message: `Done drift check found changed files outside grounded spec scope: ${unapproved.join('; ')}.${groundedHint} Add the file to approved technical references or include reviewerEvidence with an approved scope amendment.`,
42
- });
43
- }
44
66
  }
45
67
  return issues;
46
68
  }
@@ -102,6 +102,7 @@ export function createChildCancellationScope(requestedMs) {
102
102
  const normalizedMs = Number.isFinite(requestedMs) ? Math.max(0, requestedMs) : 0;
103
103
  const timeoutMs = Math.max(0, Math.min(normalizedMs, parentRemaining));
104
104
  const controller = new AbortController();
105
+ let deadlineElapsed = false;
105
106
  const abortFromParent = () => {
106
107
  controller.abort(parent?.signal.reason ?? new ExecutionCancelledError());
107
108
  };
@@ -112,12 +113,14 @@ export function createChildCancellationScope(requestedMs) {
112
113
  parent?.signal.addEventListener('abort', abortFromParent, { once: true });
113
114
  }
114
115
  const timer = setTimeout(() => {
116
+ deadlineElapsed = true;
115
117
  controller.abort(new ExecutionCancelledError(`Execution budget elapsed after ${String(timeoutMs)}ms`));
116
118
  }, timeoutMs);
117
119
  timer.unref();
118
120
  return {
119
121
  signal: controller.signal,
120
122
  timeoutMs,
123
+ didDeadlineElapse: () => deadlineElapsed,
121
124
  dispose: () => {
122
125
  clearTimeout(timer);
123
126
  parent?.signal.removeEventListener('abort', abortFromParent);
@@ -0,0 +1,4 @@
1
+ import type { DurableJobHeartbeatController, DurableJobHeartbeatRuntimeOptions, DurableJobHeartbeatStartInput } from '../../types/durable-validation.js';
2
+ /** Start one autonomous, fenced heartbeat and wait for its typed ready acknowledgement. */
3
+ export declare function createDurableJobHeartbeat(input: DurableJobHeartbeatStartInput, options?: DurableJobHeartbeatRuntimeOptions): Promise<DurableJobHeartbeatController>;
4
+ //# sourceMappingURL=durable-job-heartbeat-runtime.d.ts.map