@planu/cli 4.12.3 → 4.14.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 (787) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +29 -25
  3. package/dist/cli/commands/inspect.d.ts +4 -0
  4. package/dist/cli/commands/inspect.js +144 -0
  5. package/dist/cli/commands/install.d.ts +19 -1
  6. package/dist/cli/commands/install.js +145 -43
  7. package/dist/cli/commands/job.d.ts +3 -0
  8. package/dist/cli/commands/job.js +119 -0
  9. package/dist/cli/commands/offline.d.ts +15 -0
  10. package/dist/cli/commands/offline.js +132 -0
  11. package/dist/cli/commands/serve.js +4 -0
  12. package/dist/cli/commands/spec.js +1 -1
  13. package/dist/cli/commands/storage.d.ts +3 -0
  14. package/dist/cli/commands/storage.js +102 -0
  15. package/dist/cli/commands/uninstall.d.ts +10 -0
  16. package/dist/cli/commands/uninstall.js +93 -7
  17. package/dist/cli/commands/validate.js +1 -1
  18. package/dist/cli/index.js +2 -0
  19. package/dist/cli/router.js +9 -1
  20. package/dist/config/crash-shield-framework-rules.json +93 -0
  21. package/dist/config/environment-schema.json +149 -0
  22. package/dist/config/hardcode-exceptions.json +4 -0
  23. package/dist/config/license-plans.json +7 -0
  24. package/dist/config/native-release-public-key.pem +3 -0
  25. package/dist/config/native-targets.json +87 -0
  26. package/dist/config/product-public.d.ts +89 -0
  27. package/dist/config/product-public.js +140 -0
  28. package/dist/config/product-public.json +312 -0
  29. package/dist/config/product-public.ts +148 -0
  30. package/dist/config/release-compatibility.json +13 -0
  31. package/dist/config/release-policy.json +26 -0
  32. package/dist/config/runtime-policy.json +44 -0
  33. package/dist/config/skill-templates/planu-validate.md +7 -4
  34. package/dist/config/subagent-templates/planu-spec-implementer.md +7 -3
  35. package/dist/config/subagent-templates/planu-validator.md +10 -5
  36. package/dist/config/technology-registry.json +120 -0
  37. package/dist/config/version.js +7 -8
  38. package/dist/config/version.ts +10 -7
  39. package/dist/engine/abortable-process-runner.js +40 -9
  40. package/dist/engine/advanced-testing/accessibility-checker.js +12 -14
  41. package/dist/engine/advanced-testing/mutation-advisor.js +3 -4
  42. package/dist/engine/advanced-testing/property-based.js +2 -3
  43. package/dist/engine/advanced-testing/test-data-advisor.js +2 -3
  44. package/dist/engine/agent-generator.js +2 -1
  45. package/dist/engine/agent-handoff-store.js +2 -1
  46. package/dist/engine/agent-prompt-generator.js +7 -5
  47. package/dist/engine/agent-telemetry.js +2 -1
  48. package/dist/engine/ai-integration/gemini/extensions-advisor.js +41 -9
  49. package/dist/engine/ambiguity-detector.js +12 -11
  50. package/dist/engine/analyzer/db-engine.js +2 -3
  51. package/dist/engine/analyzer/detectors.js +13 -14
  52. package/dist/engine/analyzer/env-setup.js +9 -10
  53. package/dist/engine/analyzer-env-scanner/env-example.js +7 -8
  54. package/dist/engine/api-spec-generator/graphql-parser.js +2 -2
  55. package/dist/engine/api-validation/graphql-schema-validator.js +2 -1
  56. package/dist/engine/api-validation/openapi-impl-validator.js +6 -7
  57. package/dist/engine/architecture-detector.js +10 -8
  58. package/dist/engine/auth/config.d.ts +1 -1
  59. package/dist/engine/auth/config.js +4 -3
  60. package/dist/engine/auto-updater/atomic-upgrade.d.ts +8 -0
  61. package/dist/engine/auto-updater/atomic-upgrade.js +381 -0
  62. package/dist/engine/auto-updater/config-detector.js +9 -3
  63. package/dist/engine/auto-updater/config-patcher.d.ts +0 -4
  64. package/dist/engine/auto-updater/config-patcher.js +10 -15
  65. package/dist/engine/auto-updater/index.d.ts +3 -1
  66. package/dist/engine/auto-updater/index.js +44 -30
  67. package/dist/engine/auto-updater/npm-registry.js +10 -2
  68. package/dist/engine/auto-updater/release-verifier.d.ts +3 -0
  69. package/dist/engine/auto-updater/release-verifier.js +112 -0
  70. package/dist/engine/auto-updater/upgrade-lock.d.ts +6 -0
  71. package/dist/engine/auto-updater/upgrade-lock.js +28 -0
  72. package/dist/engine/auto-updater/upgrade-trust-state.d.ts +7 -0
  73. package/dist/engine/auto-updater/upgrade-trust-state.js +59 -0
  74. package/dist/engine/autopilot/audit-logger.js +2 -5
  75. package/dist/engine/best-practices-library.js +2 -1
  76. package/dist/engine/browser-validator.js +2 -1
  77. package/dist/engine/build-tool-detector.js +3 -2
  78. package/dist/engine/ci-generator/context-builders.js +7 -5
  79. package/dist/engine/ci-generator/stack-detector.js +0 -2
  80. package/dist/engine/ci-generator/yaml-builder.js +0 -2
  81. package/dist/engine/claude-config-auditor/rules-auditor.js +4 -3
  82. package/dist/engine/code-transforms/typescript/ast-utils.js +2 -3
  83. package/dist/engine/complexity-budget/trivial-detector.js +2 -1
  84. package/dist/engine/compliance-test-generator/index.js +7 -2
  85. package/dist/engine/compliance-test-generator/test-formatter.js +2 -2
  86. package/dist/engine/config-health/mcp-config-checker.js +2 -1
  87. package/dist/engine/config-health/ts-checker-scripts.js +4 -3
  88. package/dist/engine/config-health/ts-checker.js +3 -2
  89. package/dist/engine/convention-injector.js +5 -7
  90. package/dist/engine/convention-scanner/convention-parser.js +3 -2
  91. package/dist/engine/core-bridge-duplicate-blocks.d.ts +3 -0
  92. package/dist/engine/core-bridge-duplicate-blocks.js +57 -0
  93. package/dist/engine/core-bridge-gaps.d.ts +4 -0
  94. package/dist/engine/core-bridge-gaps.js +75 -0
  95. package/dist/engine/core-bridge.d.ts +9 -9
  96. package/dist/engine/core-bridge.js +196 -283
  97. package/dist/engine/cost-tracking/ledger.js +2 -5
  98. package/dist/engine/coverage-gap-analyzer.js +10 -1
  99. package/dist/engine/crash-shield/detectors/framework-detector.d.ts +2 -0
  100. package/dist/engine/crash-shield/detectors/framework-detector.js +110 -192
  101. package/dist/engine/crash-shield/detectors/typescript-detector.js +2 -1
  102. package/dist/engine/dashboard/data-loader.js +2 -1
  103. package/dist/engine/data-projects-gc/gc-runner.d.ts +7 -0
  104. package/dist/engine/data-projects-gc/gc-runner.js +113 -3
  105. package/dist/engine/data-projects-gc/scanner.js +5 -1
  106. package/dist/engine/decision-store.js +11 -14
  107. package/dist/engine/deleter/core.js +5 -5
  108. package/dist/engine/dep-auditor/abandonment-data.js +2 -1
  109. package/dist/engine/dep-auditor/abandonment-registry.js +3 -1
  110. package/dist/engine/dep-auditor/cve-fetcher.js +3 -0
  111. package/dist/engine/dep-auditor/dep-duplicates-detector.js +36 -4
  112. package/dist/engine/dep-auditor/license-registry.js +2 -0
  113. package/dist/engine/dependency-evaluator.d.ts +14 -0
  114. package/dist/engine/dependency-evaluator.js +81 -0
  115. package/dist/engine/deploy/providers/fly.js +7 -7
  116. package/dist/engine/deploy/providers/netlify.js +7 -7
  117. package/dist/engine/deploy/providers/railway.js +10 -12
  118. package/dist/engine/deploy/providers/vercel.js +7 -9
  119. package/dist/engine/deprecation-scanner/pattern-loader.js +0 -2
  120. package/dist/engine/desktop-detector.js +2 -3
  121. package/dist/engine/detect-duplication.js +2 -1
  122. package/dist/engine/detectors/advanced-framework-detector/css-state-detector.js +2 -1
  123. package/dist/engine/detectors/advanced-framework-detector/legacy-detector.js +2 -3
  124. package/dist/engine/detectors/advanced-framework-detector/modern-detector.js +3 -4
  125. package/dist/engine/detectors/agent-framework-detector.js +3 -2
  126. package/dist/engine/detectors/ai-native-detector.js +4 -6
  127. package/dist/engine/detectors/cache-db-detector.js +4 -3
  128. package/dist/engine/detectors/cicd-detector.js +4 -3
  129. package/dist/engine/detectors/deployment-detector.js +11 -12
  130. package/dist/engine/detectors/frontend-perf-detector.js +14 -9
  131. package/dist/engine/detectors/library-detector-multilang-a.js +16 -3
  132. package/dist/engine/detectors/library-detector-node.js +14 -4
  133. package/dist/engine/detectors/library-detector-python.js +7 -1
  134. package/dist/engine/detectors/library-detector.js +0 -2
  135. package/dist/engine/detectors/llm-detector/provider-maps.js +3 -2
  136. package/dist/engine/detectors/mcp-candidate-detector.js +12 -16
  137. package/dist/engine/detectors/mfe-detector.js +6 -7
  138. package/dist/engine/detectors/monitoring-detector.js +4 -3
  139. package/dist/engine/detectors/otel-detector.js +3 -2
  140. package/dist/engine/detectors/otel-ecosystem-detectors.d.ts +2 -2
  141. package/dist/engine/detectors/otel-ecosystem-detectors.js +4 -3
  142. package/dist/engine/detectors/platform-specialty-detector.js +3 -5
  143. package/dist/engine/detectors/template-engine-detector.js +3 -4
  144. package/dist/engine/doc-generator/builders.js +2 -3
  145. package/dist/engine/doc-generator/mobile-distribution-guide.js +13 -17
  146. package/dist/engine/doc-generator/portal/dirty-flag-map.d.ts +2 -2
  147. package/dist/engine/doc-generator/portal/portal-regenerator.js +3 -47
  148. package/dist/engine/domain-detector.js +3 -6
  149. package/dist/engine/dynamic-knowledge/knowledge-cache.js +3 -4
  150. package/dist/engine/dynamic-knowledge/knowledge-merger.js +17 -2
  151. package/dist/engine/dynamic-knowledge/web-researcher.js +15 -14
  152. package/dist/engine/dynamic-migration-detector/manifest-readers-extended.js +0 -2
  153. package/dist/engine/e2e-test-generator.js +4 -3
  154. package/dist/engine/ecosystem-absorber/knowledge-cache.js +2 -1
  155. package/dist/engine/ecosystem-absorber/platform-crawler.js +2 -2
  156. package/dist/engine/escalator/retry-counter.js +2 -1
  157. package/dist/engine/evidence-gates/artifact-reader.d.ts +6 -0
  158. package/dist/engine/evidence-gates/artifact-reader.js +105 -21
  159. package/dist/engine/evidence-gates/lifecycle-gate.d.ts +2 -1
  160. package/dist/engine/evidence-gates/lifecycle-gate.js +54 -0
  161. package/dist/engine/execution/context.d.ts +19 -0
  162. package/dist/engine/execution/context.js +127 -0
  163. package/dist/engine/execution/deadline-io.d.ts +21 -0
  164. package/dist/engine/execution/deadline-io.js +45 -0
  165. package/dist/engine/execution/job-executor.d.ts +16 -0
  166. package/dist/engine/execution/job-executor.js +140 -0
  167. package/dist/engine/execution/job-runtime.d.ts +78 -0
  168. package/dist/engine/execution/job-runtime.js +220 -0
  169. package/dist/engine/execution/native-relevance-scorer.d.ts +6 -0
  170. package/dist/engine/execution/native-relevance-scorer.js +64 -0
  171. package/dist/engine/execution/native-worker-dispatch.d.ts +3 -0
  172. package/dist/engine/execution/native-worker-dispatch.js +46 -0
  173. package/dist/engine/execution/native-worker-protocol.d.ts +6 -0
  174. package/dist/engine/execution/native-worker-protocol.js +33 -0
  175. package/dist/engine/execution/native-worker-runtime.d.ts +4 -0
  176. package/dist/engine/execution/native-worker-runtime.js +177 -0
  177. package/dist/engine/execution/native-worker-thread.d.ts +2 -0
  178. package/dist/engine/execution/native-worker-thread.js +66 -0
  179. package/dist/engine/execution/operation-journal.d.ts +66 -0
  180. package/dist/engine/execution/operation-journal.js +260 -0
  181. package/dist/engine/execution/outbox-worker.d.ts +31 -0
  182. package/dist/engine/execution/outbox-worker.js +192 -0
  183. package/dist/engine/execution/validate-job-executor.d.ts +24 -0
  184. package/dist/engine/execution/validate-job-executor.js +342 -0
  185. package/dist/engine/execution/validate-job-payload.d.ts +5 -0
  186. package/dist/engine/execution/validate-job-payload.js +87 -0
  187. package/dist/engine/execution/validate-job-recovery.d.ts +4 -0
  188. package/dist/engine/execution/validate-job-recovery.js +47 -0
  189. package/dist/engine/execution/validate-worker-runtime.d.ts +5 -0
  190. package/dist/engine/execution/validate-worker-runtime.js +100 -0
  191. package/dist/engine/execution/validate-worker-thread.d.ts +2 -0
  192. package/dist/engine/execution/validate-worker-thread.js +71 -0
  193. package/dist/engine/execution-plan/desktop-distribution.js +3 -7
  194. package/dist/engine/execution-plan/mobile-distribution.js +4 -9
  195. package/dist/engine/execution-plan/phases.js +4 -5
  196. package/dist/engine/execution-plan/plan-utils.js +8 -5
  197. package/dist/engine/facilitate/context-loader.js +3 -9
  198. package/dist/engine/figma/code-connect-fetcher.js +9 -8
  199. package/dist/engine/filesystem-watcher/index.d.ts +3 -3
  200. package/dist/engine/filesystem-watcher/index.js +5 -5
  201. package/dist/engine/framework-detector.js +14 -15
  202. package/dist/engine/git/planu-autocommit.js +8 -7
  203. package/dist/engine/git/repository-probe.d.ts +3 -0
  204. package/dist/engine/git/repository-probe.js +13 -0
  205. package/dist/engine/global-rules-manager.js +2 -2
  206. package/dist/engine/handoff-artifacts/io.js +2 -3
  207. package/dist/engine/handoff-artifacts/schemas/red-tests-handoff.js +8 -1
  208. package/dist/engine/handoff-artifacts/schemas.d.ts +4 -0
  209. package/dist/engine/handoff-artifacts/schemas.js +5 -0
  210. package/dist/engine/hook-generator/stack-hook-templates.js +4 -4
  211. package/dist/engine/hooks/config-loader.js +1 -1
  212. package/dist/engine/hooks/context-injector.js +4 -7
  213. package/dist/engine/hooks/file-watcher.js +1 -14
  214. package/dist/engine/hooks-reconciler.js +6 -4
  215. package/dist/engine/infrastructure/component-mapper.js +5 -7
  216. package/dist/engine/infrastructure/docker-compose-generator.js +8 -10
  217. package/dist/engine/infrastructure/index.js +6 -3
  218. package/dist/engine/infrastructure/kubernetes-generator.js +2 -2
  219. package/dist/engine/infrastructure/railway-generator.js +10 -8
  220. package/dist/engine/infrastructure/signal-detector.js +6 -8
  221. package/dist/engine/infrastructure/terraform-generator.js +6 -8
  222. package/dist/engine/legal-compliance/detector.js +3 -2
  223. package/dist/engine/local-first/storage-advisor.js +5 -6
  224. package/dist/engine/macos-keychain-native-port.d.ts +5 -0
  225. package/dist/engine/macos-keychain-native-port.js +26 -0
  226. package/dist/engine/marketplace-fetcher/cache.js +3 -1
  227. package/dist/engine/mcp-config/mcp-config-writer.d.ts +2 -2
  228. package/dist/engine/mcp-config/mcp-config-writer.js +10 -8
  229. package/dist/engine/migration/db-migrator.js +2 -5
  230. package/dist/engine/migration/equivalence-mapper.js +12 -13
  231. package/dist/engine/migration/service-catalogs.js +6 -7
  232. package/dist/engine/migration/service-migrator-catalogs.js +6 -7
  233. package/dist/engine/mobile-detector-ios.js +2 -3
  234. package/dist/engine/mobile-detector.js +16 -4
  235. package/dist/engine/model-router/complexity-analyzer.js +4 -7
  236. package/dist/engine/multi-agent-review/security-analyzer.js +3 -1
  237. package/dist/engine/multi-app-detector/app-type.js +26 -21
  238. package/dist/engine/multi-app-detector/core.js +3 -2
  239. package/dist/engine/multi-teammate-review/disagreement-counter.js +2 -1
  240. package/dist/engine/multi-teammate-review/panel-orchestrator.js +0 -2
  241. package/dist/engine/mutation-config-generator.js +10 -7
  242. package/dist/engine/native-capability-policy.d.ts +4 -0
  243. package/dist/engine/native-capability-policy.js +24 -0
  244. package/dist/engine/native-platform.d.ts +3 -0
  245. package/dist/engine/native-platform.js +44 -0
  246. package/dist/engine/native-runtime-handshake.d.ts +20 -0
  247. package/dist/engine/native-runtime-handshake.js +230 -0
  248. package/dist/engine/network-policy.d.ts +27 -0
  249. package/dist/engine/network-policy.js +174 -0
  250. package/dist/engine/next-spec-resolver/dependency-filter.js +2 -22
  251. package/dist/engine/nfr-profile-detector.js +12 -16
  252. package/dist/engine/nli-keywords.js +8 -9
  253. package/dist/engine/oauth/config-guard.js +4 -5
  254. package/dist/engine/observability/local-execution-spans.d.ts +15 -0
  255. package/dist/engine/observability/local-execution-spans.js +63 -0
  256. package/dist/engine/orchestrator/runtime.js +0 -1
  257. package/dist/engine/package-registry.js +2 -6
  258. package/dist/engine/performance-analyzer.js +2 -5
  259. package/dist/engine/permissions-merger/stack-detectors.js +5 -5
  260. package/dist/engine/planu-core.darwin-arm64.node.manifest.json +39 -0
  261. package/dist/engine/planu-core.darwin-arm64.node.sbom.json +1310 -0
  262. package/dist/engine/planu-core.darwin-x64.node.manifest.json +39 -0
  263. package/dist/engine/planu-core.darwin-x64.node.sbom.json +1310 -0
  264. package/dist/engine/planu-core.linux-arm64-gnu.node.manifest.json +38 -0
  265. package/dist/engine/planu-core.linux-arm64-gnu.node.sbom.json +1310 -0
  266. package/dist/engine/planu-core.linux-arm64-musl.node.manifest.json +38 -0
  267. package/dist/engine/planu-core.linux-arm64-musl.node.sbom.json +1310 -0
  268. package/dist/engine/planu-core.linux-x64-gnu.node.manifest.json +38 -0
  269. package/dist/engine/planu-core.linux-x64-gnu.node.sbom.json +1310 -0
  270. package/dist/engine/planu-core.linux-x64-musl.node.manifest.json +38 -0
  271. package/dist/engine/planu-core.linux-x64-musl.node.sbom.json +1310 -0
  272. package/dist/engine/planu-core.win32-arm64-msvc.node.manifest.json +38 -0
  273. package/dist/engine/planu-core.win32-arm64-msvc.node.sbom.json +1310 -0
  274. package/dist/engine/planu-core.win32-x64-msvc.node.manifest.json +38 -0
  275. package/dist/engine/planu-core.win32-x64-msvc.node.sbom.json +1310 -0
  276. package/dist/engine/platform-detector/desktop.js +15 -2
  277. package/dist/engine/platform-detector/extensions.js +2 -1
  278. package/dist/engine/platform-detector/games.js +2 -1
  279. package/dist/engine/platform-detector.js +3 -2
  280. package/dist/engine/platform-engineering/idp-detector.js +2 -1
  281. package/dist/engine/plugin-installer/stack-matcher.js +9 -17
  282. package/dist/engine/plugins/lifecycle.js +6 -2
  283. package/dist/engine/prior-decisions/contradiction-detector.js +60 -30
  284. package/dist/engine/project-dna/stack-detector.js +15 -17
  285. package/dist/engine/project-graph/builder.js +11 -0
  286. package/dist/engine/project-graph/cache.js +1 -1
  287. package/dist/engine/project-graph/freshness-projection.d.ts +16 -0
  288. package/dist/engine/project-graph/freshness-projection.js +95 -0
  289. package/dist/engine/project-graph/index.d.ts +1 -0
  290. package/dist/engine/project-graph/index.js +1 -0
  291. package/dist/engine/project-graph/query.js +15 -25
  292. package/dist/engine/project-health-checker.js +3 -4
  293. package/dist/engine/project-scanner/stack-detector.js +17 -17
  294. package/dist/engine/property-test-generator.js +2 -3
  295. package/dist/engine/qa-gate.d.ts +1 -0
  296. package/dist/engine/qa-gate.js +6 -4
  297. package/dist/engine/quality-gates/gate-catalog.js +47 -46
  298. package/dist/engine/quality-gates/gate-injector.js +9 -4
  299. package/dist/engine/registry/core.js +0 -2
  300. package/dist/engine/registry/loader.js +9 -12
  301. package/dist/engine/registry/matcher.js +129 -24
  302. package/dist/engine/resilience-detector/concurrency-detector.js +4 -4
  303. package/dist/engine/resilience-detector/middleware-detector.js +11 -13
  304. package/dist/engine/resilience-detector/validation-detector.js +17 -4
  305. package/dist/engine/reverse-engineer/config-analyzer.js +9 -8
  306. package/dist/engine/reverse-engineer/orchestrator.js +5 -9
  307. package/dist/engine/reverse-engineer/test-file-parser.js +6 -3
  308. package/dist/engine/rules-generator/index.js +6 -5
  309. package/dist/engine/runtime-policy.d.ts +7 -0
  310. package/dist/engine/runtime-policy.js +101 -0
  311. package/dist/engine/runtime-security/checkers/content-security.js +21 -6
  312. package/dist/engine/runtime-security/checkers/file-permissions.js +0 -2
  313. package/dist/engine/safety/atomic-write-file.js +20 -9
  314. package/dist/engine/safety/atomic-writer.js +10 -3
  315. package/dist/engine/safety/cross-process-lock.d.ts +3 -40
  316. package/dist/engine/safety/cross-process-lock.js +268 -272
  317. package/dist/engine/safety/file-mutex.d.ts +2 -9
  318. package/dist/engine/safety/file-mutex.js +155 -87
  319. package/dist/engine/safety/health-monitor.js +15 -6
  320. package/dist/engine/safety/lock-lease-store.d.ts +79 -0
  321. package/dist/engine/safety/lock-lease-store.js +372 -0
  322. package/dist/engine/safety/lock-scavenger.d.ts +2 -5
  323. package/dist/engine/safety/lock-scavenger.js +158 -76
  324. package/dist/engine/safety/lock-staleness.js +4 -1
  325. package/dist/engine/safety/obsolete-lock-guard.d.ts +8 -0
  326. package/dist/engine/safety/obsolete-lock-guard.js +31 -0
  327. package/dist/engine/safety/transaction.js +3 -3
  328. package/dist/engine/sandbox/index.js +2 -1
  329. package/dist/engine/sandbox/runner-detect.js +3 -2
  330. package/dist/engine/sandbox/runner-docker.js +4 -3
  331. package/dist/engine/scan-project/module-discoverer.js +3 -2
  332. package/dist/engine/schema-generator.js +16 -9
  333. package/dist/engine/security-analyzer/criteria-generator.js +2 -3
  334. package/dist/engine/self-healing/healer.js +4 -4
  335. package/dist/engine/session-safeguard/learnings-buffer.d.ts +1 -2
  336. package/dist/engine/session-safeguard/learnings-buffer.js +42 -65
  337. package/dist/engine/shared-agent-memory.js +66 -74
  338. package/dist/engine/skill-adapter/command-rewriter.js +3 -2
  339. package/dist/engine/skill-adapter/index.js +3 -3
  340. package/dist/engine/skill-adapter/placeholder-map.js +3 -2
  341. package/dist/engine/skill-bootstrap/stack-matcher.js +47 -48
  342. package/dist/engine/skill-generation/stack-content-generator.js +0 -2
  343. package/dist/engine/skill-generator/workflow-skill-generator.js +2 -1
  344. package/dist/engine/skill-registry/ttl-refresh.js +3 -1
  345. package/dist/engine/skills/skills-fetcher.js +3 -6
  346. package/dist/engine/skills-reconciler.js +19 -39
  347. package/dist/engine/spec-coverage/test-finder.js +7 -6
  348. package/dist/engine/spec-diff-engine.js +3 -3
  349. package/dist/engine/spec-generator/api-key-resolver.d.ts +1 -1
  350. package/dist/engine/spec-generator/api-key-resolver.js +3 -24
  351. package/dist/engine/spec-generators/issue-extractor.js +9 -3
  352. package/dist/engine/spec-migrator/drift-detector.js +5 -13
  353. package/dist/engine/spec-migrator/filesystem-import.js +14 -10
  354. package/dist/engine/spec-migrator/planu-canonical-policy.js +10 -1
  355. package/dist/engine/spec-migrator/strict-planu-cleanup.js +24 -25
  356. package/dist/engine/spec-registry/adapter.d.ts +0 -5
  357. package/dist/engine/spec-registry/adapter.js +45 -46
  358. package/dist/engine/spec-registry/client.js +2 -0
  359. package/dist/engine/spec-source-sync.js +3 -2
  360. package/dist/engine/spec-templates/custom-loader.js +2 -3
  361. package/dist/engine/spec-templates/templates-domain-specific.js +8 -5
  362. package/dist/engine/spec-templates/templates-perf-integration.js +2 -3
  363. package/dist/engine/stack-auditor/manifest-reader.js +0 -2
  364. package/dist/engine/staleness/stale-implementing.js +7 -7
  365. package/dist/engine/tdd-scaffold-generator.js +24 -11
  366. package/dist/engine/teammate-router/green-phase-verifier.js +2 -1
  367. package/dist/engine/teammate-router/red-phase-verifier.js +2 -1
  368. package/dist/engine/technology-registry.d.ts +11 -0
  369. package/dist/engine/technology-registry.js +142 -0
  370. package/dist/engine/telemetry/error-reporter.d.ts +1 -2
  371. package/dist/engine/telemetry/error-reporter.js +11 -18
  372. package/dist/engine/telemetry/health-checker.js +5 -14
  373. package/dist/engine/telemetry/index.d.ts +0 -1
  374. package/dist/engine/telemetry/index.js +0 -1
  375. package/dist/engine/telemetry/stance.js +3 -2
  376. package/dist/engine/telemetry/telemetry-client.d.ts +1 -5
  377. package/dist/engine/telemetry/telemetry-client.js +45 -29
  378. package/dist/engine/telemetry/telemetry-store.d.ts +3 -3
  379. package/dist/engine/telemetry/telemetry-store.js +30 -23
  380. package/dist/engine/test-framework-detector/detectors.js +8 -8
  381. package/dist/engine/test-framework-detector/strategy.js +8 -9
  382. package/dist/engine/test-generators/agent-test-templates.js +2 -3
  383. package/dist/engine/test-generators/contract-test-generator.d.ts +1 -1
  384. package/dist/engine/test-generators/contract-test-generator.js +9 -202
  385. package/dist/engine/test-generators/platform-test-templates-b.js +2 -3
  386. package/dist/engine/test-generators/platform-test-templates.js +2 -5
  387. package/dist/engine/test-mocks-generator.js +4 -3
  388. package/dist/engine/test-plan-generator.js +30 -12
  389. package/dist/engine/test-scaffold-generator/advanced-scaffold.js +4 -5
  390. package/dist/engine/test-scaffold-generator/unit-scaffold.js +5 -6
  391. package/dist/engine/timing/budget.d.ts +6 -17
  392. package/dist/engine/timing/budget.js +80 -64
  393. package/dist/engine/tool-groups/group-manager.js +3 -3
  394. package/dist/engine/universal-rules/installer.js +1 -1
  395. package/dist/engine/universal-rules/rules/planu-modes.js +2 -0
  396. package/dist/engine/universal-rules/rules/planu-release-policy.js +1 -0
  397. package/dist/engine/update-notifier.js +8 -5
  398. package/dist/engine/validation/approved-spec-portability.d.ts +12 -0
  399. package/dist/engine/validation/approved-spec-portability.js +107 -0
  400. package/dist/engine/validation/durable-validation.d.ts +36 -0
  401. package/dist/engine/validation/durable-validation.js +335 -0
  402. package/dist/engine/validation/validation-freshness.d.ts +36 -0
  403. package/dist/engine/validation/validation-freshness.js +427 -0
  404. package/dist/engine/validation/validation-receipt-codec.d.ts +13 -0
  405. package/dist/engine/validation/validation-receipt-codec.js +182 -0
  406. package/dist/engine/validation/validation-receipt.d.ts +59 -0
  407. package/dist/engine/validation/validation-receipt.js +282 -0
  408. package/dist/engine/validation/validation-source-policy.d.ts +4 -0
  409. package/dist/engine/validation/validation-source-policy.js +16 -0
  410. package/dist/engine/validation/validation-submission.d.ts +36 -0
  411. package/dist/engine/validation/validation-submission.js +128 -0
  412. package/dist/engine/validation-evidence-ledger.js +41 -0
  413. package/dist/engine/validation-impact-planner.js +25 -9
  414. package/dist/engine/validator/spec-compliance-runner.d.ts +1 -1
  415. package/dist/engine/validator/spec-compliance-runner.js +17 -8
  416. package/dist/engine/validator/validation-report-writer.js +1 -1
  417. package/dist/engine/validator.js +2 -1
  418. package/dist/engine/verify-integrations/index.js +1 -1
  419. package/dist/engine/version-resolver.js +5 -6
  420. package/dist/engine/web-fetcher/stack-advisor.js +156 -92
  421. package/dist/engine/web-fetcher/stack-detector.js +114 -54
  422. package/dist/engine/workspace-manager.js +3 -2
  423. package/dist/errors/classified-degradation.d.ts +3 -0
  424. package/dist/errors/classified-degradation.js +10 -0
  425. package/dist/errors/degradation-sink.d.ts +3 -0
  426. package/dist/errors/degradation-sink.js +5 -0
  427. package/dist/errors/error-taxonomy.d.ts +12 -0
  428. package/dist/errors/error-taxonomy.js +62 -0
  429. package/dist/hosts/claude-code/ux/mcp-prompts.js +10 -4
  430. package/dist/hosts/claude-code/ux/mcp-resources.js +4 -2
  431. package/dist/hosts/codex/config-scaffold.js +4 -3
  432. package/dist/hosts/gemini/config-scaffold.js +2 -1
  433. package/dist/hosts/gemini/multimodal-spec-flow.js +7 -4
  434. package/dist/index.js +21 -6
  435. package/dist/resources/patterns.js +3 -1
  436. package/dist/resources/specs.js +3 -1
  437. package/dist/resources/templates.js +3 -1
  438. package/dist/security/adapters/environment.d.ts +12 -0
  439. package/dist/security/adapters/environment.js +25 -0
  440. package/dist/security/adapters/linux-secret-service.d.ts +8 -0
  441. package/dist/security/adapters/linux-secret-service.js +60 -0
  442. package/dist/security/adapters/macos-keychain.d.ts +18 -0
  443. package/dist/security/adapters/macos-keychain.js +90 -0
  444. package/dist/security/adapters/windows-credential-manager.d.ts +8 -0
  445. package/dist/security/adapters/windows-credential-manager.js +58 -0
  446. package/dist/security/redactor.d.ts +5 -0
  447. package/dist/security/redactor.js +58 -0
  448. package/dist/security/secret-field.d.ts +5 -0
  449. package/dist/security/secret-field.js +17 -0
  450. package/dist/security/secret-migration.d.ts +3 -0
  451. package/dist/security/secret-migration.js +123 -0
  452. package/dist/security/secret-provider.d.ts +23 -0
  453. package/dist/security/secret-provider.js +145 -0
  454. package/dist/security/secure-json.d.ts +3 -0
  455. package/dist/security/secure-json.js +29 -0
  456. package/dist/storage/api-surfaces-store.js +2 -2
  457. package/dist/storage/approval-operation-lock.d.ts +1 -1
  458. package/dist/storage/approval-operation-lock.js +5 -3
  459. package/dist/storage/audit-trail-store.d.ts +1 -1
  460. package/dist/storage/audit-trail-store.js +48 -62
  461. package/dist/storage/autopilot-log-store.js +12 -5
  462. package/dist/storage/base-store.d.ts +8 -8
  463. package/dist/storage/base-store.js +57 -20
  464. package/dist/storage/checkpoint-store.js +5 -2
  465. package/dist/storage/comments-store.js +2 -2
  466. package/dist/storage/compliance-audit-store.js +5 -2
  467. package/dist/storage/compliance-gate-config-store.js +7 -4
  468. package/dist/storage/compliance-store.js +2 -2
  469. package/dist/storage/context-profile-store.js +2 -2
  470. package/dist/storage/crash-shield-store.js +8 -4
  471. package/dist/storage/feedback-store.js +10 -6
  472. package/dist/storage/figma-store.js +8 -4
  473. package/dist/storage/file-mutex.js +9 -1
  474. package/dist/storage/gaps-log.js +7 -4
  475. package/dist/storage/global-projects-store.js +4 -2
  476. package/dist/storage/ideas-store.js +2 -2
  477. package/dist/storage/index.d.ts +5 -0
  478. package/dist/storage/index.js +5 -0
  479. package/dist/storage/knowledge-store/knowledge.js +27 -33
  480. package/dist/storage/lessons-store.js +2 -2
  481. package/dist/storage/license-store.js +13 -41
  482. package/dist/storage/migrations/canonical-storage.d.ts +15 -0
  483. package/dist/storage/migrations/canonical-storage.js +599 -0
  484. package/dist/storage/oauth-store.js +36 -8
  485. package/dist/storage/path-resolver.js +16 -3
  486. package/dist/storage/pr-store.js +2 -2
  487. package/dist/storage/project-drift-store.js +20 -8
  488. package/dist/storage/project-identity.d.ts +32 -0
  489. package/dist/storage/project-identity.js +194 -0
  490. package/dist/storage/project-resolver.js +14 -7
  491. package/dist/storage/release-notes-store.js +2 -6
  492. package/dist/storage/runtime-db.d.ts +186 -0
  493. package/dist/storage/runtime-db.js +1054 -0
  494. package/dist/storage/schema-registry.d.ts +5 -0
  495. package/dist/storage/schema-registry.js +74 -0
  496. package/dist/storage/sentry-store.js +20 -9
  497. package/dist/storage/session-state-store.js +12 -5
  498. package/dist/storage/session-store.js +12 -4
  499. package/dist/storage/skill-registry-storage.d.ts +1 -1
  500. package/dist/storage/skill-registry-storage.js +13 -11
  501. package/dist/storage/slack-store.js +10 -5
  502. package/dist/storage/spec-store.js +31 -24
  503. package/dist/storage/status-store/file-lock.js +31 -9
  504. package/dist/storage/status-store/self-healing.js +10 -5
  505. package/dist/storage/status-store/version-sync.js +8 -6
  506. package/dist/storage/steering-store.js +2 -2
  507. package/dist/storage/storage-bundle.d.ts +5 -0
  508. package/dist/storage/storage-bundle.js +117 -0
  509. package/dist/storage/storage-catalog-validation.d.ts +3 -0
  510. package/dist/storage/storage-catalog-validation.js +20 -0
  511. package/dist/storage/storage-catalog.d.ts +25 -0
  512. package/dist/storage/storage-catalog.js +390 -0
  513. package/dist/storage/storage-layout.d.ts +24 -0
  514. package/dist/storage/storage-layout.js +101 -0
  515. package/dist/storage/storybook-store.js +2 -2
  516. package/dist/storage/supabase-store.js +24 -6
  517. package/dist/storage/tdd-policy-store.js +8 -6
  518. package/dist/storage/tech-debt-store.js +3 -3
  519. package/dist/storage/technology-selection-store.d.ts +1 -1
  520. package/dist/storage/technology-selection-store.js +6 -3
  521. package/dist/storage/token-cache-store.js +3 -3
  522. package/dist/storage/token-ledger-store.js +13 -8
  523. package/dist/storage/transition-log.js +7 -4
  524. package/dist/storage/trash-store.js +15 -6
  525. package/dist/storage/vector-store/migrator.js +7 -2
  526. package/dist/storage/vector-store/sqlite-adapter.js +4 -1
  527. package/dist/storage/webhook-server-store.js +2 -2
  528. package/dist/tools/api-spec-generator-handler.js +3 -2
  529. package/dist/tools/auto-update-handler.d.ts +1 -1
  530. package/dist/tools/auto-update-handler.js +1 -1
  531. package/dist/tools/browser-validate-handler.js +2 -1
  532. package/dist/tools/challenge-spec/platform-challenge-scenarios-b.js +8 -5
  533. package/dist/tools/challenge-spec/scenarios-desktop.js +8 -3
  534. package/dist/tools/challenge-spec/scenarios-failure.js +7 -2
  535. package/dist/tools/challenge-spec/security-challenge-scenarios.js +3 -3
  536. package/dist/tools/clarify-requirements/multiple-choice.js +53 -41
  537. package/dist/tools/comments-handler.js +2 -3
  538. package/dist/tools/compliance-test-handler.js +2 -2
  539. package/dist/tools/configure-telemetry.js +11 -11
  540. package/dist/tools/create-spec/auto-pipeline.js +13 -1
  541. package/dist/tools/create-spec/autopilot-analyzer.d.ts +1 -1
  542. package/dist/tools/create-spec/autopilot-analyzer.js +2 -4
  543. package/dist/tools/create-spec/mcp-tool-contract.d.ts +10 -4
  544. package/dist/tools/create-spec/mcp-tool-contract.js +7 -36
  545. package/dist/tools/create-spec/post-creation.d.ts +2 -1
  546. package/dist/tools/create-spec/post-creation.js +56 -54
  547. package/dist/tools/create-spec/relevance-scorer.d.ts +1 -1
  548. package/dist/tools/create-spec/relevance-scorer.js +17 -1
  549. package/dist/tools/create-spec/spec-builder.js +2 -12
  550. package/dist/tools/create-spec/spec-created-outbox-consumer.d.ts +14 -0
  551. package/dist/tools/create-spec/spec-created-outbox-consumer.js +176 -0
  552. package/dist/tools/create-spec.js +385 -520
  553. package/dist/tools/define-ui-contract/agent-interaction-contract.js +2 -4
  554. package/dist/tools/define-ui-contract-desktop/desktop-contract.js +12 -4
  555. package/dist/tools/define-ui-contract-desktop/native-contract.js +7 -3
  556. package/dist/tools/define-ui-contract-extensions.js +2 -3
  557. package/dist/tools/define-ui-contract-mobile.js +5 -9
  558. package/dist/tools/define-ui-contract-web/component-tree.js +4 -3
  559. package/dist/tools/define-ui-contract.js +7 -4
  560. package/dist/tools/deploy/deploy-spec.js +2 -4
  561. package/dist/tools/deploy/deploy-status.js +2 -4
  562. package/dist/tools/design-schema/nosql-category-schemas.js +2 -3
  563. package/dist/tools/design-schema-sql/migrations.js +3 -2
  564. package/dist/tools/design-schema-sql/tables.js +4 -1
  565. package/dist/tools/design-schema.js +4 -3
  566. package/dist/tools/feedback-handler.js +2 -4
  567. package/dist/tools/gc-data-projects.js +5 -5
  568. package/dist/tools/generate-execution-plan.js +3 -4
  569. package/dist/tools/generate-sub-agent.js +2 -1
  570. package/dist/tools/generate-tests/generators/a11y-tests-generator.js +5 -4
  571. package/dist/tools/generate-tests/generators/advanced-testing-generator.js +5 -4
  572. package/dist/tools/generate-tests/generators/concurrency-test-generator/js-templates.js +9 -4
  573. package/dist/tools/generate-tests/generators/concurrency-test-generator.js +8 -4
  574. package/dist/tools/generate-tests/generators/database/detectors.js +9 -3
  575. package/dist/tools/generate-tests/generators/database/index.js +2 -4
  576. package/dist/tools/generate-tests/generators/event-test-generator.js +5 -4
  577. package/dist/tools/generate-tests/generators/game-tests-generator.js +2 -1
  578. package/dist/tools/generate-tests/generators/graphql-test-generator.js +11 -5
  579. package/dist/tools/generate-tests/generators/grpc-test-generator.js +2 -3
  580. package/dist/tools/generate-tests/generators/llm-security-test-generator.js +4 -3
  581. package/dist/tools/generate-tests/generators/local-first-test-generator.js +4 -3
  582. package/dist/tools/generate-tests/generators/mcp-tests-generator.js +11 -9
  583. package/dist/tools/generate-tests/generators/microservices/index.js +2 -3
  584. package/dist/tools/generate-tests/generators/otel-test-generator.js +6 -3
  585. package/dist/tools/generate-tests/generators/security/detectors.js +2 -5
  586. package/dist/tools/generate-tests/generators/security/index.js +2 -4
  587. package/dist/tools/generate-tests/generators/supply-chain-test-generator.js +2 -3
  588. package/dist/tools/generate-tests/generators/visual-regression-generator.js +14 -17
  589. package/dist/tools/generate-tests/generators/websocket-test-generator.js +2 -3
  590. package/dist/tools/generate-tests/test-helpers.js +11 -12
  591. package/dist/tools/generate-tests-content.js +4 -3
  592. package/dist/tools/generate-tests.js +7 -4
  593. package/dist/tools/git/git-helpers.d.ts +0 -2
  594. package/dist/tools/git/git-helpers.js +7 -7
  595. package/dist/tools/github-pr-handler.js +10 -3
  596. package/dist/tools/heal-spec-docs.js +6 -53
  597. package/dist/tools/hook-generator-handler.js +6 -6
  598. package/dist/tools/init-constitution/platform-principles.js +4 -2
  599. package/dist/tools/init-project/agents-md-writer.js +14 -5
  600. package/dist/tools/init-project/claude-md-generator.js +19 -12
  601. package/dist/tools/init-project/handler.js +165 -73
  602. package/dist/tools/init-project/host-assets-writer.d.ts +1 -1
  603. package/dist/tools/init-project/host-assets-writer.js +4 -2
  604. package/dist/tools/init-project/lifecycle-helpers.js +3 -5
  605. package/dist/tools/init-project/lint-scaffolder.js +6 -2
  606. package/dist/tools/init-project/migration-runner.d.ts +10 -1
  607. package/dist/tools/init-project/migration-runner.js +68 -3
  608. package/dist/tools/init-project/per-client-files-writer.js +14 -4
  609. package/dist/tools/init-project/rules-generator.js +10 -2
  610. package/dist/tools/init-project/scaffold-writer.d.ts +1 -1
  611. package/dist/tools/init-project/scaffold-writer.js +17 -15
  612. package/dist/tools/jobs/handlers.d.ts +15 -0
  613. package/dist/tools/jobs/handlers.js +126 -0
  614. package/dist/tools/list-specs.js +35 -34
  615. package/dist/tools/manage-plugins-handler.js +17 -9
  616. package/dist/tools/migrate-tech/advanced-handlers.js +3 -2
  617. package/dist/tools/migrate-tech/build-tool-handlers.js +3 -2
  618. package/dist/tools/migrate-tech/core-handlers.js +5 -2
  619. package/dist/tools/migrate-tech/data-handlers.js +6 -3
  620. package/dist/tools/migrate-tech-advanced/rollback-handlers.js +3 -2
  621. package/dist/tools/migrate-tech-advanced/service-handlers.js +5 -2
  622. package/dist/tools/oauth-handler.js +7 -1
  623. package/dist/tools/register-sdd-tools.d.ts +1 -1
  624. package/dist/tools/register-sdd-tools.js +5 -0
  625. package/dist/tools/register-spec-tools/core-spec-tools.js +31 -0
  626. package/dist/tools/registry/auth.js +13 -5
  627. package/dist/tools/registry/publish.js +7 -4
  628. package/dist/tools/resolve-project-path.d.ts +2 -2
  629. package/dist/tools/resolve-project-path.js +7 -7
  630. package/dist/tools/reverse-engineer/analyzer.js +14 -14
  631. package/dist/tools/rollback-release.js +3 -2
  632. package/dist/tools/safe-handler.js +295 -171
  633. package/dist/tools/schema-generator-handler.js +2 -1
  634. package/dist/tools/schemas/output-schemas.d.ts +88 -82
  635. package/dist/tools/schemas/output-schemas.js +12 -94
  636. package/dist/tools/schemas/plugins-schemas.js +0 -2
  637. package/dist/tools/schemas/registry.js +0 -2
  638. package/dist/tools/schemas/skill-registry-schemas.js +0 -2
  639. package/dist/tools/schemas/validate-output-schema.d.ts +256 -0
  640. package/dist/tools/schemas/validate-output-schema.js +212 -0
  641. package/dist/tools/sentry-handler.js +6 -1
  642. package/dist/tools/skill-bootstrap-handler.js +7 -4
  643. package/dist/tools/status-handler.js +4 -0
  644. package/dist/tools/storage-bundle-handler.d.ts +9 -0
  645. package/dist/tools/storage-bundle-handler.js +29 -0
  646. package/dist/tools/storage-paths-handler.d.ts +9 -0
  647. package/dist/tools/storage-paths-handler.js +17 -0
  648. package/dist/tools/suggest-mcp-server.js +11 -5
  649. package/dist/tools/suggest-mcps.js +29 -9
  650. package/dist/tools/suggest-tooling/advanced-testing-catalog.js +4 -5
  651. package/dist/tools/suggest-tooling/build-tool-catalog.js +2 -1
  652. package/dist/tools/suggest-tooling/css-framework-catalog.js +13 -7
  653. package/dist/tools/suggest-tooling/framework-catalog.js +3 -5
  654. package/dist/tools/suggest-tooling/frontend-perf-catalog.js +2 -6
  655. package/dist/tools/suggest-tooling/handler.js +10 -4
  656. package/dist/tools/suggest-tooling/hypermedia-catalog.js +11 -3
  657. package/dist/tools/suggest-tooling/linting-catalog.js +4 -7
  658. package/dist/tools/suggest-tooling/llm-security-catalog.js +2 -1
  659. package/dist/tools/suggest-tooling/local-first-catalog.js +7 -5
  660. package/dist/tools/suggest-tooling/observability-catalog.js +3 -4
  661. package/dist/tools/suggest-tooling/otel-catalog.js +4 -1
  662. package/dist/tools/suggest-tooling/resilience-catalog.js +16 -5
  663. package/dist/tools/suggest-tooling/skills-catalog.js +10 -9
  664. package/dist/tools/suggest-tooling/supply-chain-catalog.js +2 -3
  665. package/dist/tools/supabase-handler.js +2 -1
  666. package/dist/tools/token-intelligence-handler.js +2 -2
  667. package/dist/tools/token-recording.js +2 -2
  668. package/dist/tools/token-savings-handler.js +2 -2
  669. package/dist/tools/tool-registry/core-tools.js +131 -0
  670. package/dist/tools/tool-registry/group-infra.js +10 -12
  671. package/dist/tools/tool-registry/group-quality-compliance.js +5 -12
  672. package/dist/tools/update-status/approval-gates.d.ts +13 -0
  673. package/dist/tools/update-status/approval-gates.js +81 -0
  674. package/dist/tools/update-status/batch.js +4 -2
  675. package/dist/tools/update-status/dod-gates.d.ts +6 -24
  676. package/dist/tools/update-status/dod-gates.js +60 -135
  677. package/dist/tools/update-status/done-receipt-verifier.d.ts +15 -0
  678. package/dist/tools/update-status/done-receipt-verifier.js +145 -0
  679. package/dist/tools/update-status/evidence-gate.js +154 -2
  680. package/dist/tools/update-status/file-sync.js +23 -12
  681. package/dist/tools/update-status/gate-harness.d.ts +7 -0
  682. package/dist/tools/update-status/gate-harness.js +8 -0
  683. package/dist/tools/update-status/index.js +228 -325
  684. package/dist/tools/update-status/qa-gate.d.ts +1 -1
  685. package/dist/tools/update-status/qa-gate.js +2 -2
  686. package/dist/tools/update-status/side-effects.js +30 -37
  687. package/dist/tools/update-status/transition-guard.d.ts +4 -2
  688. package/dist/tools/update-status/transition-guard.js +57 -10
  689. package/dist/tools/update-status-convention-gate.js +24 -23
  690. package/dist/tools/update-status-reconcile.js +2 -2
  691. package/dist/tools/validate-api-contract-handler.js +3 -3
  692. package/dist/tools/validate-lint.js +20 -13
  693. package/dist/tools/validate.d.ts +3 -1
  694. package/dist/tools/validate.js +213 -5
  695. package/dist/transports/http-transport.js +84 -61
  696. package/dist/transports/middleware/with-telemetry.js +3 -2
  697. package/dist/types/abortable-process.d.ts +2 -0
  698. package/dist/types/advanced-framework.js +0 -2
  699. package/dist/types/atomic-upgrade.d.ts +71 -0
  700. package/dist/types/atomic-upgrade.js +2 -0
  701. package/dist/types/ci.js +0 -2
  702. package/dist/types/core-bridge.d.ts +78 -1
  703. package/dist/types/crash-shield-framework-rules.d.ts +24 -0
  704. package/dist/types/crash-shield-framework-rules.js +2 -0
  705. package/dist/types/data-gc.d.ts +16 -0
  706. package/dist/types/deploy.js +0 -2
  707. package/dist/types/durable-job.d.ts +78 -0
  708. package/dist/types/durable-job.js +2 -0
  709. package/dist/types/durable-validation.d.ts +60 -0
  710. package/dist/types/durable-validation.js +2 -0
  711. package/dist/types/estimation.d.ts +2 -0
  712. package/dist/types/evidence-gates.d.ts +9 -1
  713. package/dist/types/execution.d.ts +43 -0
  714. package/dist/types/handoff-artifacts.d.ts +2 -0
  715. package/dist/types/index.d.ts +2 -0
  716. package/dist/types/index.js +2 -0
  717. package/dist/types/infrastructure.js +0 -2
  718. package/dist/types/lifecycle.js +0 -2
  719. package/dist/types/migration/canonical-storage.d.ts +37 -0
  720. package/dist/types/migration/canonical-storage.js +2 -0
  721. package/dist/types/migration/index.d.ts +1 -1
  722. package/dist/types/native-worker.d.ts +48 -0
  723. package/dist/types/native-worker.js +2 -0
  724. package/dist/types/network-policy.d.ts +12 -0
  725. package/dist/types/network-policy.js +2 -0
  726. package/dist/types/oauth.js +0 -2
  727. package/dist/types/observability.d.ts +32 -0
  728. package/dist/types/outbox-worker.d.ts +35 -0
  729. package/dist/types/outbox-worker.js +11 -0
  730. package/dist/types/permissions-config.d.ts +0 -27
  731. package/dist/types/permissions-config.js +0 -2
  732. package/dist/types/plugin-install.d.ts +0 -11
  733. package/dist/types/plugin-install.js +0 -2
  734. package/dist/types/portal.d.ts +1 -0
  735. package/dist/types/product-public.d.ts +75 -0
  736. package/dist/types/product-public.js +2 -0
  737. package/dist/types/project/inputs.d.ts +2 -0
  738. package/dist/types/project/mfe-detection.js +0 -2
  739. package/dist/types/project/platform-mobile.js +0 -2
  740. package/dist/types/project/platform-specialty.js +0 -2
  741. package/dist/types/project-knowledge-graph.d.ts +7 -0
  742. package/dist/types/runtime-database.d.ts +10 -0
  743. package/dist/types/runtime-database.js +2 -0
  744. package/dist/types/runtime-policy.d.ts +40 -0
  745. package/dist/types/runtime-policy.js +2 -0
  746. package/dist/types/safety.d.ts +4 -5
  747. package/dist/types/schema-registry.d.ts +12 -0
  748. package/dist/types/schema-registry.js +2 -0
  749. package/dist/types/security.d.ts +52 -0
  750. package/dist/types/skill-registry.js +0 -2
  751. package/dist/types/spec/inputs.d.ts +2 -0
  752. package/dist/types/spec-lock-v2.d.ts +13 -7
  753. package/dist/types/spec-lock-v2.js +1 -1
  754. package/dist/types/spec-registry.js +0 -2
  755. package/dist/types/storage-bundle.d.ts +13 -0
  756. package/dist/types/storage-bundle.js +2 -0
  757. package/dist/types/storage-catalog.d.ts +18 -0
  758. package/dist/types/storage-catalog.js +2 -0
  759. package/dist/types/team-planner.js +0 -2
  760. package/dist/types/technology-registry.d.ts +35 -0
  761. package/dist/types/technology-registry.js +2 -0
  762. package/dist/types/technology-symbols.generated.d.ts +117 -0
  763. package/dist/types/technology-symbols.generated.js +2 -0
  764. package/dist/types/telemetry.d.ts +3 -3
  765. package/dist/types/transport.d.ts +2 -0
  766. package/dist/types/validate-worker.d.ts +44 -0
  767. package/dist/types/validate-worker.js +2 -0
  768. package/dist/types/validation-evidence.d.ts +1 -1
  769. package/dist/types/validation-receipt.d.ts +104 -0
  770. package/dist/types/validation-receipt.js +2 -0
  771. package/package.json +31 -20
  772. package/planu-native.json +1 -1
  773. package/planu-plugin.json +1 -1
  774. package/dist/engine/telemetry/geo-resolver.d.ts +0 -9
  775. package/dist/engine/telemetry/geo-resolver.js +0 -43
  776. package/dist/storage/data-dir-discovery.d.ts +0 -31
  777. package/dist/storage/data-dir-discovery.js +0 -140
  778. package/dist/storage/migrations/cwd-to-absolute.d.ts +0 -25
  779. package/dist/storage/migrations/cwd-to-absolute.js +0 -281
  780. package/dist/tools/create-spec/adapters/prior-decisions-hint.d.ts +0 -14
  781. package/dist/tools/create-spec/adapters/prior-decisions-hint.js +0 -30
  782. package/dist/tools/init-project/ancestor-data-detector.d.ts +0 -22
  783. package/dist/tools/init-project/ancestor-data-detector.js +0 -81
  784. package/dist/tools/update-status/force-done-audit.d.ts +0 -2
  785. package/dist/tools/update-status/force-done-audit.js +0 -23
  786. package/dist/types/migration/cwd-to-absolute.d.ts +0 -8
  787. package/dist/types/migration/cwd-to-absolute.js +0 -3
@@ -2,22 +2,22 @@ import { elicitOrFallback, buildEnumSchema } from '../../engine/elicitation/elic
2
2
  import { ti } from '../../i18n/index.js';
3
3
  import { AutopilotSummaryCollector } from '../../engine/autopilot/summary-collector.js';
4
4
  import { specStore, knowledgeStore } from '../../storage/index.js';
5
+ import { reportClassifiedDegradation } from '../../errors/classified-degradation.js';
5
6
  import { rollbackTransitionSpec, transitionSpec, } from '../../engine/spec-state-machine/transition-spec.js';
6
7
  import { calculateAccuracy } from '../../engine/estimator.js';
7
8
  import { cascadeCheck } from '../../engine/spec-versioner.js';
8
9
  import { runComplianceGates } from '../update-status-convention-gate.js';
9
10
  import { runDoneActions, runDoneSideEffects, runImplementingActions, runImplementingSideEffects, } from '../update-status-actions.js';
10
11
  import { compactObj } from '../../engine/compact-obj.js';
11
- import { checkTransition, checkDorGate, checkAmbiguityGate, checkReadinessGate, checkChallengeGate, resolveAutoAdvanceSteps, isReverseTransition, validateReverseTransition, } from './transition-guard.js';
12
+ import { checkTransition, checkDorGate, checkAmbiguityGate, checkReadinessGate, checkChallengeGate, checkImplementationDependencyGate, resolveAutoAdvanceSteps, isReverseTransition, validateReverseTransition, } from './transition-guard.js';
12
13
  import { checkApprovedDepGate } from '../../engine/dep-guard/index.js';
13
14
  import { checkApprovalGate } from '../../engine/approval-workflow.js';
14
15
  import * as approvalStore from '../../storage/approval-store.js';
15
16
  import { withApprovalSpecLock } from '../../storage/approval-operation-lock.js';
16
17
  import { isLocked, getLock } from '../../storage/spec-lock-store.js';
17
- import { runValidateGate, checkDoneGates, checkComplianceGate, checkQaGate, checkApprovedFormatGate, readApprovedValidationReportGate, checkSpecReviewGate, writeSpecReviewArtifact, } from './dod-gates.js';
18
- import { writeImplementationReviewReport } from '../../engine/validator/validation-report-writer.js';
18
+ import { checkDoneGates, checkComplianceGate, checkApprovedFormatGate, checkSpecReviewGate, writeSpecReviewArtifact, } from './dod-gates.js';
19
19
  import { checkLifecycleEvidenceTransitionGate } from './evidence-gate.js';
20
- import { buildStatusResponse, buildValidateBlockedResponse, buildDryRunResponse, } from './response-builder.js';
20
+ import { buildStatusResponse, buildDryRunResponse } from './response-builder.js';
21
21
  import { recordDoneMetrics, syncSpecFiles, tryReconcile, recordTerminalTransitionEvent, } from './file-sync.js';
22
22
  import { appendEntry, getLastHash } from '../../storage/audit-trail-store.js';
23
23
  import { appendTransitionEvent } from '../../storage/transition-log.js';
@@ -28,10 +28,7 @@ import { recordForceUsage } from '../../storage/force-analytics-store.js';
28
28
  import { maybeSafePushOnDone, queuePostCommitTasks, runCascadeForResponse, } from './side-effects.js';
29
29
  import { formatKeyValue } from '../output-formatter.js';
30
30
  import { checkCodeReality } from '../../engine/code-scanner/index.js';
31
- import { scanCrashRisks } from '../../engine/crash-shield/index.js';
32
- import { shouldSkipCrashScan, recordCrashScanRun, } from '../../engine/autopilot/crash-shield-rate-limiter.js';
33
- import { mkdir, writeFile } from 'node:fs/promises';
34
- import { join, dirname } from 'node:path';
31
+ import { join } from 'node:path';
35
32
  import { trackCost } from '../../engine/cost-tracking/operation-tracker.js';
36
33
  import { resolveProjectIdOrAutoDetect } from '../resolve-project-id.js';
37
34
  import { withToolTimeout } from '../safe-handler.js';
@@ -39,7 +36,10 @@ import { detectHost } from '../../engine/host-detection/detect-host.js';
39
36
  import { shellHygieneReminder } from '../../hosts/claude-code/coach.js';
40
37
  import { buildTransitionEvidenceMeta, checkSddModelRoutingGate, } from '../../engine/sdd-model-routing.js';
41
38
  import { acquireLock, releaseLock, isLocked as isCrossProcessLocked, LockBusyError, } from '../../engine/safety/cross-process-lock.js';
42
- import { validateStrictLayoutOrError } from '../validate-helpers.js';
39
+ import { projectDataDir } from '../../storage/base-store.js';
40
+ import { assertExecutionCanCommit } from '../../engine/execution/context.js';
41
+ import { shouldSkipGateForExplicitLegacyHarness } from './gate-harness.js';
42
+ import { assertValidationFreshnessBarrier, } from '../../engine/validation/validation-freshness.js';
43
43
  /**
44
44
  * SPEC-280: Silently traverse intermediate states so callers can jump forward
45
45
  * (e.g. draft → approved) without receiving an error.
@@ -141,9 +141,8 @@ async function createVersionSnapshot(specId, projectId, tag) {
141
141
  if (!spec) {
142
142
  return;
143
143
  }
144
- const snapshotPath = join('data', 'projects', projectId, 'version-snapshots', `${tag}.json`);
145
- await mkdir(dirname(snapshotPath), { recursive: true });
146
- await writeFile(snapshotPath, JSON.stringify(spec, null, 2), 'utf-8');
144
+ const snapshotPath = join(projectDataDir(projectId), 'version-snapshots', `${tag}.json`);
145
+ await atomicWriteFile(snapshotPath, `${JSON.stringify(spec, null, 2)}\n`);
147
146
  }
148
147
  function checkIdempotentOrTransition(projectId, spec, target) {
149
148
  if (spec.status === target) {
@@ -361,7 +360,10 @@ async function recoverPendingPostCommitTasks(projectId, projectPath) {
361
360
  }
362
361
  }
363
362
  finally {
364
- await releaseLock(recoveryLock).catch(() => undefined);
363
+ await releaseLock(recoveryLock).catch((error) => {
364
+ /* reliability-cleanup: RECOVERY_LOCK_RELEASE — lease expiry remains the recovery boundary */
365
+ reportClassifiedDegradation('RECOVERY_LOCK_RELEASE', error);
366
+ });
365
367
  }
366
368
  }
367
369
  }
@@ -405,15 +407,106 @@ function buildPersistenceFailureResponse(args) {
405
407
  },
406
408
  };
407
409
  }
408
- /** SPEC-628: Check crash scan rate-limit and return skip reason if within window. */
409
- async function checkCrashScanRateLimit(newStatus, effectiveGatePath) {
410
- if (newStatus !== 'done' || !effectiveGatePath) {
411
- return null;
412
- }
413
- const skipCheck = await shouldSkipCrashScan(effectiveGatePath).catch(() => ({
414
- skip: false,
415
- }));
416
- return skipCheck.skip ? (skipCheck.reason ?? 'recently scanned') : null;
410
+ async function commitTransitionWithNarrowLock(args) {
411
+ return withApprovalSpecLock(args.projectPath, args.specId, async () => {
412
+ const lock = await acquireLock(args.projectPath, args.specId, {
413
+ reason: `update_status(${args.newStatus}) commit`,
414
+ });
415
+ if (lock === null) {
416
+ return {
417
+ ok: false,
418
+ error: {
419
+ content: [
420
+ {
421
+ type: 'text',
422
+ text: `Spec ${args.specId} is locked by another process (cross-process lock). Retry later.`,
423
+ },
424
+ ],
425
+ isError: true,
426
+ },
427
+ };
428
+ }
429
+ try {
430
+ const freshSpec = typeof specStore.getSpecFresh === 'function'
431
+ ? await specStore.getSpecFresh(args.projectId, args.specId)
432
+ : await specStore.getSpec(args.projectId, args.specId);
433
+ if (freshSpec?.status !== args.expectedSpec.status ||
434
+ freshSpec.updatedAt !== args.expectedSpec.updatedAt) {
435
+ return {
436
+ ok: false,
437
+ error: {
438
+ content: [
439
+ {
440
+ type: 'text',
441
+ text: `Spec ${args.specId} changed while lifecycle gates were running. Retry with the fresh state.`,
442
+ },
443
+ ],
444
+ isError: true,
445
+ structuredContent: { error: 'TRANSITION_CONFLICT', code: 409 },
446
+ },
447
+ };
448
+ }
449
+ if (args.newStatus === 'done' &&
450
+ (!args.freshnessLease || !(await assertValidationFreshnessBarrier(args.freshnessLease))) &&
451
+ !shouldSkipGateForExplicitLegacyHarness('evidence')) {
452
+ return {
453
+ ok: false,
454
+ error: {
455
+ content: [
456
+ {
457
+ type: 'text',
458
+ text: `Validation inputs for ${args.specId} changed before commit. Re-run validate.`,
459
+ },
460
+ ],
461
+ isError: true,
462
+ structuredContent: { error: 'VALIDATION_RECEIPT_STALE', code: 409 },
463
+ },
464
+ };
465
+ }
466
+ assertExecutionCanCommit();
467
+ const transitionRecord = await transitionSpec(args.projectId, args.specId, args.newStatus, {
468
+ ...args.options,
469
+ expectedSpec: freshSpec,
470
+ });
471
+ const updatedSpec = transitionRecord.spec;
472
+ const syncResult = await syncSpecFiles(updatedSpec, args.originalStatus, args.newStatus, args.projectPath);
473
+ if (!syncResult.warning) {
474
+ return { ok: true, transitionRecord, updatedSpec };
475
+ }
476
+ try {
477
+ await rollbackTransitionSpec(transitionRecord);
478
+ return {
479
+ ok: false,
480
+ error: buildPersistenceFailureResponse({
481
+ specId: args.specId,
482
+ previousStatus: args.originalStatus,
483
+ newStatus: args.newStatus,
484
+ reason: syncResult.warning.reason,
485
+ recoveryRequired: false,
486
+ }),
487
+ };
488
+ }
489
+ catch (rollbackError) {
490
+ return {
491
+ ok: false,
492
+ error: buildPersistenceFailureResponse({
493
+ specId: args.specId,
494
+ previousStatus: args.originalStatus,
495
+ newStatus: args.newStatus,
496
+ reason: `${syncResult.warning.reason}; compensation failed: ` +
497
+ (rollbackError instanceof Error ? rollbackError.message : String(rollbackError)),
498
+ recoveryRequired: true,
499
+ }),
500
+ };
501
+ }
502
+ }
503
+ finally {
504
+ await releaseLock(lock).catch((error) => {
505
+ /* reliability-cleanup: UPDATE_STATUS_LOCK_RELEASE — lease expiry remains the recovery boundary */
506
+ reportClassifiedDegradation('UPDATE_STATUS_LOCK_RELEASE', error);
507
+ });
508
+ }
509
+ });
417
510
  }
418
511
  /** Build fallback interactiveQuestion for status confirmation (SPEC-595). */
419
512
  function buildStatusConfirmFallback(specId, newStatus) {
@@ -468,20 +561,15 @@ async function resolveOrchestrationPlan(newStatus, specScope, specId, projectPat
468
561
  }
469
562
  return withToolTimeout(import('../orchestrate-agents-handler.js')
470
563
  .then(({ buildOrchestrationPlanSummary }) => buildOrchestrationPlanSummary(specId, projectPath))
471
- .catch(() => null), 5_000, null);
472
- }
473
- function shouldSkipSddRoutingGateForLegacyTestHarness() {
474
- return process.env.VITEST === 'true' && process.env.PLANU_TEST_STRICT_SDD_GATES !== 'true';
475
- }
476
- function shouldSkipEvidenceGateForLegacyTestHarness() {
477
- return process.env.VITEST === 'true' && process.env.PLANU_TEST_STRICT_EVIDENCE_GATES !== 'true';
478
- }
479
- function shouldSkipStrictLayoutGateForLegacyTestHarness() {
480
- return process.env.VITEST === 'true' && process.env.PLANU_TEST_STRICT_LAYOUT_GATE !== 'true';
564
+ .catch((error) => {
565
+ // reliability-optional: ORCHESTRATION_PLAN_SUMMARY — summary enrichment is non-authoritative
566
+ reportClassifiedDegradation('ORCHESTRATION_PLAN_SUMMARY', error);
567
+ return null;
568
+ }), 5_000, null);
481
569
  }
482
570
  /* eslint-disable complexity, max-lines-per-function */
483
571
  export async function handleUpdateStatus(params, server) {
484
- return trackCost(params.projectPath ?? '', 'update_status', async () => {
572
+ return trackCost(params.projectPath?.trim() ?? '', 'update_status', async () => {
485
573
  const { specId, status: newStatus, actuals, reviewNotes } = params;
486
574
  // SPEC-509: auto-detect project from git root when projectPath/projectId are omitted
487
575
  const resolved = await resolveProjectIdOrAutoDetect({
@@ -498,50 +586,33 @@ export async function handleUpdateStatus(params, server) {
498
586
  const { runStrictPlanuCleanup } = await import('../../engine/spec-migrator/index.js');
499
587
  await runStrictPlanuCleanup(effectiveProjectPath);
500
588
  }
501
- catch {
502
- /* strict cleanup is best-effort here; validate fails closed if artifacts remain */
589
+ catch (error) {
590
+ /* reliability-cleanup: PRE_TRANSITION_STRICT_CLEANUP validate remains fail-closed */
591
+ reportClassifiedDegradation('PRE_TRANSITION_STRICT_CLEANUP', error);
503
592
  }
504
593
  }
505
594
  await recoverPendingPostCommitTasks(projectId, effectiveProjectPath).catch((error) => {
506
- console.warn('[planu:post-commit] automatic recovery scan failed', {
507
- projectId,
508
- error: error instanceof Error ? error.message : String(error),
509
- });
595
+ /* reliability-optional: POST_COMMIT_RECOVERY_SCAN durable tasks remain retryable */
596
+ reportClassifiedDegradation('POST_COMMIT_RECOVERY_SCAN', error);
510
597
  });
511
- return withApprovalSpecLock(effectiveProjectPath, specId, async () => {
598
+ return (async () => {
512
599
  try {
513
600
  // SPEC-301: Reject status changes when spec is locked by another holder (legacy manual lock)
514
601
  const lockError = await checkSpecLockGate(effectiveProjectPath, specId);
515
602
  if (lockError) {
516
603
  return lockError;
517
604
  }
518
- // SPEC-731: dry_run never acquires the cross-process lock.
519
- // SPEC-719: Cross-process disk lock acquire before any spec.md mutation.
520
- // Released in finally below. Best-effort when no projectPath is available.
605
+ // Dry-run checks availability without acquiring. Real mutations acquire only
606
+ // around the compare-and-swap plus spec/store commit below.
521
607
  const isDryRun = params.dry_run === true;
522
- let crossProcessLockHandle = null;
523
- if (!isDryRun) {
524
- crossProcessLockHandle = await acquireLock(effectiveProjectPath, specId, {
525
- reason: `update_status(${newStatus})`,
526
- });
527
- if (crossProcessLockHandle === null) {
528
- // acquireLock returns null only when another live session holds the lock
529
- // For dry_run, return a special response indicating lock is busy
530
- return {
531
- content: [
532
- {
533
- type: 'text',
534
- text: `Spec ${specId} is locked by another process (cross-process lock). Retry later or inspect data/.locks/planu/${specId}.lock`,
535
- },
536
- ],
537
- isError: true,
538
- };
539
- }
540
- }
541
- else {
608
+ if (isDryRun) {
542
609
  // SPEC-731: dry_run checks lock availability without acquiring it.
543
610
  // isLocked returns null when no lockfile exists (available), or a LockInfo when locked.
544
- const lockInfo = await isCrossProcessLocked(effectiveProjectPath, specId).catch(() => null);
611
+ const lockInfo = await isCrossProcessLocked(effectiveProjectPath, specId).catch((error) => {
612
+ // reliability-optional: DRY_RUN_LOCK_PROBE — null conservatively avoids stale lock claims
613
+ reportClassifiedDegradation('DRY_RUN_LOCK_PROBE', error);
614
+ return null;
615
+ });
545
616
  const lockIsBusy = lockInfo !== null && !lockInfo.stale;
546
617
  if (lockIsBusy) {
547
618
  // Lock is busy — return dry_run result indicating this without blocking
@@ -562,11 +633,9 @@ export async function handleUpdateStatus(params, server) {
562
633
  }
563
634
  }
564
635
  try {
565
- // Reload only after the per-spec lock is held. This snapshot is the sole
566
- // input for gates, transition persistence, and rollback compensation.
567
- const spec = crossProcessLockHandle !== null && typeof specStore.getSpecFresh === 'function'
568
- ? await specStore.getSpecFresh(projectId, specId)
569
- : await specStore.getSpec(projectId, specId);
636
+ // Gates consume an unlocked snapshot. Commit revalidates this snapshot
637
+ // under the narrow mutation lock before compare-and-swap.
638
+ const spec = await specStore.getSpec(projectId, specId);
570
639
  if (!spec) {
571
640
  return {
572
641
  content: [{ type: 'text', text: ti('spec.notFound', { id: specId }) }],
@@ -672,9 +741,12 @@ export async function handleUpdateStatus(params, server) {
672
741
  }
673
742
  // SPEC-728: DepGuard — block 'approved' if spec participates in a dependency cycle
674
743
  let depGuardResult = null;
744
+ let allSpecsForDependencyGate = null;
745
+ if (plannedStatuses.includes('approved') || plannedStatuses.includes('implementing')) {
746
+ allSpecsForDependencyGate = await specStore.listSpecs(projectId);
747
+ }
675
748
  if (plannedStatuses.includes('approved')) {
676
- const allSpecsForDepGuard = await specStore.listSpecs(projectId);
677
- depGuardResult = checkApprovedDepGate(spec, allSpecsForDepGuard);
749
+ depGuardResult = checkApprovedDepGate(spec, allSpecsForDependencyGate ?? []);
678
750
  if (depGuardResult.blocked) {
679
751
  return {
680
752
  content: [{ type: 'text', text: `DepGuard blocked: ${depGuardResult.narrative}` }],
@@ -689,6 +761,12 @@ export async function handleUpdateStatus(params, server) {
689
761
  };
690
762
  }
691
763
  }
764
+ if (plannedStatuses.includes('implementing')) {
765
+ const dependencyGate = checkImplementationDependencyGate(spec, allSpecsForDependencyGate ?? [], 'implementing');
766
+ if (dependencyGate) {
767
+ return dependencyGate;
768
+ }
769
+ }
692
770
  // SPEC-964: Challenge gate — block 'review' if challenge_spec was never run
693
771
  const challengeGateStatus = plannedStatuses.includes('review') ? 'review' : newStatus;
694
772
  const challengeGate = checkChallengeGate(spec, challengeGateStatus);
@@ -709,14 +787,14 @@ export async function handleUpdateStatus(params, server) {
709
787
  // Load knowledge for project path (needed for DoD gates, validate trigger and HTML regen)
710
788
  const knowledge = await knowledgeStore.getKnowledge(projectId);
711
789
  // Resolve effective project path once — used across all gates below
712
- const effectiveGatePath = knowledge?.projectPath ?? params.projectPath;
790
+ const effectiveGatePath = knowledge?.projectPath ?? effectiveProjectPath;
713
791
  // SPEC-1044: SDD model-routing + context continuity hard gate.
714
792
  const sddRoutingGate = {
715
793
  blockResult: null,
716
794
  gateResults: { sddModelRouting: 'skip' },
717
795
  forcedReasons: [],
718
796
  };
719
- if (!shouldSkipSddRoutingGateForLegacyTestHarness()) {
797
+ if (!shouldSkipGateForExplicitLegacyHarness('routing')) {
720
798
  const routedStatuses = plannedStatuses.filter((status) => status === 'approved' || status === 'implementing' || status === 'done');
721
799
  for (const status of routedStatuses) {
722
800
  const gate = await checkSddModelRoutingGate({
@@ -737,7 +815,7 @@ export async function handleUpdateStatus(params, server) {
737
815
  // SPEC-1054: BDD/SDD evidence gates. Non-trivial specs must carry
738
816
  // Discovery before approval, task-plan before implementation, and
739
817
  // traceability/contract evidence before done.
740
- if (!shouldSkipEvidenceGateForLegacyTestHarness()) {
818
+ if (!shouldSkipGateForExplicitLegacyHarness('evidence')) {
741
819
  const evidenceStatuses = plannedStatuses.filter((status) => status === 'approved' || status === 'implementing' || status === 'done');
742
820
  for (const transition of evidenceStatuses) {
743
821
  const evidenceGate = await checkLifecycleEvidenceTransitionGate({
@@ -757,24 +835,22 @@ export async function handleUpdateStatus(params, server) {
757
835
  // SPEC-441: Code reality check before transitioning to 'implementing'
758
836
  // SPEC-335: DoD + security gates before transitioning to 'done'
759
837
  // ---------------------------------------------------------------------------
760
- // SPEC-642: QA gate block done if typecheck + test:coverage have not passed
761
- // ---------------------------------------------------------------------------
762
- if (newStatus === 'done') {
763
- const qaGateResult = await checkQaGate(spec, effectiveGatePath, params.force ?? false);
764
- if (qaGateResult !== null) {
765
- return qaGateResult;
766
- }
767
- }
768
- // ---------------------------------------------------------------------------
838
+ // `done` consumes the immutable validation receipt below. Validation, QA,
839
+ // security and repository scans belong to the durable validation worker.
769
840
  let codeRealityWarning = null;
770
841
  let forcedBypassWarning = null;
842
+ let doneFreshnessLease;
771
843
  const [codeRealityResult, doneGatesResult] = await Promise.all([
772
844
  // Code reality: only relevant for 'implementing'
773
845
  newStatus === 'implementing' && !reverseTransition && effectiveGatePath
774
- ? checkCodeReality(effectiveGatePath, spec.title).catch(() => null)
846
+ ? checkCodeReality(effectiveGatePath, spec.title).catch((error) => {
847
+ // reliability-optional: CODE_REALITY_ENRICHMENT — downstream evidence gates remain binding
848
+ reportClassifiedDegradation('CODE_REALITY_ENRICHMENT', error);
849
+ return null;
850
+ })
775
851
  : Promise.resolve(null),
776
852
  // Done gates: only relevant for 'done'
777
- newStatus === 'done'
853
+ newStatus === 'done' && !shouldSkipGateForExplicitLegacyHarness('evidence')
778
854
  ? checkDoneGates(spec, specId, projectId, effectiveGatePath, params.force, params.forceStatusReason ?? params.reason ?? 'No force reason provided')
779
855
  : Promise.resolve(null),
780
856
  ]);
@@ -788,89 +864,24 @@ export async function handleUpdateStatus(params, server) {
788
864
  return doneGatesResult.blocked;
789
865
  }
790
866
  forcedBypassWarning = doneGatesResult.forcedBypassWarning;
867
+ doneFreshnessLease = doneGatesResult.freshnessLease ?? undefined;
791
868
  }
792
869
  // ---------------------------------------------------------------------------
793
- // BATCH B (parallel): validate + crash-shield + compliance — independent of
794
- // each other, all need spec/projectPath (available from Batch A outputs)
795
- // SPEC-222: Auto-validate before marking done
796
- // SPEC-442: Crash Shield warning on 'done'
797
- // SPEC-447: Compliance gate on 'review' or 'implementing'
870
+ // Review-only heuristic compliance. `done` must remain an O(1) receipt
871
+ // consumer and therefore must not execute commands or scan the repository.
798
872
  // ---------------------------------------------------------------------------
799
- let validateScore = null;
800
- let validateScoreSource = null;
801
- let crashShieldWarning = null;
802
- let crashShieldSkipReason = null;
873
+ const validateScore = null;
874
+ const validateScoreSource = null;
875
+ const crashShieldWarning = null;
803
876
  let complianceGateResult = null;
804
- let validationReportGate = null;
805
- // SPEC-628: Rate-limit crash scan check before entering the parallel batch
806
- crashShieldSkipReason = await checkCrashScanRateLimit(newStatus, effectiveGatePath ?? null);
807
- const [validateGateResult, crashRisksReport, complianceResult] = await Promise.all([
808
- // Validate: only on 'done'.
809
- // SPEC-721: timeout lives inside runValidateGate (Promise.race) — do NOT wrap with
810
- // withToolTimeout here, which would silently convert timeout into blocked:false (fail-open).
811
- newStatus === 'done'
812
- ? runValidateGate(spec, effectiveGatePath ?? '', params.forceStatus ?? false, params.forceStatusReason, 9_000, { projectId, specId })
813
- : Promise.resolve(null),
814
- // Crash shield: only on 'done', skipped if rate-limited (SPEC-628)
815
- newStatus === 'done' && effectiveGatePath && !crashShieldSkipReason
816
- ? withToolTimeout(scanCrashRisks(effectiveGatePath).catch(() => null), 9_000, null)
817
- : Promise.resolve(null),
818
- // The heuristic scorer is a review aid. Done relies on the authoritative validate report.
819
- plannedStatuses.includes('review')
820
- ? withToolTimeout(checkComplianceGate(specId, projectId, effectiveGatePath), 9_000, {
821
- skipped: true,
822
- blocked: false,
823
- score: null,
824
- issues: [],
825
- })
826
- : Promise.resolve(null),
827
- ]);
828
- // Process validate result — may block (SPEC-721: fail-closed)
829
- let forcedValidateBypass = null;
830
- if (validateGateResult !== null) {
831
- if (validateGateResult.blocked) {
832
- return buildValidateBlockedResponse(specId, validateGateResult);
833
- }
834
- validateScore = validateGateResult.score;
835
- if (validateGateResult.forced) {
836
- validateScoreSource = validateGateResult.scoreSource;
837
- forcedValidateBypass = {
838
- reason: validateGateResult.forcedReason,
839
- observedScore: validateGateResult.score,
840
- };
841
- }
842
- else {
843
- validateScoreSource = 'validateSpec';
844
- }
845
- }
846
- if (newStatus === 'done' &&
847
- effectiveGatePath &&
848
- !shouldSkipStrictLayoutGateForLegacyTestHarness()) {
849
- const strictLayoutError = await validateStrictLayoutOrError({
850
- projectPath: effectiveGatePath,
851
- specId,
852
- specPath: spec.specPath,
853
- failClosedOnCrash: true,
854
- });
855
- if (strictLayoutError) {
856
- return strictLayoutError;
857
- }
858
- }
859
- // Process crash shield result — record run timestamp on success (SPEC-628)
860
- /* c8 ignore next */
861
- if (crashRisksReport !== null) {
862
- if (crashRisksReport.score < 80) {
863
- const criticalCount = crashRisksReport.risks.filter((r) => r.severity === 'CRITICAL').length;
864
- crashShieldWarning =
865
- `Crash Shield: score ${String(crashRisksReport.score)}/100 — ${String(criticalCount)} critical risk(s) detected. ` +
866
- `Run \`scan_crash_risks\` for details.`;
867
- }
868
- if (effectiveGatePath) {
869
- void recordCrashScanRun(effectiveGatePath).catch(() => {
870
- /* best-effort */
871
- });
872
- }
873
- }
877
+ const complianceResult = plannedStatuses.includes('review')
878
+ ? await withToolTimeout(checkComplianceGate(specId, projectId, effectiveGatePath), 9_000, {
879
+ skipped: true,
880
+ blocked: false,
881
+ score: null,
882
+ issues: [],
883
+ })
884
+ : null;
874
885
  // Process compliance gate result — may block on 'review'
875
886
  if (complianceResult !== null) {
876
887
  complianceGateResult = complianceResult;
@@ -878,10 +889,9 @@ export async function handleUpdateStatus(params, server) {
878
889
  return buildBlockedByComplianceResponse(specId, complianceResult);
879
890
  }
880
891
  }
881
- // SPEC-190: Run all compliance gates in parallel (convention + constitution + compile + lint + test, non-blocking)
882
- // runComplianceGates internally skips heavy commands (compile/lint/test) for non-done transitions,
883
- // but 'approved' still needs constitutionWarnings so run for 'done' and 'approved' only.
884
- const { conventionWarnings, constitutionWarnings, compileWarnings, lintWarnings, testWarnings, } = newStatus === 'done' || plannedStatuses.includes('approved')
892
+ // Approved still needs constitution warnings. Done relies exclusively on
893
+ // the validation receipt and never invokes this legacy command runner.
894
+ const { conventionWarnings, constitutionWarnings, compileWarnings, lintWarnings, testWarnings, } = plannedStatuses.includes('approved')
885
895
  ? await runComplianceGates(projectId, spec.title, spec.tags, newStatus, specId)
886
896
  : {
887
897
  conventionWarnings: [],
@@ -890,38 +900,13 @@ export async function handleUpdateStatus(params, server) {
890
900
  lintWarnings: [],
891
901
  testWarnings: [],
892
902
  };
893
- if (newStatus === 'done' && !(params.force ?? params.forceStatus ?? false)) {
894
- if (!isDryRun && effectiveGatePath) {
895
- await writeImplementationReviewReport({
896
- projectId,
897
- specId,
898
- spec,
899
- projectPath: effectiveGatePath,
900
- score: validateScore,
901
- lintPassed: lintWarnings.length === 0,
902
- conventionRegression: conventionWarnings.length > 0,
903
- });
904
- }
905
- validationReportGate = await readApprovedValidationReportGate(specId, projectId, false);
906
- if (!validationReportGate.ok) {
907
- return validationReportGate.error;
908
- }
909
- if (validationReportGate.score !== null) {
910
- validateScore = validationReportGate.score;
911
- validateScoreSource = 'validation-report';
912
- }
913
- }
914
903
  // SPEC-731: dry_run short-circuit — all gates have been evaluated above.
915
904
  // Do NOT call transitionSpec, appendTransitionEvent, or acquire any lock.
916
905
  if (isDryRun) {
917
906
  const dryRunGates = {
918
907
  dod: newStatus === 'done' ? (doneGatesResult?.blocked ? 'fail' : 'pass') : 'skip',
919
- validate: newStatus === 'done'
920
- ? validateGateResult === null
921
- ? 'skip'
922
- : 'pass' // blocked case already returned above (line 615)
923
- : 'skip',
924
- qa: newStatus === 'done' ? 'pass' : 'skip', // QA gate runs above — if we reach here, it passed
908
+ validate: newStatus === 'done' ? 'pass' : 'skip',
909
+ qa: newStatus === 'done' ? 'pass' : 'skip',
925
910
  security: newStatus === 'done' ? (doneGatesResult?.blocked ? 'fail' : 'pass') : 'skip',
926
911
  lock: 'available',
927
912
  compliance: complianceGateResult === null
@@ -987,39 +972,7 @@ export async function handleUpdateStatus(params, server) {
987
972
  if (resolvedActuals) {
988
973
  nonStatusUpdates.actuals = resolvedActuals;
989
974
  }
990
- // SPEC-721: Audit-trail entry when forceStatus bypassed the validate gate
991
- let forceStatusAuditId = null;
992
- if (newStatus === 'done' && forcedValidateBypass !== null) {
993
- try {
994
- const auditId = uuid();
995
- const prevHash = getLastHash();
996
- // Hash this entry minimally — full chain hashing is handled by the audit engine on export
997
- const entry = {
998
- id: auditId,
999
- timestamp: new Date().toISOString(),
1000
- toolName: 'update_status',
1001
- inputSummary: `validate_gate_forced_bypass specId=${specId} score=${String(forcedValidateBypass.observedScore)} reason="${forcedValidateBypass.reason.slice(0, 80)}"`,
1002
- outputType: 'success',
1003
- durationMs: 0,
1004
- specId,
1005
- projectPath: effectiveGatePath ?? undefined,
1006
- prevHash,
1007
- hash: '',
1008
- event: 'validate_gate_forced_bypass',
1009
- details: {
1010
- reason: forcedValidateBypass.reason,
1011
- observedScore: forcedValidateBypass.observedScore,
1012
- fromStatus: originalStatus,
1013
- toStatus: newStatus,
1014
- },
1015
- };
1016
- appendEntry(entry);
1017
- forceStatusAuditId = auditId;
1018
- }
1019
- catch {
1020
- /* best-effort — audit must never block transition */
1021
- }
1022
- }
975
+ const forceStatusAuditId = null;
1023
976
  // SPEC-780: Audit-trail entry when forceApprove bypassed readiness/format gates
1024
977
  let forceApproveAuditId = null;
1025
978
  if (newStatus === 'approved' && params.forceApprove) {
@@ -1042,7 +995,7 @@ export async function handleUpdateStatus(params, server) {
1042
995
  outputType: 'success',
1043
996
  durationMs: 0,
1044
997
  specId,
1045
- projectPath: effectiveGatePath ?? undefined,
998
+ projectPath: effectiveGatePath,
1046
999
  prevHash,
1047
1000
  hash: '',
1048
1001
  event: 'approve_gate_forced_bypass',
@@ -1059,8 +1012,9 @@ export async function handleUpdateStatus(params, server) {
1059
1012
  appendEntry(entry);
1060
1013
  forceApproveAuditId = auditId;
1061
1014
  }
1062
- catch {
1063
- /* best-effortaudit must never block transition */
1015
+ catch (error) {
1016
+ /* reliability-optional: FORCE_APPROVAL_AUDIT transition receipt remains authoritative */
1017
+ reportClassifiedDegradation('FORCE_APPROVAL_AUDIT', error);
1064
1018
  }
1065
1019
  }
1066
1020
  }
@@ -1078,7 +1032,7 @@ export async function handleUpdateStatus(params, server) {
1078
1032
  outputType: 'success',
1079
1033
  durationMs: 0,
1080
1034
  specId,
1081
- projectPath: effectiveGatePath ?? undefined,
1035
+ projectPath: effectiveGatePath,
1082
1036
  prevHash,
1083
1037
  hash: '',
1084
1038
  event: 'sdd_model_routing_forced_bypass',
@@ -1093,8 +1047,9 @@ export async function handleUpdateStatus(params, server) {
1093
1047
  appendEntry(entry);
1094
1048
  sddRoutingAuditId = auditId;
1095
1049
  }
1096
- catch {
1097
- /* best-effortaudit must never block transition */
1050
+ catch (error) {
1051
+ /* reliability-optional: SDD_ROUTING_AUDIT transition receipt remains authoritative */
1052
+ reportClassifiedDegradation('SDD_ROUTING_AUDIT', error);
1098
1053
  }
1099
1054
  }
1100
1055
  // SPEC-969: Track forceStatus / forceApprove usage
@@ -1115,8 +1070,9 @@ export async function handleUpdateStatus(params, server) {
1115
1070
  `Consider re-running validate within 24h.`;
1116
1071
  }
1117
1072
  }
1118
- catch {
1119
- /* best-effortanalytics must never block transition */
1073
+ catch (error) {
1074
+ /* reliability-optional: BYPASS_ANALYTICS lifecycle gates remain authoritative */
1075
+ reportClassifiedDegradation('BYPASS_ANALYTICS', error);
1120
1076
  }
1121
1077
  }
1122
1078
  const versionSnapshotTag = newStatus === 'approved'
@@ -1133,45 +1089,32 @@ export async function handleUpdateStatus(params, server) {
1133
1089
  hasProjectPath: Boolean(effectiveGatePath),
1134
1090
  shouldAutoStage,
1135
1091
  });
1136
- // Commit status and non-status fields in one store mutation, then pair it
1137
- // with an atomic spec.md write while the per-spec lock is still held.
1138
- const transitionRecord = await transitionSpec(projectId, specId, newStatus, {
1139
- trigger: trigger,
1140
- actor,
1141
- viaSync,
1142
- reason: params.reason,
1143
- updates: nonStatusUpdates,
1144
- pendingBackgroundActions: plannedBackgroundActions,
1092
+ const persistence = await commitTransitionWithNarrowLock({
1093
+ projectPath: effectiveProjectPath || projectId,
1094
+ projectId,
1095
+ specId,
1096
+ newStatus,
1097
+ originalStatus,
1145
1098
  expectedSpec: spec,
1099
+ options: {
1100
+ trigger: trigger,
1101
+ actor,
1102
+ viaSync,
1103
+ reason: params.reason,
1104
+ updates: nonStatusUpdates,
1105
+ pendingBackgroundActions: plannedBackgroundActions,
1106
+ expectedSpec: spec,
1107
+ },
1108
+ ...(doneFreshnessLease ? { freshnessLease: doneFreshnessLease } : {}),
1146
1109
  });
1147
- const updatedSpec = transitionRecord.spec;
1148
- const syncResult = await syncSpecFiles(updatedSpec, originalStatus, newStatus, effectiveGatePath);
1149
- if (syncResult.warning) {
1150
- try {
1151
- await rollbackTransitionSpec(transitionRecord);
1152
- return buildPersistenceFailureResponse({
1153
- specId,
1154
- previousStatus: originalStatus,
1155
- newStatus,
1156
- reason: syncResult.warning.reason,
1157
- recoveryRequired: false,
1158
- });
1159
- }
1160
- catch (rollbackError) {
1161
- return buildPersistenceFailureResponse({
1162
- specId,
1163
- previousStatus: originalStatus,
1164
- newStatus,
1165
- reason: `${syncResult.warning.reason}; compensation failed: ` +
1166
- (rollbackError instanceof Error ? rollbackError.message : String(rollbackError)),
1167
- recoveryRequired: true,
1168
- });
1169
- }
1110
+ if (!persistence.ok) {
1111
+ return persistence.error;
1170
1112
  }
1113
+ const { transitionRecord, updatedSpec } = persistence;
1171
1114
  const frontmatterSyncWarnings = [];
1172
1115
  const transitionId = transitionRecord.transitionId;
1173
1116
  const committedAt = transitionRecord.timestamp;
1174
- void appendTransitionEvent({
1117
+ await appendTransitionEvent({
1175
1118
  projectId,
1176
1119
  specId,
1177
1120
  eventType: 'transition',
@@ -1183,11 +1126,12 @@ export async function handleUpdateStatus(params, server) {
1183
1126
  modelId: params.modelId,
1184
1127
  gateResults: sddRoutingGate.gateResults,
1185
1128
  meta: { ...transitionEvidenceMeta, transitionId, committedAt },
1186
- }).catch(() => {
1187
- /* best-effort — never block the committed acknowledgement */
1129
+ }).catch((error) => {
1130
+ /* reliability-optional: SDD_ROUTING_REPORT — never block committed acknowledgement */
1131
+ reportClassifiedDegradation('SDD_ROUTING_REPORT', error);
1188
1132
  });
1189
1133
  if (reverseTransition && params.reason) {
1190
- void appendTransitionEvent({
1134
+ await appendTransitionEvent({
1191
1135
  projectId,
1192
1136
  specId,
1193
1137
  eventType: 'reopen',
@@ -1197,18 +1141,8 @@ export async function handleUpdateStatus(params, server) {
1197
1141
  reason: params.reason,
1198
1142
  meta: { transitionId, committedAt },
1199
1143
  }).catch((err) => {
1200
- console.warn('[planu:transition] reopen_event_append_failed', {
1201
- specId,
1202
- error: err instanceof Error ? err.message : String(err),
1203
- });
1204
- });
1205
- }
1206
- // SPEC-1044: Keep the reconstructible context packet fresh on every phase change.
1207
- if (effectiveGatePath) {
1208
- void import('../../engine/session-context-generator.js')
1209
- .then(({ generateSessionContext }) => generateSessionContext(effectiveGatePath, projectId))
1210
- .catch(() => {
1211
- /* best-effort — context gate blocks later phases if this cannot be reconstructed */
1144
+ /* reliability-optional: REOPEN_EVENT_APPEND — transition receipt remains authoritative */
1145
+ reportClassifiedDegradation('REOPEN_EVENT_APPEND', err);
1212
1146
  });
1213
1147
  }
1214
1148
  // SPEC-769/SPEC-780: Write qualityWarnings to spec.md frontmatter when force-approved (best-effort)
@@ -1228,8 +1162,9 @@ export async function handleUpdateStatus(params, server) {
1228
1162
  const updated = updateFrontmatterField(content, 'qualityWarnings', warningsJson);
1229
1163
  await atomicWriteFile(specPathForWarnings, updated);
1230
1164
  }
1231
- catch {
1232
- // best-effortnever blocks the transition
1165
+ catch (error) {
1166
+ // reliability-optional: QUALITY_WARNING_FRONTMATTER canonical receipt retains warnings
1167
+ reportClassifiedDegradation('QUALITY_WARNING_FRONTMATTER', error);
1233
1168
  }
1234
1169
  })();
1235
1170
  }
@@ -1240,10 +1175,7 @@ export async function handleUpdateStatus(params, server) {
1240
1175
  const terminalGateResults = {};
1241
1176
  if (newStatus === 'done') {
1242
1177
  Object.assign(terminalGateResults, sddRoutingGate.gateResults);
1243
- if (validateGateResult !== null) {
1244
- // At this point blocked === false (we returned earlier if blocked was true)
1245
- terminalGateResults.validate = validateGateResult.forced ? 'forced' : 'pass';
1246
- }
1178
+ terminalGateResults.validate = 'pass';
1247
1179
  if (complianceGateResult !== null) {
1248
1180
  terminalGateResults.compliance = complianceGateResult.skipped
1249
1181
  ? 'skip'
@@ -1251,15 +1183,8 @@ export async function handleUpdateStatus(params, server) {
1251
1183
  ? 'fail'
1252
1184
  : 'pass';
1253
1185
  }
1254
- if (crashRisksReport !== null) {
1255
- terminalGateResults['crash-shield'] =
1256
- crashRisksReport.score >= 80 ? 'pass' : 'fail';
1257
- }
1258
- else if (crashShieldSkipReason) {
1259
- terminalGateResults['crash-shield'] = 'skip';
1260
- }
1261
1186
  }
1262
- void recordTerminalTransitionEvent({
1187
+ await recordTerminalTransitionEvent({
1263
1188
  projectId,
1264
1189
  specId,
1265
1190
  specPath: updatedSpec.specPath,
@@ -1272,8 +1197,9 @@ export async function handleUpdateStatus(params, server) {
1272
1197
  modelId: params.modelId,
1273
1198
  gateResults: Object.keys(terminalGateResults).length > 0 ? terminalGateResults : undefined,
1274
1199
  meta: transitionEvidenceMeta,
1275
- }).catch(() => {
1276
- /* best-effortnever block the transition */
1200
+ }).catch((error) => {
1201
+ /* reliability-optional: TERMINAL_VALIDATION_REPORT canonical receipt is authoritative */
1202
+ reportClassifiedDegradation('TERMINAL_VALIDATION_REPORT', error);
1277
1203
  });
1278
1204
  }
1279
1205
  const allSpecs = await specStore.listSpecs(projectId);
@@ -1301,15 +1227,6 @@ export async function handleUpdateStatus(params, server) {
1301
1227
  // SPEC-469: Collect autopilot summary for done-transition side effects
1302
1228
  const collector = new AutopilotSummaryCollector();
1303
1229
  if (newStatus === 'done') {
1304
- if (validateScore !== null) {
1305
- collector.pushOk('validate', `Validate score: ${String(validateScore)}/100`);
1306
- }
1307
- if (crashShieldWarning) {
1308
- collector.pushFail('crash-shield', crashShieldWarning);
1309
- }
1310
- else if (crashShieldSkipReason) {
1311
- collector.pushOk('crash-shield', `scan_crash_risks: skipped (${crashShieldSkipReason})`);
1312
- }
1313
1230
  if (doneActions?.mergeWarning) {
1314
1231
  collector.pushFail('merge-check', doneActions.mergeWarning);
1315
1232
  }
@@ -1392,26 +1309,12 @@ export async function handleUpdateStatus(params, server) {
1392
1309
  ...(collector.hasEntries() ? { autopilotSummary: collector.getMessages() } : {}),
1393
1310
  });
1394
1311
  // SPEC-772 Scenario 4: surface validate failure from cascade as explicit warning
1395
- const autopilotValidateWarning = validateScore !== null && validateScore < 100
1396
- ? `Validate score ${String(validateScore)}/100 — below threshold. Check workspace_alerts for cascade details.`
1397
- : null;
1398
- if (autopilotValidateWarning) {
1399
- result.autopilotValidateWarning = autopilotValidateWarning;
1400
- }
1401
1312
  // SPEC-754: Append shell-hygiene reminder when transitioning to done on claude-code host
1402
1313
  const shellHygieneHint = newStatus === 'done' && detectHost() === 'claude-code' ? shellHygieneReminder() : null;
1403
1314
  return buildStatusResponse(result, specId, originalStatus, newStatus, null, spec.title, shellHygieneHint);
1404
1315
  }
1405
1316
  finally {
1406
- // SPEC-719: Release cross-process lock in all exit paths (return, throw)
1407
- if (crossProcessLockHandle !== null) {
1408
- await releaseLock(crossProcessLockHandle).catch((err) => {
1409
- console.warn('[planu:lock] update_status release error', {
1410
- specId,
1411
- error: err instanceof Error ? err.message : String(err),
1412
- });
1413
- });
1414
- }
1317
+ // Expensive gates intentionally execute without a mutation lock.
1415
1318
  }
1416
1319
  }
1417
1320
  catch (error) {
@@ -1432,7 +1335,7 @@ export async function handleUpdateStatus(params, server) {
1432
1335
  isError: true,
1433
1336
  };
1434
1337
  }
1435
- });
1338
+ })();
1436
1339
  }); // end trackCost
1437
1340
  }
1438
1341
  //# sourceMappingURL=index.js.map