@planu/cli 5.3.67 → 5.3.69

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 (389) hide show
  1. package/CHANGELOG.md +92 -0
  2. package/dist/.planu-build.json +1 -1
  3. package/dist/cli/commands/install.d.ts +2 -15
  4. package/dist/config/release-policy.json +2 -2
  5. package/dist/core/shared/fs.d.ts +11 -0
  6. package/dist/core/shared/fs.js +90 -0
  7. package/dist/core/shared/strings.d.ts +3 -0
  8. package/dist/core/shared/strings.js +13 -0
  9. package/dist/engine/actuals/git-analyzer.js +1 -1
  10. package/dist/engine/actuals/progress-parser.js +1 -3
  11. package/dist/engine/agent-handoff-store.js +1 -0
  12. package/dist/engine/agent-squad/dispatcher.js +1 -0
  13. package/dist/engine/agent-telemetry.js +1 -0
  14. package/dist/engine/auth/config.js +1 -0
  15. package/dist/engine/auto-updater/atomic-upgrade.js +1 -0
  16. package/dist/engine/auto-updater/index.js +1 -0
  17. package/dist/engine/autopilot/action-registry.js +20 -0
  18. package/dist/engine/autopilot/audit-logger.js +1 -0
  19. package/dist/engine/autopilot/bootstrap.js +9 -2
  20. package/dist/engine/autopilot/complete-loop.js +4 -0
  21. package/dist/engine/autopilot/crash-shield-rate-limiter.js +1 -0
  22. package/dist/engine/autopilot/event-bus.js +1 -0
  23. package/dist/engine/autopilot/state-updater.js +6 -0
  24. package/dist/engine/browser-validator.js +1 -3
  25. package/dist/engine/build-tool-detector.js +1 -8
  26. package/dist/engine/bundle-installer.js +2 -10
  27. package/dist/engine/cascade-hooks/core/append-releases.js +1 -0
  28. package/dist/engine/cascade-hooks/core/write-session-json.js +2 -2
  29. package/dist/engine/cascade-hooks/hooks/dispatch-hook-event.hook.d.ts +3 -1
  30. package/dist/engine/cascade-hooks/hooks/dispatch-hook-event.hook.js +12 -3
  31. package/dist/engine/cascade-hooks/hooks/estimate-calibration.hook.js +1 -0
  32. package/dist/engine/cascade-hooks/hooks/housekeeping-on-done.hook.js +2 -0
  33. package/dist/engine/cascade-hooks/hooks/implementing-kickoff.hook.js +5 -1
  34. package/dist/engine/cascade-hooks/hooks/lesson-drift.hook.js +1 -0
  35. package/dist/engine/cascade-hooks/hooks/orchestration-plan.hook.js +1 -0
  36. package/dist/engine/cascade-hooks/hooks/session-context.hook.js +4 -2
  37. package/dist/engine/cascade-hooks/hooks/slack-notify.hook.js +1 -0
  38. package/dist/engine/cascade-hooks/hooks/status-json.hook.js +2 -0
  39. package/dist/engine/cascade-hooks/hooks/velocity-profile.hook.js +2 -0
  40. package/dist/engine/cascade-hooks/runner.js +2 -0
  41. package/dist/engine/cascade-hooks/state-drift-detector.js +2 -0
  42. package/dist/engine/checkpoint/checkpoint-manager.js +2 -0
  43. package/dist/engine/checkpoint/policy-engine.js +1 -0
  44. package/dist/engine/ci-generator/stack-detector.js +2 -10
  45. package/dist/engine/clarification-gate/token-store.js +1 -0
  46. package/dist/engine/claude-config-auditor/claudemd-auditor.js +2 -10
  47. package/dist/engine/claude-config-auditor/settings-auditor.js +2 -10
  48. package/dist/engine/client-detection.js +2 -10
  49. package/dist/engine/compliance/auto-remediator.js +1 -0
  50. package/dist/engine/compliance/evidence-builder.d.ts +2 -2
  51. package/dist/engine/compliance/framework-catalog.d.ts +6 -6
  52. package/dist/engine/compliance/gap-analyzer.d.ts +2 -2
  53. package/dist/engine/config-health/build-tool-checker.js +1 -9
  54. package/dist/engine/config-health/ci-commands-collector.d.ts +2 -1
  55. package/dist/engine/config-health/ci-commands-collector.js +2 -9
  56. package/dist/engine/config-health/go-checker.js +1 -9
  57. package/dist/engine/config-health/mcp-config-checker.js +2 -10
  58. package/dist/engine/config-health/python-checker.js +1 -9
  59. package/dist/engine/config-health/rust-checker.js +1 -9
  60. package/dist/engine/config-health/ts-checker-scripts.js +1 -9
  61. package/dist/engine/config-health/ts-checker.js +1 -9
  62. package/dist/engine/context-artifacts/store.js +1 -0
  63. package/dist/engine/context-md-generator.js +1 -0
  64. package/dist/engine/context-orchestrator/index.js +2 -0
  65. package/dist/engine/convention-scanner/convention-parser.js +2 -9
  66. package/dist/engine/cost-guardrails.js +1 -0
  67. package/dist/engine/cost-tracking/ledger.js +1 -0
  68. package/dist/engine/criterion-identity.js +1 -1
  69. package/dist/engine/dashboard/data-loader.js +1 -0
  70. package/dist/engine/dashboard/drift-score.js +2 -0
  71. package/dist/engine/dashboard/spec-updater.d.ts +3 -1
  72. package/dist/engine/dashboard/spec-updater.js +9 -2
  73. package/dist/engine/dashboard/templates-layout.d.ts +2 -2
  74. package/dist/engine/dashboard/templates-layout.js +2 -9
  75. package/dist/engine/data-projects-gc/gc-runner.js +2 -4
  76. package/dist/engine/deleter/audit-logger.js +1 -0
  77. package/dist/engine/deleter/core.js +6 -0
  78. package/dist/engine/deleter/trash-manager.js +1 -0
  79. package/dist/engine/desktop-detector.js +1 -9
  80. package/dist/engine/detection-utils.d.ts +2 -1
  81. package/dist/engine/detection-utils.js +3 -10
  82. package/dist/engine/detectors/advanced-framework-detector/helpers.d.ts +3 -2
  83. package/dist/engine/detectors/advanced-framework-detector/helpers.js +3 -17
  84. package/dist/engine/detectors/cicd-detector.js +2 -10
  85. package/dist/engine/detectors/css-framework-detector.js +2 -10
  86. package/dist/engine/detectors/deployment-detector.js +3 -12
  87. package/dist/engine/detectors/frontend-perf-detector.js +2 -10
  88. package/dist/engine/detectors/gitops-detector.js +3 -11
  89. package/dist/engine/detectors/idp-detector.js +1 -3
  90. package/dist/engine/detectors/k3s-detector.js +3 -11
  91. package/dist/engine/detectors/llm-detector/file-readers.d.ts +2 -1
  92. package/dist/engine/detectors/llm-detector/file-readers.js +2 -9
  93. package/dist/engine/detectors/mfe-detector.js +5 -13
  94. package/dist/engine/detectors/monitoring-detector.js +2 -11
  95. package/dist/engine/detectors/monorepo-detector.d.ts +1 -0
  96. package/dist/engine/detectors/monorepo-detector.js +1 -10
  97. package/dist/engine/detectors/nomad-detector.js +3 -11
  98. package/dist/engine/detectors/otel-ecosystem-detectors.d.ts +2 -1
  99. package/dist/engine/detectors/otel-ecosystem-detectors.js +2 -10
  100. package/dist/engine/doc-generator/executive-summary/html-template.js +1 -7
  101. package/dist/engine/doc-generator/executive-summary/section-builders.js +1 -7
  102. package/dist/engine/doc-generator/per-spec-report/mermaid-renderer.js +1 -7
  103. package/dist/engine/doc-generator/per-spec-report/spec-section-builders.js +1 -7
  104. package/dist/engine/doc-generator/per-spec-report/technical-report.js +1 -7
  105. package/dist/engine/doc-generator/portal/analytics-page.js +1 -7
  106. package/dist/engine/doc-generator/portal/architecture-page.js +1 -7
  107. package/dist/engine/doc-generator/portal/changelog-page.js +1 -7
  108. package/dist/engine/doc-generator/portal/decision-page.js +1 -7
  109. package/dist/engine/doc-generator/portal/decision-timeline-builder.js +1 -7
  110. package/dist/engine/doc-generator/portal/kanban-view-builder.js +1 -7
  111. package/dist/engine/doc-generator/portal/portal-breadcrumbs.js +1 -7
  112. package/dist/engine/doc-generator/portal/portal-landing-cards.js +1 -7
  113. package/dist/engine/doc-generator/portal/portal-navbar.js +1 -7
  114. package/dist/engine/doc-generator/portal/portal-page-detector.d.ts +3 -0
  115. package/dist/engine/doc-generator/portal/portal-page-detector.js +1 -10
  116. package/dist/engine/doc-generator/portal/portal-regenerator.js +2 -0
  117. package/dist/engine/doc-generator/portal/risk-matrix-svg.js +1 -7
  118. package/dist/engine/doc-generator/portal/risk-page.js +1 -7
  119. package/dist/engine/doc-generator/portal/roadmap-page.js +1 -7
  120. package/dist/engine/doc-generator/proposal/proposal-gantt-builder.js +1 -7
  121. package/dist/engine/doc-generator/proposal/proposal-kpi-builder.js +1 -7
  122. package/dist/engine/doc-generator/proposal/proposal-section-builders-advanced.js +2 -8
  123. package/dist/engine/doc-generator/proposal/proposal-section-builders.js +1 -7
  124. package/dist/engine/docs-site-generator/html-templates.js +1 -7
  125. package/dist/engine/docs-site-generator/markdown-renderer.js +1 -7
  126. package/dist/engine/drift/violation-resolver.js +2 -0
  127. package/dist/engine/dynamic-knowledge/knowledge-cache.js +1 -0
  128. package/dist/engine/ecosystem-absorber/knowledge-cache.js +1 -0
  129. package/dist/engine/edge-db-detector.js +1 -10
  130. package/dist/engine/escalator/retry-counter.js +1 -0
  131. package/dist/engine/evidence-gates/artifact-reader.js +1 -0
  132. package/dist/engine/evidence-gates/evidence-autofill.js +1 -0
  133. package/dist/engine/evidence-gates/evidence-skeletons.js +1 -0
  134. package/dist/engine/evidence-gates/reconciliation-freshness.js +1 -0
  135. package/dist/engine/execution/durable-job-heartbeat-runtime.js +1 -0
  136. package/dist/engine/execution/job-runtime.js +2 -0
  137. package/dist/engine/execution/validate-job-executor.d.ts +1 -1
  138. package/dist/engine/execution/validate-job-executor.js +3 -0
  139. package/dist/engine/execution/validate-job-payload.js +1 -0
  140. package/dist/engine/execution/validate-worker-thread.js +1 -0
  141. package/dist/engine/facilitate/context-loader.js +1 -0
  142. package/dist/engine/figma/change-detector.d.ts +1 -8
  143. package/dist/engine/figma/code-connect-fetcher.d.ts +1 -7
  144. package/dist/engine/figma/design-enricher.d.ts +1 -17
  145. package/dist/engine/figma/design-enricher.js +0 -1
  146. package/dist/engine/figma/e2e-generator.d.ts +1 -23
  147. package/dist/engine/figma/flow-analyzer.d.ts +1 -11
  148. package/dist/engine/figma/frame-extractor.d.ts +1 -11
  149. package/dist/engine/figma/frame-extractor.js +3 -0
  150. package/dist/engine/figma/multi-file-manager.d.ts +1 -6
  151. package/dist/engine/figma/spec-generator.js +2 -0
  152. package/dist/engine/figma/thumbnail-fetcher.d.ts +1 -1
  153. package/dist/engine/figma/token-extractor.d.ts +1 -6
  154. package/dist/engine/figma/token-extractor.js +0 -1
  155. package/dist/engine/figma/version-tracker.d.ts +1 -7
  156. package/dist/engine/figma/version-tracker.js +0 -1
  157. package/dist/engine/figma/visual-qa.d.ts +5 -19
  158. package/dist/engine/figma/visual-qa.js +1 -2
  159. package/dist/engine/figma/webhook-manager.d.ts +1 -7
  160. package/dist/engine/frontmatter-sha/reseal.js +1 -0
  161. package/dist/engine/frontmatter-sha/verify-terminal.js +1 -0
  162. package/dist/engine/git-hook-injector.js +2 -10
  163. package/dist/engine/github/quality-dimensions.js +1 -3
  164. package/dist/engine/global-rules-manager.js +2 -3
  165. package/dist/engine/handoff-artifacts/implementation-review-reader.js +1 -0
  166. package/dist/engine/handoff-artifacts/io.js +2 -0
  167. package/dist/engine/handoff-packager.js +2 -1
  168. package/dist/engine/health/auto-fixer.js +1 -0
  169. package/dist/engine/hooks/context-injector.js +1 -0
  170. package/dist/engine/hooks-reconciler.js +1 -8
  171. package/dist/engine/impact-detector/index.js +2 -9
  172. package/dist/engine/implementation-contract/common.js +1 -3
  173. package/dist/engine/implementation-contract/evaluator.js +1 -3
  174. package/dist/engine/keyword-matcher/boundary.d.ts +2 -7
  175. package/dist/engine/keyword-matcher/boundary.js +2 -14
  176. package/dist/engine/lifecycle-reconciliation-io.js +1 -0
  177. package/dist/engine/lifecycle-reconciliation.js +3 -0
  178. package/dist/engine/local-first/detector.js +1 -9
  179. package/dist/engine/marketplace-fetcher/cache.js +2 -0
  180. package/dist/engine/marketplace-fetcher/index.js +1 -0
  181. package/dist/engine/mcp-config/mcp-config-writer.js +2 -10
  182. package/dist/engine/migrations/remove-commercial-state.js +2 -0
  183. package/dist/engine/mobile-detector-shared.d.ts +1 -1
  184. package/dist/engine/mobile-detector-shared.js +2 -9
  185. package/dist/engine/multi-channel-notifier.js +1 -0
  186. package/dist/engine/multi-teammate-review/disagreement-counter.js +1 -0
  187. package/dist/engine/multi-teammate-review/panel-orchestrator.js +1 -0
  188. package/dist/engine/onboarding-engine.js +1 -9
  189. package/dist/engine/permissions-merger/stack-detectors.js +2 -10
  190. package/dist/engine/pii-detector/core.js +1 -3
  191. package/dist/engine/platform-engineering/dx-analyzer.js +1 -10
  192. package/dist/engine/platform-engineering/idp-detector.js +2 -10
  193. package/dist/engine/project-dna/ai-tool-detector.js +2 -10
  194. package/dist/engine/project-dna/stack-detector.js +2 -10
  195. package/dist/engine/project-graph/builder.js +11 -2
  196. package/dist/engine/project-graph/cache.d.ts +5 -2
  197. package/dist/engine/project-graph/cache.js +174 -34
  198. package/dist/engine/project-graph/extractors/decision-store-extractor.js +1 -0
  199. package/dist/engine/project-graph/freshness-projection.js +3 -0
  200. package/dist/engine/project-graph/query.js +14 -11
  201. package/dist/engine/project-health-checker.js +2 -6
  202. package/dist/engine/provider-adapters/shared/spec-loader.js +1 -0
  203. package/dist/engine/quality-gates/gate-evaluator.js +1 -3
  204. package/dist/engine/react-detector.js +6 -14
  205. package/dist/engine/reconcile/apply-changes.js +1 -3
  206. package/dist/engine/registry/core.js +1 -0
  207. package/dist/engine/registry/loader.js +2 -0
  208. package/dist/engine/release/postmortem-generator.js +1 -0
  209. package/dist/engine/release/rollback-runner.d.ts +2 -2
  210. package/dist/engine/release/stuck-spec-detector.js +7 -0
  211. package/dist/engine/release-pipeline/release-spec-closer.js +3 -0
  212. package/dist/engine/rules-reconciler.d.ts +1 -1
  213. package/dist/engine/rules-reconciler.js +2 -9
  214. package/dist/engine/safety/atomic-writer.js +1 -0
  215. package/dist/engine/safety/cross-process-lock.js +2 -0
  216. package/dist/engine/safety/file-mutex.js +1 -0
  217. package/dist/engine/safety/lock-lease-store.js +1 -0
  218. package/dist/engine/safety/lock-scavenger.js +2 -0
  219. package/dist/engine/saga/transition-cascade.js +3 -0
  220. package/dist/engine/scan-project/index.js +1 -0
  221. package/dist/engine/scan-project/module-discoverer.js +1 -9
  222. package/dist/engine/schema-parity-auditor/handler-checker.js +1 -3
  223. package/dist/engine/schema-parity-auditor/index.js +1 -3
  224. package/dist/engine/schema-parity-auditor/type-checker.js +1 -3
  225. package/dist/engine/self-healing/strategies/coverage-fix.js +2 -10
  226. package/dist/engine/session-context-generator.d.ts +8 -0
  227. package/dist/engine/session-context-generator.js +33 -23
  228. package/dist/engine/session-state/session-artifact-refresher.d.ts +7 -0
  229. package/dist/engine/session-state/session-artifact-refresher.js +140 -0
  230. package/dist/engine/session-state/writer.d.ts +3 -0
  231. package/dist/engine/session-state/writer.js +35 -17
  232. package/dist/engine/shared-agent-memory.js +1 -0
  233. package/dist/engine/skill-adapter/index.js +3 -0
  234. package/dist/engine/skill-bootstrap/registry-fetcher.js +1 -0
  235. package/dist/engine/skill-bootstrap/skill-writer.js +2 -9
  236. package/dist/engine/skill-bootstrap/stack-matcher.js +1 -9
  237. package/dist/engine/skill-discovery/multi-agent-writer.d.ts +1 -0
  238. package/dist/engine/skill-discovery/multi-agent-writer.js +1 -9
  239. package/dist/engine/skill-generator/workflow-skill-generator.js +1 -0
  240. package/dist/engine/skill-registry/ttl-refresh.js +2 -0
  241. package/dist/engine/spec-audit/index.js +2 -0
  242. package/dist/engine/spec-audit/report-writer.js +1 -0
  243. package/dist/engine/spec-coverage/core.js +1 -0
  244. package/dist/engine/spec-decomposer/analyzer.js +1 -11
  245. package/dist/engine/spec-dependency-graph/dot-exporter.d.ts +1 -1
  246. package/dist/engine/spec-dependency-graph/graph-builder.d.ts +1 -20
  247. package/dist/engine/spec-dependency-graph/superseded-set.d.ts +1 -1
  248. package/dist/engine/spec-diff-engine.js +1 -7
  249. package/dist/engine/spec-format/read-technical-section.js +1 -3
  250. package/dist/engine/spec-format/replace-section.js +1 -3
  251. package/dist/engine/spec-format/spec-id.d.ts +9 -1
  252. package/dist/engine/spec-format/spec-id.js +24 -3
  253. package/dist/engine/spec-format/unified-spec-builder.js +1 -3
  254. package/dist/engine/spec-migrator/canonical-deduplicator.js +2 -0
  255. package/dist/engine/spec-observability/tracker.js +1 -0
  256. package/dist/engine/spec-registry/adapter.js +2 -10
  257. package/dist/engine/spec-registry/validator.d.ts +1 -0
  258. package/dist/engine/spec-registry/validator.js +1 -9
  259. package/dist/engine/spec-state-machine/transition-spec.js +1 -0
  260. package/dist/engine/spec-templates/custom-loader.js +1 -0
  261. package/dist/engine/stack-auditor/build-tool-auditor.js +1 -9
  262. package/dist/engine/staleness/stale-implementing.js +5 -14
  263. package/dist/engine/status-reconciler/index.js +4 -1
  264. package/dist/engine/structural-memory/helpers.js +1 -0
  265. package/dist/engine/supply-chain/slsa-checker.js +1 -9
  266. package/dist/engine/tdd-enforcer/stub-artifact-path.js +1 -0
  267. package/dist/engine/telemetry/health-checker.js +1 -0
  268. package/dist/engine/telemetry/telemetry-store.js +1 -0
  269. package/dist/engine/token-optimizer/response-cache.js +1 -3
  270. package/dist/engine/tool-groups/group-manager.js +2 -0
  271. package/dist/engine/update-notifier.js +1 -0
  272. package/dist/engine/validation/approved-spec-portability.js +1 -0
  273. package/dist/engine/validation/durable-validation.js +1 -0
  274. package/dist/engine/validation/validation-freshness.js +2 -0
  275. package/dist/engine/validation/validation-receipt.js +1 -0
  276. package/dist/engine/validation/validation-submission.d.ts +1 -1
  277. package/dist/engine/validation-evidence-ledger.js +1 -0
  278. package/dist/engine/validator/deep-code-checker.js +1 -3
  279. package/dist/engine/validator/executable-evidence.d.ts +1 -14
  280. package/dist/engine/validator/scope-resolver.d.ts +2 -2
  281. package/dist/engine/validator/spec-compliance-runner.d.ts +1 -31
  282. package/dist/engine/validator/validation-report-writer.js +1 -1
  283. package/dist/engine/validator.d.ts +1 -1
  284. package/dist/engine/validator.js +1 -0
  285. package/dist/engine/velocity/measure-velocity.js +2 -0
  286. package/dist/engine/version-resolver.js +1 -0
  287. package/dist/engine/workers/handlers/auto-drift.js +3 -0
  288. package/dist/engine/workspace-manager.js +4 -0
  289. package/dist/hosts/gemini/config-scaffold.js +2 -10
  290. package/dist/storage/approval-operation-lock.js +1 -0
  291. package/dist/storage/auto-promoter-config-store.js +1 -0
  292. package/dist/storage/autopilot-log-store.js +1 -0
  293. package/dist/storage/base-store.js +1 -0
  294. package/dist/storage/checkpoint-store.js +1 -0
  295. package/dist/storage/feedback-remote.js +1 -0
  296. package/dist/storage/gaps-log.js +1 -0
  297. package/dist/storage/global-projects-store.d.ts +17 -0
  298. package/dist/storage/global-projects-store.js +47 -0
  299. package/dist/storage/global-store.js +1 -0
  300. package/dist/storage/knowledge-store/sessions.js +2 -0
  301. package/dist/storage/migrations/canonical-storage.js +42 -18
  302. package/dist/storage/project-drift-store.js +1 -0
  303. package/dist/storage/project-identity.d.ts +27 -0
  304. package/dist/storage/project-identity.js +132 -2
  305. package/dist/storage/project-resolver.js +1 -17
  306. package/dist/storage/runtime-db.d.ts +2 -20
  307. package/dist/storage/runtime-db.js +2 -9
  308. package/dist/storage/semantic-index-store.js +1 -0
  309. package/dist/storage/sentry-store.js +1 -0
  310. package/dist/storage/session-state-store.js +1 -0
  311. package/dist/storage/spec-store.d.ts +31 -3
  312. package/dist/storage/spec-store.js +146 -5
  313. package/dist/storage/status-store/atomic-status-write.js +1 -0
  314. package/dist/storage/status-store/file-lock.js +1 -0
  315. package/dist/storage/status-store/self-healing.js +1 -0
  316. package/dist/storage/storage-bundle.d.ts +12 -2
  317. package/dist/storage/supabase-store.js +1 -0
  318. package/dist/storage/technology-selection-store.js +1 -0
  319. package/dist/storage/trash-store.d.ts +2 -4
  320. package/dist/storage/trash-store.js +2 -15
  321. package/dist/storage/vector-store/json-fallback.js +1 -0
  322. package/dist/storage/vector-store/migrator.js +1 -0
  323. package/dist/storage/vector-store/sqlite-adapter.js +1 -0
  324. package/dist/tools/audit-claude-config.js +1 -10
  325. package/dist/tools/challenge-spec-helpers.d.ts +1 -1
  326. package/dist/tools/challenge-spec-helpers.js +7 -2
  327. package/dist/tools/challenge-spec.js +11 -6
  328. package/dist/tools/check-readiness.js +121 -24
  329. package/dist/tools/clarify-requirements/multiple-choice.d.ts +3 -3
  330. package/dist/tools/configure-oauth-handler.js +1 -0
  331. package/dist/tools/create-spec-helpers.d.ts +1 -3
  332. package/dist/tools/create-spec-helpers.js +1 -8
  333. package/dist/tools/create-spec.js +1 -13
  334. package/dist/tools/dashboard.js +5 -0
  335. package/dist/tools/generate-execution-plan.js +10 -6
  336. package/dist/tools/github-pr-handler.js +1 -0
  337. package/dist/tools/github-release-handler.d.ts +1 -0
  338. package/dist/tools/github-release-handler.js +4 -3
  339. package/dist/tools/graph-specs.d.ts +1 -1
  340. package/dist/tools/heal-spec-docs.js +1 -3
  341. package/dist/tools/init-project/git-setup.d.ts +2 -2
  342. package/dist/tools/init-project/host-assets-writer.js +2 -10
  343. package/dist/tools/init-project/lifecycle-helpers.d.ts +2 -2
  344. package/dist/tools/init-project/lint-scaffolder.js +2 -10
  345. package/dist/tools/init-project/stack-detector.d.ts +2 -2
  346. package/dist/tools/reconcile-interactive-question-hooks.d.ts +2 -2
  347. package/dist/tools/register-sdd-tools.js +1 -0
  348. package/dist/tools/safe-handler.js +1 -0
  349. package/dist/tools/schemas/spec-id.d.ts +1 -6
  350. package/dist/tools/schemas/spec-id.js +1 -16
  351. package/dist/tools/tool-entry.d.ts +2 -2
  352. package/dist/tools/tool-entry.js +1 -1
  353. package/dist/tools/tool-registry/core-tools.d.ts +2 -2
  354. package/dist/tools/tool-registry/deprecated-stubs.d.ts +3 -3
  355. package/dist/tools/tool-registry/deprecated-stubs.js +1 -1
  356. package/dist/tools/triage-request.d.ts +2 -2
  357. package/dist/tools/update-status/approval-gates.d.ts +2 -2
  358. package/dist/tools/update-status/approval-gates.js +1 -0
  359. package/dist/tools/update-status/dod-gates.d.ts +1 -1
  360. package/dist/tools/update-status/done-receipt-verifier.d.ts +1 -1
  361. package/dist/tools/update-status/evidence-gate.js +5 -5
  362. package/dist/tools/update-status/file-sync.js +11 -39
  363. package/dist/tools/update-status/index.js +1 -1
  364. package/dist/tools/update-status/side-effects.js +5 -0
  365. package/dist/tools/update-status/transition-guard.d.ts +1 -1
  366. package/dist/tools/update-status/transition-guard.js +40 -8
  367. package/dist/tools/update-status-actions.js +28 -40
  368. package/dist/tools/validate-graph-coverage.js +14 -2
  369. package/dist/tools/validate.js +2 -0
  370. package/dist/transports/middleware/types.d.ts +3 -3
  371. package/dist/types/atomic-upgrade.d.ts +1 -1
  372. package/dist/types/cascade-hooks.d.ts +3 -0
  373. package/dist/types/cross-repo-search.d.ts +2 -0
  374. package/dist/types/dashboard.d.ts +4 -1
  375. package/dist/types/durable-job.d.ts +20 -0
  376. package/dist/types/durable-job.js +9 -1
  377. package/dist/types/index.d.ts +2 -0
  378. package/dist/types/index.js +2 -0
  379. package/dist/types/installation.d.ts +16 -0
  380. package/dist/types/installation.js +2 -0
  381. package/dist/types/project-knowledge-graph.d.ts +11 -0
  382. package/dist/types/session-checkpoint.d.ts +16 -0
  383. package/dist/types/spec-dependency-graph.d.ts +21 -0
  384. package/dist/types/spec-dependency-graph.js +2 -0
  385. package/dist/types/validation-evidence.d.ts +45 -0
  386. package/package.json +2 -2
  387. package/planu-plugin.json +1 -1
  388. package/dist/types/storage-bundle.d.ts +0 -13
  389. package/dist/types/storage-bundle.js +0 -2
@@ -1,3 +1,4 @@
1
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
1
2
  import { technologyValue } from '../engine/technology-registry.js';
2
3
  // storage/sentry-store.ts — Sentry integration persistence (SPEC-435)
3
4
  import { mkdir, readFile, writeFile } from 'node:fs/promises';
@@ -4,6 +4,7 @@ import { readJson, writeJson } from './base-store.js';
4
4
  import { join } from 'node:path';
5
5
  import { execSync } from 'node:child_process';
6
6
  import { readFile } from 'node:fs/promises';
7
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
7
8
  import { getUniqueTopLevelFrontmatterString } from '../engine/frontmatter-parser.js';
8
9
  import { reportClassifiedDegradation } from '../errors/classified-degradation.js';
9
10
  // ---------------------------------------------------------------------------
@@ -20,6 +20,13 @@ export declare function validateCanonicalSpecRows(projectId: string, specs: read
20
20
  export declare function withCanonicalSpecRepairLock<T>(projectId: string, fn: () => Promise<T>): Promise<T>;
21
21
  /** Evict the cache for a project (e.g. after external file changes). */
22
22
  export declare function invalidateSpecsCache(projectId: string): void;
23
+ /**
24
+ * Discover the canonical `planu/specs/<specId[-slug]>/spec.md` for a spec by ID,
25
+ * independent of any stale or missing registry record. Fails closed (returns
26
+ * `null`) on zero or ambiguous matches, matching the fail-closed contract of
27
+ * {@link resolveVerifiedSpecPath}.
28
+ */
29
+ export declare function discoverCanonicalSpecPath(specId: string, canonicalRoot: string): Promise<string | null>;
23
30
  /**
24
31
  * List every spec for a project.
25
32
  */
@@ -31,10 +38,31 @@ export declare function listSpecs(projectId: string): Promise<Spec[]>;
31
38
  export declare function withFreshSpecsLock<T>(projectId: string, fn: (specs: Spec[]) => Promise<T>): Promise<T>;
32
39
  /**
33
40
  * Get a single spec by ID. Returns `null` when not found.
34
- */
35
- export declare function getSpec(projectId: string, specId: string): Promise<Spec | null>;
41
+ *
42
+ * When `canonicalRoot` is supplied, a legacy absolute `specPath`/`technicalPath`
43
+ * for this spec is migrated to its portable project-relative identity first
44
+ * (best-effort — a failed migration attempt never blocks the read).
45
+ */
46
+ export declare function getSpec(projectId: string, specId: string, canonicalRoot?: string): Promise<Spec | null>;
47
+ /** Result of a {@link migrateLegacySpecPaths} run. */
48
+ export interface SpecPathMigrationResult {
49
+ readonly migrated: number;
50
+ readonly specIds: readonly string[];
51
+ }
52
+ /**
53
+ * Atomically migrate every eligible legacy absolute `specPath`/`technicalPath`
54
+ * in this project to its portable project-relative identity.
55
+ *
56
+ * Runs under the existing cross-process spec-store lock. A record migrates only
57
+ * when its normalized relative suffix identifies the same spec and the file
58
+ * exists under the verified `canonicalRoot` — never by guessing. Migration
59
+ * changes only the stored path identity; it never touches spec content.
60
+ * Idempotent: a spec already holding a portable path is a no-op. Emits at
61
+ * most one audit event per call, regardless of how many specs migrated.
62
+ */
63
+ export declare function migrateLegacySpecPaths(projectId: string, canonicalRoot: string, specIds?: readonly string[]): Promise<SpecPathMigrationResult>;
36
64
  /** Reload a spec from disk after the caller acquires its cross-process lock. */
37
- export declare function getSpecFresh(projectId: string, specId: string): Promise<Spec | null>;
65
+ export declare function getSpecFresh(projectId: string, specId: string, canonicalRoot?: string): Promise<Spec | null>;
38
66
  /** SPEC-601: Lookup a spec by its globally unique UUID. */
39
67
  export declare function getSpecByUuid(projectId: string, uuid: string): Promise<Spec | null>;
40
68
  /**
@@ -3,10 +3,19 @@ import { CriticalJsonReadError, readCriticalJson, readJson, writeJson, projectDa
3
3
  import { decodeCriticalSchema, registerCriticalSchema } from './schema-registry.js';
4
4
  import { BoundaryFailure } from '../errors/error-taxonomy.js';
5
5
  import { withFileLock } from './file-mutex.js';
6
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
6
7
  import { computeHealthScore } from '../engine/spec-health-scorer.js';
8
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
7
9
  import { loadSpecContent } from '../engine/validation-loop.js';
8
10
  import { createHash, randomUUID } from 'node:crypto';
11
+ import { basename, dirname, isAbsolute, join } from 'node:path';
12
+ import { glob } from 'glob';
13
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
9
14
  import { acquireLock, releaseLock } from '../engine/safety/cross-process-lock.js';
15
+ import { resolvePortableSpecPath, toPortableSpecPath, PortablePathError, } from './project-identity.js';
16
+ import { appendEntry, getLastHash } from './audit-trail-store.js';
17
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
18
+ import { hashEntry } from '../engine/audit-trail/hasher.js';
10
19
  // ---------------------------------------------------------------------------
11
20
  // SPEC-720: Guard error — direct status write forbidden
12
21
  // ---------------------------------------------------------------------------
@@ -197,6 +206,21 @@ async function saveAll(projectId, specs) {
197
206
  export function invalidateSpecsCache(projectId) {
198
207
  specsCache.delete(projectId);
199
208
  }
209
+ /**
210
+ * Discover the canonical `planu/specs/<specId[-slug]>/spec.md` for a spec by ID,
211
+ * independent of any stale or missing registry record. Fails closed (returns
212
+ * `null`) on zero or ambiguous matches, matching the fail-closed contract of
213
+ * {@link resolveVerifiedSpecPath}.
214
+ */
215
+ export async function discoverCanonicalSpecPath(specId, canonicalRoot) {
216
+ const pattern = join(canonicalRoot, 'planu', 'specs', '*', 'spec.md');
217
+ const matches = await glob(pattern, { absolute: true });
218
+ const candidates = matches.filter((path) => {
219
+ const dir = basename(dirname(path));
220
+ return dir === specId || dir.startsWith(`${specId}-`);
221
+ });
222
+ return candidates.length === 1 ? (candidates[0] ?? null) : null;
223
+ }
200
224
  // --- public API ---
201
225
  /**
202
226
  * List every spec for a project.
@@ -213,21 +237,136 @@ export async function withFreshSpecsLock(projectId, fn) {
213
237
  }
214
238
  /**
215
239
  * Get a single spec by ID. Returns `null` when not found.
240
+ *
241
+ * When `canonicalRoot` is supplied, a legacy absolute `specPath`/`technicalPath`
242
+ * for this spec is migrated to its portable project-relative identity first
243
+ * (best-effort — a failed migration attempt never blocks the read).
216
244
  */
217
- export async function getSpec(projectId, specId) {
245
+ export async function getSpec(projectId, specId, canonicalRoot) {
246
+ if (canonicalRoot !== undefined) {
247
+ await migrateLegacySpecPaths(projectId, canonicalRoot, [specId]).catch((error) => {
248
+ reportClassifiedDegradation('SPEC_PATH_MIGRATION_DEFERRED', error);
249
+ });
250
+ }
218
251
  const specs = await loadAll(projectId);
219
252
  return specs.find((s) => s.id === specId) ?? null;
220
253
  }
254
+ /**
255
+ * Record one hash-chained audit event for a legacy specPath migration batch.
256
+ * Best-effort: an audit failure never rolls back an already-persisted migration.
257
+ */
258
+ function recordSpecPathMigrationAudit(projectId, specIds) {
259
+ try {
260
+ const partial = {
261
+ id: randomUUID(),
262
+ timestamp: new Date().toISOString(),
263
+ toolName: 'spec-store.migrateLegacySpecPaths',
264
+ inputSummary: `projectId=${projectId} specIds=${specIds.join(',')}`.slice(0, 200),
265
+ outputType: 'success',
266
+ durationMs: 0,
267
+ prevHash: getLastHash(),
268
+ };
269
+ appendEntry({ ...partial, hash: hashEntry(partial) });
270
+ }
271
+ catch (error) {
272
+ reportClassifiedDegradation('SPEC_PATH_MIGRATION_AUDIT', error);
273
+ }
274
+ }
275
+ /**
276
+ * Atomically migrate every eligible legacy absolute `specPath`/`technicalPath`
277
+ * in this project to its portable project-relative identity.
278
+ *
279
+ * Runs under the existing cross-process spec-store lock. A record migrates only
280
+ * when its normalized relative suffix identifies the same spec and the file
281
+ * exists under the verified `canonicalRoot` — never by guessing. Migration
282
+ * changes only the stored path identity; it never touches spec content.
283
+ * Idempotent: a spec already holding a portable path is a no-op. Emits at
284
+ * most one audit event per call, regardless of how many specs migrated.
285
+ */
286
+ export async function migrateLegacySpecPaths(projectId, canonicalRoot, specIds) {
287
+ return withSpecMutationLock(projectId, async () => {
288
+ const specs = await loadAll(projectId);
289
+ const scope = specIds ? new Set(specIds) : null;
290
+ const migratedIds = [];
291
+ const next = await Promise.all(specs.map(async (spec) => {
292
+ if (scope && !scope.has(spec.id)) {
293
+ return spec;
294
+ }
295
+ if (typeof spec.specPath !== 'string' || !isAbsolute(spec.specPath)) {
296
+ return spec;
297
+ }
298
+ try {
299
+ await resolvePortableSpecPath(spec.id, spec.specPath, canonicalRoot);
300
+ }
301
+ catch (error) {
302
+ reportClassifiedDegradation('SPEC_PATH_MIGRATION_SKIPPED', error);
303
+ return spec;
304
+ }
305
+ const portableSpecPath = toPortableSpecPath(spec.id, spec.specPath);
306
+ let portableTechnicalPath = spec.technicalPath;
307
+ if (typeof spec.technicalPath === 'string' && isAbsolute(spec.technicalPath)) {
308
+ try {
309
+ portableTechnicalPath = toPortableSpecPath(spec.id, spec.technicalPath);
310
+ }
311
+ catch (error) {
312
+ reportClassifiedDegradation('TECHNICAL_PATH_MIGRATION_SKIPPED', error);
313
+ portableTechnicalPath = spec.technicalPath;
314
+ }
315
+ }
316
+ migratedIds.push(spec.id);
317
+ return { ...spec, specPath: portableSpecPath, technicalPath: portableTechnicalPath };
318
+ }));
319
+ if (migratedIds.length > 0) {
320
+ await saveAll(projectId, next);
321
+ recordSpecPathMigrationAudit(projectId, migratedIds);
322
+ }
323
+ return { migrated: migratedIds.length, specIds: migratedIds };
324
+ });
325
+ }
221
326
  /** Reload a spec from disk after the caller acquires its cross-process lock. */
222
- export async function getSpecFresh(projectId, specId) {
327
+ export async function getSpecFresh(projectId, specId, canonicalRoot) {
223
328
  specsCache.delete(projectId);
224
- return getSpec(projectId, specId);
329
+ return getSpec(projectId, specId, canonicalRoot);
225
330
  }
226
331
  /** SPEC-601: Lookup a spec by its globally unique UUID. */
227
332
  export async function getSpecByUuid(projectId, uuid) {
228
333
  const specs = await loadAll(projectId);
229
334
  return (specs.find((spec) => spec.uuid === uuid || spec.uuidAliases?.includes(uuid) === true) ?? null);
230
335
  }
336
+ /**
337
+ * Normalize an incoming absolute `specPath`/`technicalPath` — rooted in whatever
338
+ * checkout the caller invoked from — to its portable project-relative identity
339
+ * before it ever reaches disk. A value that is not the standard
340
+ * `planu/specs/<specId[-slug]>/<file>` shape is left untouched (best-effort):
341
+ * the shared resolver still fails closed for it at read time.
342
+ */
343
+ function portableizeSpecPaths(spec) {
344
+ let specPath = spec.specPath;
345
+ let technicalPath = spec.technicalPath;
346
+ if (typeof specPath === 'string' && isAbsolute(specPath)) {
347
+ try {
348
+ specPath = toPortableSpecPath(spec.id, specPath);
349
+ }
350
+ catch (error) {
351
+ if (!(error instanceof PortablePathError)) {
352
+ throw error;
353
+ }
354
+ }
355
+ }
356
+ if (typeof technicalPath === 'string' && isAbsolute(technicalPath)) {
357
+ try {
358
+ technicalPath = toPortableSpecPath(spec.id, technicalPath);
359
+ }
360
+ catch (error) {
361
+ if (!(error instanceof PortablePathError)) {
362
+ throw error;
363
+ }
364
+ }
365
+ }
366
+ return specPath === spec.specPath && technicalPath === spec.technicalPath
367
+ ? spec
368
+ : { ...spec, specPath, technicalPath };
369
+ }
231
370
  /**
232
371
  * Create a new spec. Throws if a spec with the same ID already exists.
233
372
  */
@@ -238,9 +377,11 @@ export async function createSpec(projectId, spec) {
238
377
  throw new Error(`Spec "${spec.id}" already exists in project "${projectId}"`);
239
378
  }
240
379
  const { criteria } = await loadSpecContent(spec);
380
+ const portableSpec = portableizeSpecPaths(spec);
241
381
  const specWithScore = {
242
- ...spec,
243
- healthScore: computeHealthScore(spec, criteria.length > 0 ? criteria : undefined).score,
382
+ ...portableSpec,
383
+ healthScore: computeHealthScore(portableSpec, criteria.length > 0 ? criteria : undefined)
384
+ .score,
244
385
  };
245
386
  const nextSpecs = [...specs, specWithScore];
246
387
  await saveAll(projectId, nextSpecs);
@@ -1,6 +1,7 @@
1
1
  import { readdir, unlink } from 'node:fs/promises';
2
2
  import { basename, dirname } from 'node:path';
3
3
  import { reportClassifiedDegradation } from '../../errors/classified-degradation.js';
4
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
4
5
  import { atomicWriteFile } from '../../engine/safety/atomic-write-file.js';
5
6
  /** Publish one complete canonical status snapshot with same-directory atomic replacement. */
6
7
  export function atomicStatusWrite(statusPath, status) {
@@ -3,6 +3,7 @@
3
3
  // Uses a local FIFO for fair in-process ordering and the existing SQLite fenced lease for
4
4
  // exclusion across CLI, MCP, durable-worker, and background-side-effect processes.
5
5
  import { resolve } from 'node:path';
6
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
6
7
  import { acquireLock, releaseLock } from '../../engine/safety/file-mutex.js';
7
8
  import { cleanupDeadStatusTemps } from './atomic-status-write.js';
8
9
  const lockQueues = new Map();
@@ -110,6 +110,7 @@ export async function quarantineCorruptStatus(statusPath, projectPath) {
110
110
  }
111
111
  return { quarantinedAt: new Date().toISOString(), quarantinePath };
112
112
  }
113
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
113
114
  import { fastScanSpecsAsync } from '../../engine/core-bridge.js';
114
115
  /**
115
116
  * Rebuild a fresh status.json by reading all spec.md frontmatters.
@@ -1,5 +1,15 @@
1
- import type { StorageBundle, StorageBundleOptions } from '../types/storage-bundle.js';
2
- export type { StorageBundle, StorageBundleOptions } from '../types/storage-bundle.js';
1
+ import { RuntimeDatabase, type RuntimeProjectBundle } from './runtime-db.js';
2
+ export interface StorageBundle {
3
+ readonly schemaVersion: 1;
4
+ readonly createdAt: string;
5
+ readonly runtimeSchemaVersion: number;
6
+ readonly projectId: string;
7
+ readonly payload: RuntimeProjectBundle;
8
+ readonly checksum: string;
9
+ }
10
+ export interface StorageBundleOptions {
11
+ readonly database?: RuntimeDatabase;
12
+ }
3
13
  export declare function exportStorageBundle(projectId: string, outputPath: string, options?: StorageBundleOptions): Promise<StorageBundle>;
4
14
  export declare function importStorageBundle(inputPath: string, options?: StorageBundleOptions): Promise<StorageBundle>;
5
15
  //# sourceMappingURL=storage-bundle.d.ts.map
@@ -1,3 +1,4 @@
1
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
1
2
  import { technologyValue } from '../engine/technology-registry.js';
2
3
  // storage/supabase-store.ts — Supabase integration persistence (SPEC-437)
3
4
  import { join } from 'node:path';
@@ -1,6 +1,7 @@
1
1
  // storage/technology-selection-store.ts — SPEC-1021 project-local technology contract
2
2
  import { mkdir, readFile } from 'node:fs/promises';
3
3
  import { dirname, join } from 'node:path';
4
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
4
5
  import { writeJsonSafe } from '../engine/safety/atomic-writer.js';
5
6
  import { safeJsonParse } from './base-store.js';
6
7
  import { withFileLock } from './file-mutex.js';
@@ -1,5 +1,7 @@
1
1
  import type { TrashItem } from '../types/index.js';
2
2
  import type { TrashCleanupConfig, TrashCleanupResult } from '../types/safety.js';
3
+ import { pathExistsStrictByStat as pathExists } from '../core/shared/fs.js';
4
+ export { pathExists };
3
5
  /**
4
6
  * Load the trash manifest (list of all trashed items).
5
7
  */
@@ -29,10 +31,6 @@ export declare function purgeAllTrash(projectId: string): Promise<number>;
29
31
  * Count files in a directory recursively (for project delete summary).
30
32
  */
31
33
  export declare function countFiles(dirPath: string): Promise<number>;
32
- /**
33
- * Check if a path exists.
34
- */
35
- export declare function pathExists(p: string): Promise<boolean>;
36
34
  /**
37
35
  * Recursively sum file sizes in a directory.
38
36
  */
@@ -2,6 +2,8 @@ import { readJson, writeJson, projectDataDir } from './base-store.js';
2
2
  import { withFileLock } from './file-mutex.js';
3
3
  import { mkdir, cp, rm, readdir, stat } from 'node:fs/promises';
4
4
  import { join } from 'node:path';
5
+ import { pathExistsStrictByStat as pathExists } from '../core/shared/fs.js';
6
+ export { pathExists };
5
7
  function sanitizeId(id) {
6
8
  const sanitized = id.replace(/[/\\]/g, '_').replace(/\.\./g, '_');
7
9
  if (!sanitized || sanitized === '.' || sanitized === '..') {
@@ -176,21 +178,6 @@ export async function countFiles(dirPath) {
176
178
  throw error;
177
179
  }
178
180
  }
179
- /**
180
- * Check if a path exists.
181
- */
182
- export async function pathExists(p) {
183
- try {
184
- await stat(p);
185
- return true;
186
- }
187
- catch (error) {
188
- if (error.code === 'ENOENT') {
189
- return false;
190
- }
191
- throw error;
192
- }
193
- }
194
181
  // ---------------------------------------------------------------------------
195
182
  // Trash TTL cleanup (SPEC-094 AC-6)
196
183
  // ---------------------------------------------------------------------------
@@ -2,6 +2,7 @@
2
2
  // SPEC-075 AC-04: Same interface as SQLite adapter, uses JSON files.
3
3
  import { readJson, writeJson, projectDataDir } from '../base-store.js';
4
4
  import { withFileLock } from '../file-mutex.js';
5
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
5
6
  import { cosineSimilarity } from '../../engine/vector-store/similarity.js';
6
7
  let warnedOnce = false;
7
8
  /**
@@ -2,6 +2,7 @@
2
2
  // SPEC-075 AC-05: Idempotent, preserves JSON backup.
3
3
  import { readJson, projectDataDir } from '../base-store.js';
4
4
  import { existsSync } from 'node:fs';
5
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
5
6
  import { TFIDFEngine } from '../../engine/vector-store/tfidf.js';
6
7
  import { reportClassifiedDegradation } from '../../errors/classified-degradation.js';
7
8
  /** Check if a migration marker exists (idempotency). */
@@ -1,5 +1,6 @@
1
1
  // storage/vector-store/sqlite-adapter.ts — SQLite storage backend using better-sqlite3.
2
2
  // SPEC-075 AC-03: WAL mode, BLOB embeddings, optional native dependency.
3
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
3
4
  import { cosineSimilarity } from '../../engine/vector-store/similarity.js';
4
5
  import { projectDataDir, safeJsonParse } from '../base-store.js';
5
6
  import { mkdirSync, existsSync } from 'node:fs';
@@ -1,9 +1,9 @@
1
1
  // audit-claude-config.ts — Tool handler for audit_claude_config (SPEC-092)
2
2
  // SPEC-724: Added gate='core-rules' to assert per-host rule files exist.
3
3
  import { compactResult } from './output-formatter.js';
4
+ import { fileExists } from '../core/shared/fs.js';
4
5
  import { auditClaudeMd, auditRules, auditMemory, auditSettings, calculateScore, pickQuickWins, } from '../engine/claude-config-auditor/index.js';
5
6
  import { detectHost } from '../engine/host-detection/detect-host.js';
6
- import { access } from 'node:fs/promises';
7
7
  import { join } from 'node:path';
8
8
  import { homedir } from 'node:os';
9
9
  // ---------------------------------------------------------------------------
@@ -14,15 +14,6 @@ const CORE_RULES_FILES = [
14
14
  'parallelism.md',
15
15
  'token-optimization.md',
16
16
  ];
17
- async function fileExists(filePath) {
18
- try {
19
- await access(filePath);
20
- return true;
21
- }
22
- catch {
23
- return false;
24
- }
25
- }
26
17
  async function checkCoreRulesGate(projectPath) {
27
18
  const host = detectHost();
28
19
  const blockers = [];
@@ -11,5 +11,5 @@ export interface ConcurrencyAnalysisResult extends ConcurrencyAnalysis {
11
11
  export declare function generateConcurrencyAnalysis(_spec: Spec, content: string, _knowledge: ProjectKnowledge): ConcurrencyAnalysisResult;
12
12
  export declare function buildScalabilityAssessment(spec: Spec, knowledge: ProjectKnowledge, scenarios: FailureScenario[], hasRolloutEvidence?: boolean): string;
13
13
  export declare function calculateOverallRisk(scenarios: FailureScenario[], concurrency: ConcurrencyAnalysis): RiskLevel;
14
- export declare function readSpecContent(spec: Spec): Promise<string>;
14
+ export declare function readSpecContent(spec: Spec, projectPath?: string): Promise<string>;
15
15
  //# sourceMappingURL=challenge-spec-helpers.d.ts.map
@@ -1,5 +1,7 @@
1
1
  // tools/challenge-spec-helpers.ts — Concurrency, risk, and spec-reader helpers for challenge-spec
2
2
  import { readFile } from 'node:fs/promises';
3
+ import { isAbsolute } from 'node:path';
4
+ import { resolveVerifiedSpecPath } from '../storage/project-identity.js';
3
5
  import { readSpecTechnicalSection } from '../engine/spec-format/read-technical-section.js';
4
6
  import { hasAffirmedMatch, stripMetaAnalysisText, stripNonContractText, } from '../engine/text-signal-boundaries.js';
5
7
  // Bare keyword matches (counter, status, draft, ...) are common in unrelated
@@ -131,11 +133,14 @@ export function calculateOverallRisk(scenarios, concurrency) {
131
133
  return 'low';
132
134
  }
133
135
  // --- Spec content reader ---
134
- export async function readSpecContent(spec) {
136
+ export async function readSpecContent(spec, projectPath) {
135
137
  let content = `${spec.title} ${spec.type} ${spec.scope} ${spec.target} ${spec.tags.join(' ')}`;
136
138
  try {
137
139
  if (spec.specPath) {
138
- content += ' ' + (await readFile(spec.specPath, 'utf-8'));
140
+ const resolvedPath = !isAbsolute(spec.specPath) && projectPath
141
+ ? await resolveVerifiedSpecPath(spec.id, spec.specPath, projectPath)
142
+ : spec.specPath;
143
+ content += ' ' + (await readFile(resolvedPath, 'utf-8'));
139
144
  }
140
145
  }
141
146
  catch {
@@ -2,11 +2,13 @@
2
2
  // Analyzes a spec from adversarial perspectives: failure scenarios,
3
3
  // concurrency issues, scale limits, security holes, and data consistency.
4
4
  import { readFile } from 'node:fs/promises';
5
+ import { isAbsolute } from 'node:path';
5
6
  import { createHash } from 'node:crypto';
6
7
  import { specStore, knowledgeStore } from '../storage/index.js';
7
8
  // SPEC-1011 Bug F: fallback resolver using disk fingerprints
8
9
  import { resolveProjectFromPath } from '../storage/project-resolver.js';
9
10
  import { updateSpec } from '../storage/spec-store.js';
11
+ import { resolveVerifiedSpecPath } from '../storage/project-identity.js';
10
12
  import { resolveProjectId, missingProjectIdError } from './resolve-project-id.js';
11
13
  import { elicitOrFallback, buildEnumSchema } from '../engine/elicitation/elicit-helper.js';
12
14
  import { t, ti } from '../i18n/index.js';
@@ -83,13 +85,16 @@ function extractOutOfScopeSection(content) {
83
85
  }
84
86
  return found ? captured.join('\n') : null;
85
87
  }
86
- async function resolveDocumentOutOfScope(spec) {
88
+ async function resolveDocumentOutOfScope(spec, projectPath) {
87
89
  if (!spec.specPath) {
88
90
  return [];
89
91
  }
90
92
  let fileContent;
91
93
  try {
92
- fileContent = await readFile(spec.specPath, 'utf-8');
94
+ const resolvedPath = !isAbsolute(spec.specPath) && projectPath
95
+ ? await resolveVerifiedSpecPath(spec.id, spec.specPath, projectPath)
96
+ : spec.specPath;
97
+ fileContent = await readFile(resolvedPath, 'utf-8');
93
98
  }
94
99
  catch {
95
100
  return [];
@@ -97,8 +102,8 @@ async function resolveDocumentOutOfScope(spec) {
97
102
  const sectionContent = extractOutOfScopeSection(fileContent);
98
103
  return sectionContent === null ? [] : extractListItems(sectionContent);
99
104
  }
100
- async function resolveOutOfScopeItems(spec) {
101
- const documentItems = await resolveDocumentOutOfScope(spec);
105
+ async function resolveOutOfScopeItems(spec, projectPath) {
106
+ const documentItems = await resolveDocumentOutOfScope(spec, projectPath);
102
107
  return documentItems.length > 0 ? documentItems : (spec.outOfScope ?? []);
103
108
  }
104
109
  /**
@@ -192,7 +197,7 @@ export async function handleChallengeSpec(args, server) {
192
197
  // 2b. Load Constitution for compliance context
193
198
  const constitution = await knowledgeStore.getConstitution(projectId);
194
199
  // 3. Read spec content
195
- const specContent = await readSpecContent(spec);
200
+ const specContent = await readSpecContent(spec, knowledge.projectPath);
196
201
  const capabilities = detectChallengeCapabilities(spec, specContent);
197
202
  // 4. Determine focus areas
198
203
  const focusAreas = focus && focus.length > 0 ? focus : ALL_FOCUS_AREAS;
@@ -224,7 +229,7 @@ export async function handleChallengeSpec(args, server) {
224
229
  }
225
230
  failureScenarios.push(...collectCapabilityScenarios({ spec, specContent, knowledge, focusAreas, capabilities }));
226
231
  // SPEC-612: Check for contradictions between outOfScope and acceptance criteria
227
- const resolvedOutOfScope = await resolveOutOfScopeItems(spec);
232
+ const resolvedOutOfScope = await resolveOutOfScopeItems(spec, knowledge.projectPath);
228
233
  if (resolvedOutOfScope.length > 0) {
229
234
  const criteriaRange = findMarkdownSectionRange(specContent, 'Acceptance Criteria');
230
235
  const criteriaTexts = criteriaRange === null