@planu/cli 5.3.68 → 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (381) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/dist/.planu-build.json +1 -1
  3. package/dist/cli/commands/install.d.ts +2 -15
  4. package/dist/config/skill-templates/planu-dogfood-bug.md +43 -0
  5. package/dist/config/skill-templates/planu-implement.md +42 -0
  6. package/dist/config/skill-templates/planu-review.md +47 -0
  7. package/dist/core/shared/fs.d.ts +11 -0
  8. package/dist/core/shared/fs.js +90 -0
  9. package/dist/core/shared/strings.d.ts +3 -0
  10. package/dist/core/shared/strings.js +13 -0
  11. package/dist/engine/actuals/git-analyzer.js +1 -1
  12. package/dist/engine/actuals/progress-parser.js +1 -3
  13. package/dist/engine/agent-handoff-store.js +1 -0
  14. package/dist/engine/agent-squad/dispatcher.js +1 -0
  15. package/dist/engine/agent-telemetry.js +1 -0
  16. package/dist/engine/auth/config.js +1 -0
  17. package/dist/engine/auto-updater/atomic-upgrade.js +1 -0
  18. package/dist/engine/auto-updater/index.js +1 -0
  19. package/dist/engine/autopilot/action-registry.js +20 -0
  20. package/dist/engine/autopilot/audit-logger.js +1 -0
  21. package/dist/engine/autopilot/bootstrap.js +9 -2
  22. package/dist/engine/autopilot/complete-loop.js +4 -0
  23. package/dist/engine/autopilot/crash-shield-rate-limiter.js +1 -0
  24. package/dist/engine/autopilot/event-bus.js +1 -0
  25. package/dist/engine/autopilot/state-updater.js +6 -0
  26. package/dist/engine/browser-validator.js +1 -3
  27. package/dist/engine/build-tool-detector.js +1 -8
  28. package/dist/engine/bundle-installer.js +2 -10
  29. package/dist/engine/cascade-hooks/core/append-releases.js +1 -0
  30. package/dist/engine/cascade-hooks/core/write-session-json.js +2 -2
  31. package/dist/engine/cascade-hooks/hooks/dispatch-hook-event.hook.d.ts +3 -1
  32. package/dist/engine/cascade-hooks/hooks/dispatch-hook-event.hook.js +12 -3
  33. package/dist/engine/cascade-hooks/hooks/estimate-calibration.hook.js +1 -0
  34. package/dist/engine/cascade-hooks/hooks/housekeeping-on-done.hook.js +2 -0
  35. package/dist/engine/cascade-hooks/hooks/implementing-kickoff.hook.js +5 -1
  36. package/dist/engine/cascade-hooks/hooks/lesson-drift.hook.js +1 -0
  37. package/dist/engine/cascade-hooks/hooks/orchestration-plan.hook.js +1 -0
  38. package/dist/engine/cascade-hooks/hooks/session-context.hook.js +4 -2
  39. package/dist/engine/cascade-hooks/hooks/slack-notify.hook.js +1 -0
  40. package/dist/engine/cascade-hooks/hooks/status-json.hook.js +2 -0
  41. package/dist/engine/cascade-hooks/hooks/velocity-profile.hook.js +2 -0
  42. package/dist/engine/cascade-hooks/runner.js +2 -0
  43. package/dist/engine/cascade-hooks/state-drift-detector.js +2 -0
  44. package/dist/engine/checkpoint/checkpoint-manager.js +2 -0
  45. package/dist/engine/checkpoint/policy-engine.js +1 -0
  46. package/dist/engine/ci-generator/stack-detector.js +2 -10
  47. package/dist/engine/clarification-gate/token-store.js +1 -0
  48. package/dist/engine/claude-config-auditor/claudemd-auditor.js +2 -10
  49. package/dist/engine/claude-config-auditor/settings-auditor.js +2 -10
  50. package/dist/engine/client-detection.js +2 -10
  51. package/dist/engine/compliance/auto-remediator.js +1 -0
  52. package/dist/engine/compliance/evidence-builder.d.ts +2 -2
  53. package/dist/engine/compliance/framework-catalog.d.ts +6 -6
  54. package/dist/engine/compliance/gap-analyzer.d.ts +2 -2
  55. package/dist/engine/config-health/build-tool-checker.js +1 -9
  56. package/dist/engine/config-health/ci-commands-collector.d.ts +2 -1
  57. package/dist/engine/config-health/ci-commands-collector.js +2 -9
  58. package/dist/engine/config-health/go-checker.js +1 -9
  59. package/dist/engine/config-health/mcp-config-checker.js +2 -10
  60. package/dist/engine/config-health/python-checker.js +1 -9
  61. package/dist/engine/config-health/rust-checker.js +1 -9
  62. package/dist/engine/config-health/ts-checker-scripts.js +1 -9
  63. package/dist/engine/config-health/ts-checker.js +1 -9
  64. package/dist/engine/context-artifacts/store.js +1 -0
  65. package/dist/engine/context-md-generator.js +1 -0
  66. package/dist/engine/context-orchestrator/index.js +2 -0
  67. package/dist/engine/convention-scanner/convention-parser.js +2 -9
  68. package/dist/engine/cost-guardrails.js +1 -0
  69. package/dist/engine/cost-tracking/ledger.js +1 -0
  70. package/dist/engine/criterion-identity.js +1 -1
  71. package/dist/engine/dashboard/data-loader.js +1 -0
  72. package/dist/engine/dashboard/drift-score.js +2 -0
  73. package/dist/engine/dashboard/spec-updater.d.ts +3 -1
  74. package/dist/engine/dashboard/spec-updater.js +9 -2
  75. package/dist/engine/dashboard/templates-layout.d.ts +2 -2
  76. package/dist/engine/dashboard/templates-layout.js +2 -9
  77. package/dist/engine/data-projects-gc/gc-runner.js +2 -4
  78. package/dist/engine/deleter/audit-logger.js +1 -0
  79. package/dist/engine/deleter/core.js +6 -0
  80. package/dist/engine/deleter/trash-manager.js +1 -0
  81. package/dist/engine/desktop-detector.js +1 -9
  82. package/dist/engine/detection-utils.d.ts +2 -1
  83. package/dist/engine/detection-utils.js +3 -10
  84. package/dist/engine/detectors/advanced-framework-detector/helpers.d.ts +3 -2
  85. package/dist/engine/detectors/advanced-framework-detector/helpers.js +3 -17
  86. package/dist/engine/detectors/cicd-detector.js +2 -10
  87. package/dist/engine/detectors/css-framework-detector.js +2 -10
  88. package/dist/engine/detectors/deployment-detector.js +3 -12
  89. package/dist/engine/detectors/frontend-perf-detector.js +2 -10
  90. package/dist/engine/detectors/gitops-detector.js +3 -11
  91. package/dist/engine/detectors/idp-detector.js +1 -3
  92. package/dist/engine/detectors/k3s-detector.js +3 -11
  93. package/dist/engine/detectors/llm-detector/file-readers.d.ts +2 -1
  94. package/dist/engine/detectors/llm-detector/file-readers.js +2 -9
  95. package/dist/engine/detectors/mfe-detector.js +5 -13
  96. package/dist/engine/detectors/monitoring-detector.js +2 -11
  97. package/dist/engine/detectors/monorepo-detector.d.ts +1 -0
  98. package/dist/engine/detectors/monorepo-detector.js +1 -10
  99. package/dist/engine/detectors/nomad-detector.js +3 -11
  100. package/dist/engine/detectors/otel-ecosystem-detectors.d.ts +2 -1
  101. package/dist/engine/detectors/otel-ecosystem-detectors.js +2 -10
  102. package/dist/engine/doc-generator/executive-summary/html-template.js +1 -7
  103. package/dist/engine/doc-generator/executive-summary/section-builders.js +1 -7
  104. package/dist/engine/doc-generator/per-spec-report/mermaid-renderer.js +1 -7
  105. package/dist/engine/doc-generator/per-spec-report/spec-section-builders.js +1 -7
  106. package/dist/engine/doc-generator/per-spec-report/technical-report.js +1 -7
  107. package/dist/engine/doc-generator/portal/analytics-page.js +1 -7
  108. package/dist/engine/doc-generator/portal/architecture-page.js +1 -7
  109. package/dist/engine/doc-generator/portal/changelog-page.js +1 -7
  110. package/dist/engine/doc-generator/portal/decision-page.js +1 -7
  111. package/dist/engine/doc-generator/portal/decision-timeline-builder.js +1 -7
  112. package/dist/engine/doc-generator/portal/kanban-view-builder.js +1 -7
  113. package/dist/engine/doc-generator/portal/portal-breadcrumbs.js +1 -7
  114. package/dist/engine/doc-generator/portal/portal-landing-cards.js +1 -7
  115. package/dist/engine/doc-generator/portal/portal-navbar.js +1 -7
  116. package/dist/engine/doc-generator/portal/portal-page-detector.d.ts +3 -0
  117. package/dist/engine/doc-generator/portal/portal-page-detector.js +1 -10
  118. package/dist/engine/doc-generator/portal/portal-regenerator.js +2 -0
  119. package/dist/engine/doc-generator/portal/risk-matrix-svg.js +1 -7
  120. package/dist/engine/doc-generator/portal/risk-page.js +1 -7
  121. package/dist/engine/doc-generator/portal/roadmap-page.js +1 -7
  122. package/dist/engine/doc-generator/proposal/proposal-gantt-builder.js +1 -7
  123. package/dist/engine/doc-generator/proposal/proposal-kpi-builder.js +1 -7
  124. package/dist/engine/doc-generator/proposal/proposal-section-builders-advanced.js +2 -8
  125. package/dist/engine/doc-generator/proposal/proposal-section-builders.js +1 -7
  126. package/dist/engine/docs-site-generator/html-templates.js +1 -7
  127. package/dist/engine/docs-site-generator/markdown-renderer.js +1 -7
  128. package/dist/engine/drift/violation-resolver.js +2 -0
  129. package/dist/engine/dynamic-knowledge/knowledge-cache.js +1 -0
  130. package/dist/engine/ecosystem-absorber/knowledge-cache.js +1 -0
  131. package/dist/engine/edge-db-detector.js +1 -10
  132. package/dist/engine/escalator/retry-counter.js +1 -0
  133. package/dist/engine/evidence-gates/artifact-reader.js +1 -0
  134. package/dist/engine/evidence-gates/evidence-autofill.js +1 -0
  135. package/dist/engine/evidence-gates/evidence-skeletons.js +1 -0
  136. package/dist/engine/evidence-gates/reconciliation-freshness.js +1 -0
  137. package/dist/engine/execution/durable-job-heartbeat-runtime.js +1 -0
  138. package/dist/engine/execution/job-runtime.js +2 -0
  139. package/dist/engine/execution/validate-job-executor.d.ts +1 -1
  140. package/dist/engine/execution/validate-job-executor.js +3 -0
  141. package/dist/engine/execution/validate-job-payload.js +1 -0
  142. package/dist/engine/execution/validate-worker-thread.js +1 -0
  143. package/dist/engine/facilitate/context-loader.js +1 -0
  144. package/dist/engine/figma/change-detector.d.ts +1 -8
  145. package/dist/engine/figma/code-connect-fetcher.d.ts +1 -7
  146. package/dist/engine/figma/design-enricher.d.ts +1 -17
  147. package/dist/engine/figma/design-enricher.js +0 -1
  148. package/dist/engine/figma/e2e-generator.d.ts +1 -23
  149. package/dist/engine/figma/flow-analyzer.d.ts +1 -11
  150. package/dist/engine/figma/frame-extractor.d.ts +1 -11
  151. package/dist/engine/figma/frame-extractor.js +3 -0
  152. package/dist/engine/figma/multi-file-manager.d.ts +1 -6
  153. package/dist/engine/figma/spec-generator.js +2 -0
  154. package/dist/engine/figma/thumbnail-fetcher.d.ts +1 -1
  155. package/dist/engine/figma/token-extractor.d.ts +1 -6
  156. package/dist/engine/figma/token-extractor.js +0 -1
  157. package/dist/engine/figma/version-tracker.d.ts +1 -7
  158. package/dist/engine/figma/version-tracker.js +0 -1
  159. package/dist/engine/figma/visual-qa.d.ts +5 -19
  160. package/dist/engine/figma/visual-qa.js +1 -2
  161. package/dist/engine/figma/webhook-manager.d.ts +1 -7
  162. package/dist/engine/frontmatter-sha/reseal.js +1 -0
  163. package/dist/engine/frontmatter-sha/verify-terminal.js +1 -0
  164. package/dist/engine/git-hook-injector.js +2 -10
  165. package/dist/engine/github/quality-dimensions.js +1 -3
  166. package/dist/engine/global-rules-manager.js +2 -3
  167. package/dist/engine/handoff-artifacts/implementation-review-reader.js +1 -0
  168. package/dist/engine/handoff-artifacts/io.js +2 -0
  169. package/dist/engine/handoff-packager.js +2 -1
  170. package/dist/engine/health/auto-fixer.js +1 -0
  171. package/dist/engine/hooks/context-injector.js +1 -0
  172. package/dist/engine/hooks-reconciler.js +1 -8
  173. package/dist/engine/impact-detector/index.js +2 -9
  174. package/dist/engine/implementation-contract/common.js +1 -3
  175. package/dist/engine/implementation-contract/evaluator.js +1 -3
  176. package/dist/engine/keyword-matcher/boundary.d.ts +2 -7
  177. package/dist/engine/keyword-matcher/boundary.js +2 -14
  178. package/dist/engine/lifecycle-reconciliation-io.js +1 -0
  179. package/dist/engine/lifecycle-reconciliation.js +3 -0
  180. package/dist/engine/local-first/detector.js +1 -9
  181. package/dist/engine/marketplace-fetcher/cache.js +2 -0
  182. package/dist/engine/marketplace-fetcher/index.js +1 -0
  183. package/dist/engine/mcp-config/mcp-config-writer.js +2 -10
  184. package/dist/engine/migrations/remove-commercial-state.js +2 -0
  185. package/dist/engine/mobile-detector-shared.d.ts +1 -1
  186. package/dist/engine/mobile-detector-shared.js +2 -9
  187. package/dist/engine/multi-channel-notifier.js +1 -0
  188. package/dist/engine/multi-teammate-review/disagreement-counter.js +1 -0
  189. package/dist/engine/multi-teammate-review/panel-orchestrator.js +1 -0
  190. package/dist/engine/onboarding-engine.js +1 -9
  191. package/dist/engine/permissions-merger/stack-detectors.js +2 -10
  192. package/dist/engine/pii-detector/core.js +1 -3
  193. package/dist/engine/platform-engineering/dx-analyzer.js +1 -10
  194. package/dist/engine/platform-engineering/idp-detector.js +2 -10
  195. package/dist/engine/project-dna/ai-tool-detector.js +2 -10
  196. package/dist/engine/project-dna/stack-detector.js +2 -10
  197. package/dist/engine/project-graph/builder.js +11 -2
  198. package/dist/engine/project-graph/cache.d.ts +5 -2
  199. package/dist/engine/project-graph/cache.js +174 -34
  200. package/dist/engine/project-graph/extractors/decision-store-extractor.js +1 -0
  201. package/dist/engine/project-graph/freshness-projection.js +3 -0
  202. package/dist/engine/project-graph/query.js +14 -11
  203. package/dist/engine/project-health-checker.js +2 -6
  204. package/dist/engine/provider-adapters/shared/spec-loader.js +1 -0
  205. package/dist/engine/quality-gates/gate-evaluator.js +1 -3
  206. package/dist/engine/react-detector.js +6 -14
  207. package/dist/engine/reconcile/apply-changes.js +1 -3
  208. package/dist/engine/registry/core.js +1 -0
  209. package/dist/engine/registry/loader.js +2 -0
  210. package/dist/engine/release/postmortem-generator.js +1 -0
  211. package/dist/engine/release/rollback-runner.d.ts +2 -2
  212. package/dist/engine/release/stuck-spec-detector.js +7 -0
  213. package/dist/engine/release-pipeline/release-spec-closer.js +3 -0
  214. package/dist/engine/rules-reconciler.d.ts +1 -1
  215. package/dist/engine/rules-reconciler.js +2 -9
  216. package/dist/engine/safety/atomic-writer.js +1 -0
  217. package/dist/engine/safety/cross-process-lock.js +2 -0
  218. package/dist/engine/safety/file-mutex.js +1 -0
  219. package/dist/engine/safety/lock-lease-store.js +1 -0
  220. package/dist/engine/safety/lock-scavenger.js +2 -0
  221. package/dist/engine/saga/transition-cascade.js +3 -0
  222. package/dist/engine/scan-project/index.js +1 -0
  223. package/dist/engine/scan-project/module-discoverer.js +1 -9
  224. package/dist/engine/schema-parity-auditor/handler-checker.js +1 -3
  225. package/dist/engine/schema-parity-auditor/index.js +1 -3
  226. package/dist/engine/schema-parity-auditor/type-checker.js +1 -3
  227. package/dist/engine/self-healing/strategies/coverage-fix.js +2 -10
  228. package/dist/engine/session-context-generator.d.ts +8 -0
  229. package/dist/engine/session-context-generator.js +33 -23
  230. package/dist/engine/session-state/session-artifact-refresher.d.ts +7 -0
  231. package/dist/engine/session-state/session-artifact-refresher.js +140 -0
  232. package/dist/engine/session-state/writer.d.ts +3 -0
  233. package/dist/engine/session-state/writer.js +35 -17
  234. package/dist/engine/shared-agent-memory.js +1 -0
  235. package/dist/engine/skill-adapter/index.js +3 -0
  236. package/dist/engine/skill-bootstrap/registry-fetcher.js +1 -0
  237. package/dist/engine/skill-bootstrap/skill-writer.js +2 -9
  238. package/dist/engine/skill-bootstrap/stack-matcher.js +1 -9
  239. package/dist/engine/skill-discovery/multi-agent-writer.d.ts +1 -0
  240. package/dist/engine/skill-discovery/multi-agent-writer.js +1 -9
  241. package/dist/engine/skill-generator/workflow-skill-generator.js +1 -0
  242. package/dist/engine/skill-registry/ttl-refresh.js +2 -0
  243. package/dist/engine/spec-audit/index.js +2 -0
  244. package/dist/engine/spec-audit/report-writer.js +1 -0
  245. package/dist/engine/spec-coverage/core.js +1 -0
  246. package/dist/engine/spec-decomposer/analyzer.js +1 -11
  247. package/dist/engine/spec-dependency-graph/dot-exporter.d.ts +1 -1
  248. package/dist/engine/spec-dependency-graph/graph-builder.d.ts +1 -20
  249. package/dist/engine/spec-dependency-graph/superseded-set.d.ts +1 -1
  250. package/dist/engine/spec-diff-engine.js +1 -7
  251. package/dist/engine/spec-format/read-technical-section.js +1 -3
  252. package/dist/engine/spec-format/replace-section.js +1 -3
  253. package/dist/engine/spec-format/spec-id.d.ts +9 -1
  254. package/dist/engine/spec-format/spec-id.js +24 -3
  255. package/dist/engine/spec-format/unified-spec-builder.js +1 -3
  256. package/dist/engine/spec-migrator/canonical-deduplicator.js +2 -0
  257. package/dist/engine/spec-observability/tracker.js +1 -0
  258. package/dist/engine/spec-registry/adapter.js +2 -10
  259. package/dist/engine/spec-registry/validator.d.ts +1 -0
  260. package/dist/engine/spec-registry/validator.js +1 -9
  261. package/dist/engine/spec-state-machine/transition-spec.js +1 -0
  262. package/dist/engine/spec-templates/custom-loader.js +1 -0
  263. package/dist/engine/stack-auditor/build-tool-auditor.js +1 -9
  264. package/dist/engine/staleness/stale-implementing.js +5 -14
  265. package/dist/engine/status-reconciler/index.js +4 -1
  266. package/dist/engine/structural-memory/helpers.js +1 -0
  267. package/dist/engine/supply-chain/slsa-checker.js +1 -9
  268. package/dist/engine/tdd-enforcer/stub-artifact-path.js +1 -0
  269. package/dist/engine/telemetry/health-checker.js +1 -0
  270. package/dist/engine/telemetry/telemetry-store.js +1 -0
  271. package/dist/engine/token-optimizer/response-cache.js +1 -3
  272. package/dist/engine/tool-groups/group-manager.js +2 -0
  273. package/dist/engine/update-notifier.js +1 -0
  274. package/dist/engine/validation/approved-spec-portability.js +1 -0
  275. package/dist/engine/validation/durable-validation.js +1 -0
  276. package/dist/engine/validation/validation-freshness.js +2 -0
  277. package/dist/engine/validation/validation-receipt.js +1 -0
  278. package/dist/engine/validation/validation-submission.d.ts +1 -1
  279. package/dist/engine/validation-evidence-ledger.js +1 -0
  280. package/dist/engine/validator/deep-code-checker.js +1 -3
  281. package/dist/engine/validator/executable-evidence.d.ts +1 -14
  282. package/dist/engine/validator/scope-resolver.d.ts +2 -2
  283. package/dist/engine/validator/spec-compliance-runner.d.ts +1 -31
  284. package/dist/engine/validator/validation-report-writer.js +1 -1
  285. package/dist/engine/validator.d.ts +1 -1
  286. package/dist/engine/validator.js +1 -0
  287. package/dist/engine/velocity/measure-velocity.js +2 -0
  288. package/dist/engine/version-resolver.js +1 -0
  289. package/dist/engine/workers/handlers/auto-drift.js +3 -0
  290. package/dist/engine/workspace-manager.js +4 -0
  291. package/dist/hosts/gemini/config-scaffold.js +2 -10
  292. package/dist/storage/approval-operation-lock.js +1 -0
  293. package/dist/storage/auto-promoter-config-store.js +1 -0
  294. package/dist/storage/autopilot-log-store.js +1 -0
  295. package/dist/storage/base-store.js +1 -0
  296. package/dist/storage/checkpoint-store.js +1 -0
  297. package/dist/storage/feedback-remote.js +1 -0
  298. package/dist/storage/gaps-log.js +1 -0
  299. package/dist/storage/global-projects-store.js +1 -0
  300. package/dist/storage/global-store.js +1 -0
  301. package/dist/storage/knowledge-store/sessions.js +2 -0
  302. package/dist/storage/migrations/canonical-storage.js +42 -18
  303. package/dist/storage/project-drift-store.js +1 -0
  304. package/dist/storage/project-identity.js +1 -0
  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 +7 -0
  312. package/dist/storage/spec-store.js +21 -1
  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/check-readiness.js +104 -30
  326. package/dist/tools/clarify-requirements/multiple-choice.d.ts +3 -3
  327. package/dist/tools/configure-oauth-handler.js +1 -0
  328. package/dist/tools/create-skill.js +11 -9
  329. package/dist/tools/create-spec-helpers.d.ts +1 -3
  330. package/dist/tools/create-spec-helpers.js +1 -8
  331. package/dist/tools/create-spec.js +1 -13
  332. package/dist/tools/dashboard.js +5 -0
  333. package/dist/tools/github-pr-handler.js +1 -0
  334. package/dist/tools/github-release-handler.d.ts +1 -0
  335. package/dist/tools/github-release-handler.js +4 -3
  336. package/dist/tools/graph-specs.d.ts +1 -1
  337. package/dist/tools/heal-spec-docs.js +1 -3
  338. package/dist/tools/init-project/git-setup.d.ts +2 -2
  339. package/dist/tools/init-project/host-assets-writer.js +9 -10
  340. package/dist/tools/init-project/lifecycle-helpers.d.ts +2 -2
  341. package/dist/tools/init-project/lint-scaffolder.js +2 -10
  342. package/dist/tools/init-project/stack-detector.d.ts +2 -2
  343. package/dist/tools/reconcile-interactive-question-hooks.d.ts +2 -2
  344. package/dist/tools/register-sdd-tools.js +1 -0
  345. package/dist/tools/safe-handler.js +1 -0
  346. package/dist/tools/schemas/spec-id.d.ts +1 -6
  347. package/dist/tools/schemas/spec-id.js +1 -16
  348. package/dist/tools/tool-entry.d.ts +2 -2
  349. package/dist/tools/tool-entry.js +1 -1
  350. package/dist/tools/tool-registry/core-tools.d.ts +2 -2
  351. package/dist/tools/tool-registry/deprecated-stubs.d.ts +3 -3
  352. package/dist/tools/tool-registry/deprecated-stubs.js +1 -1
  353. package/dist/tools/triage-request.d.ts +2 -2
  354. package/dist/tools/update-status/approval-gates.d.ts +2 -2
  355. package/dist/tools/update-status/approval-gates.js +1 -0
  356. package/dist/tools/update-status/dod-gates.d.ts +1 -1
  357. package/dist/tools/update-status/done-receipt-verifier.d.ts +1 -1
  358. package/dist/tools/update-status/side-effects.js +5 -0
  359. package/dist/tools/update-status-actions.js +28 -40
  360. package/dist/tools/validate-graph-coverage.js +14 -2
  361. package/dist/tools/validate.js +2 -0
  362. package/dist/transports/middleware/types.d.ts +3 -3
  363. package/dist/types/atomic-upgrade.d.ts +1 -1
  364. package/dist/types/cascade-hooks.d.ts +3 -0
  365. package/dist/types/dashboard.d.ts +4 -1
  366. package/dist/types/durable-job.d.ts +20 -0
  367. package/dist/types/durable-job.js +9 -1
  368. package/dist/types/index.d.ts +2 -0
  369. package/dist/types/index.js +2 -0
  370. package/dist/types/installation.d.ts +16 -0
  371. package/dist/types/installation.js +2 -0
  372. package/dist/types/project-knowledge-graph.d.ts +11 -0
  373. package/dist/types/session-checkpoint.d.ts +16 -0
  374. package/dist/types/spec-dependency-graph.d.ts +21 -0
  375. package/dist/types/spec-dependency-graph.js +2 -0
  376. package/dist/types/universal-rules/index.d.ts +1 -0
  377. package/dist/types/validation-evidence.d.ts +45 -0
  378. package/package.json +16 -16
  379. package/planu-plugin.json +1 -1
  380. package/dist/types/storage-bundle.d.ts +0 -13
  381. package/dist/types/storage-bundle.js +0 -2
@@ -6,6 +6,7 @@ import { readFile, writeFile } from 'node:fs/promises';
6
6
  import { tmpdir } from 'node:os';
7
7
  import { join } from 'node:path';
8
8
  import { fetchLatestVersion } from './package-registry.js';
9
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
9
10
  import { getCachedVersions, saveCachedVersions, isExpired as isCachedVersionExpired, } from '../storage/version-cache-store.js';
10
11
  // -- Constants ---------------------------------------------------------------
11
12
  const CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours
@@ -1,8 +1,11 @@
1
1
  // engine/workers/handlers/auto-drift.ts — Auto drift detection on file changes (SPEC-225)
2
2
  import { relative, extname } from 'node:path';
3
3
  import { readdir, stat } from 'node:fs/promises';
4
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
4
5
  import { specStore } from '../../../storage/index.js';
6
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
5
7
  import { hashProjectPath } from '../../../storage/base-store.js';
8
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
6
9
  import { DriftCacheStore } from '../../../storage/drift-cache-store.js';
7
10
  import { emitAutopilotEvent } from '../../autopilot/event-bus.js';
8
11
  // ---------------------------------------------------------------------------
@@ -1,8 +1,12 @@
1
1
  // engine/workspace-manager.ts — SPEC-363: Multi-tenant Workspace Dashboard
2
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
2
3
  import { getProjects, addProject } from '../storage/global-projects-store.js';
4
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
3
5
  import { specStore } from '../storage/index.js';
6
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
4
7
  import { hashProjectPath, readJson } from '../storage/base-store.js';
5
8
  import { glob } from 'glob';
9
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
6
10
  import { resolveStorageLayout } from '../storage/storage-layout.js';
7
11
  // ---------------------------------------------------------------------------
8
12
  // SPEC-789: Project discovery fallback
@@ -2,11 +2,12 @@
2
2
  // Writes .gemini/conventions.md, .gemini/skills/planu-*.md, and .gemini/hooks/
3
3
  // equivalents when init_project runs inside a Gemini workspace.
4
4
  // NOTE: This function deliberately does NOT create .claude/ files.
5
- import { writeFile, readFile, mkdir, access } from 'node:fs/promises';
5
+ import { writeFile, readFile, mkdir } from 'node:fs/promises';
6
6
  import { join } from 'node:path';
7
7
  import { buildRulesForHost } from '../../engine/host-rules-templates/index.js';
8
8
  import { assertEnglishOnlyArtifactText } from '../../engine/spec-language/english-only.js';
9
9
  import { PLANU_VERSION } from '../../config/version.js';
10
+ import { fileExists } from '../../core/shared/fs.js';
10
11
  // ---------------------------------------------------------------------------
11
12
  // File content generators
12
13
  // ---------------------------------------------------------------------------
@@ -188,13 +189,4 @@ async function injectRulesBlock(filePath, version) {
188
189
  // ---------------------------------------------------------------------------
189
190
  // Internal helpers
190
191
  // ---------------------------------------------------------------------------
191
- async function fileExists(filePath) {
192
- try {
193
- await access(filePath);
194
- return true;
195
- }
196
- catch {
197
- return false;
198
- }
199
- }
200
192
  //# sourceMappingURL=config-scaffold.js.map
@@ -2,6 +2,7 @@ import { createHash } from 'node:crypto';
2
2
  import { AsyncLocalStorage } from 'node:async_hooks';
3
3
  import { isAbsolute, resolve } from 'node:path';
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 { LockBusyError, withSpecLock } from '../engine/safety/cross-process-lock.js';
6
7
  const heldApprovalLocks = new AsyncLocalStorage();
7
8
  function approvalLockId(specId) {
@@ -1,6 +1,7 @@
1
1
  // storage/auto-promoter-config-store.ts — Persists auto-promoter config (SPEC-391)
2
2
  // Layout: data/projects/{hash}/config/auto-promoter.json
3
3
  import { readJson, writeJson, projectDataDir, hashProjectPath } from './base-store.js';
4
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
4
5
  import { getDefaultConfig } from '../engine/auto-promoter.js';
5
6
  function configFile(projectId) {
6
7
  return `${projectDataDir(projectId)}/config/auto-promoter.json`;
@@ -1,6 +1,7 @@
1
1
  // storage/autopilot-log-store.ts — SPEC-772: Autopilot cascade log persistence
2
2
  import { readFile, mkdir } 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 { atomicWriteFile } from '../engine/safety/atomic-write-file.js';
5
6
  import { reportClassifiedDegradation } from '../errors/classified-degradation.js';
6
7
  import { projectDataDir } from './base-store.js';
@@ -3,6 +3,7 @@
3
3
  import { readFile, mkdir } from 'node:fs/promises';
4
4
  import { readFileSync } from 'node:fs';
5
5
  import { dirname, isAbsolute, join, 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 { writeJsonSafe } from '../engine/safety/atomic-writer.js';
7
8
  import { resolveStorageLayout } from './storage-layout.js';
8
9
  import { reportClassifiedDegradation } from '../errors/classified-degradation.js';
@@ -3,6 +3,7 @@ import { readdir, mkdir } from 'node:fs/promises';
3
3
  import { join } from 'node:path';
4
4
  import { readJson, writeJson, projectDataDir } from './base-store.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 { writeJsonSafe } from '../engine/safety/atomic-writer.js';
7
8
  // ---------------------------------------------------------------------------
8
9
  // Helpers
@@ -1,5 +1,6 @@
1
1
  // storage/feedback-remote.ts — Configured remote feedback relay (fire-and-forget)
2
2
  // No PII is ever sent: no project paths, no user names, no emails.
3
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
3
4
  import { networkFetch, withNetworkConsent } from '../engine/network-policy.js';
4
5
  function resolveConfiguredFeedbackEndpoint(endpoint) {
5
6
  const configured = endpoint ?? process.env.PLANU_FEEDBACK_ENDPOINT;
@@ -7,6 +7,7 @@
7
7
  import { createHash, randomUUID } from 'node:crypto';
8
8
  import { appendFile, readFile, mkdir } from 'node:fs/promises';
9
9
  import { dirname, join } from 'node:path';
10
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
10
11
  import { fastAppendGapEntry, fastVerifyGapsChain } from '../engine/core-bridge.js';
11
12
  import { projectDataDir } from './base-store.js';
12
13
  import { reportClassifiedDegradation } from '../errors/classified-degradation.js';
@@ -2,6 +2,7 @@
2
2
  // Persistence file: data/global/registered-projects.json
3
3
  import { readJson, writeJson, globalDataDir, hashProjectPath } 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 { isEphemeralProject } from '../engine/data-projects-gc/pattern-matcher.js';
6
7
  import { reportClassifiedDegradation } from '../errors/classified-degradation.js';
7
8
  import { readFile } from 'node:fs/promises';
@@ -1,5 +1,6 @@
1
1
  import { readJson, writeJson, globalDataDir } from './base-store.js';
2
2
  import { withFileLock } from './file-mutex.js';
3
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
3
4
  import { applyLearnedLimit, markVerified } from '../engine/registry-extender.js';
4
5
  import { readFileSync } from 'node:fs';
5
6
  import { reportClassifiedDegradation } from '../errors/classified-degradation.js';
@@ -1,6 +1,8 @@
1
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
1
2
  import { mergeContext } from '../../engine/context-merger.js';
2
3
  import { readJson, writeJson, projectDataDir } from '../base-store.js';
3
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
4
6
  import { addMetricsToState } from '../../engine/calibrator.js';
5
7
  import { getKnowledge, knowledgeFile } from './knowledge.js';
6
8
  // --- File paths ---
@@ -3,7 +3,9 @@ import { copyFile, lstat, mkdir, readFile, readdir, rename, rm, writeFile } from
3
3
  import { createHash, randomUUID } from 'node:crypto';
4
4
  import { homedir, tmpdir } from 'node:os';
5
5
  import { basename, dirname, isAbsolute, join, parse, relative, resolve, sep } 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 as acquireFileMutex, releaseLock as releaseFileMutex, } from '../../engine/safety/file-mutex.js';
8
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
7
9
  import { assertNoObsoleteFileLock } from '../../engine/safety/obsolete-lock-guard.js';
8
10
  function sha256(value) {
9
11
  return createHash('sha256').update(value).digest('hex');
@@ -174,10 +176,17 @@ async function readJournal(path, expected) {
174
176
  throw error;
175
177
  }
176
178
  }
179
+ function isTerminalPhaseValue(value) {
180
+ return value === 'completed';
181
+ }
182
+ async function quarantineStaleJournal(journalPath) {
183
+ const quarantinePath = journalPath.replace(/\.journal\.json$/, `.journal.stale-${String(Date.now())}.json`);
184
+ await rename(journalPath, quarantinePath);
185
+ }
177
186
  async function retireCompletedJournalForNewSources(journalPath, expected) {
178
- let parsed;
187
+ let rawText;
179
188
  try {
180
- parsed = JSON.parse(await readFile(journalPath, 'utf8'));
189
+ rawText = await readFile(journalPath, 'utf8');
181
190
  }
182
191
  catch (error) {
183
192
  if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
@@ -185,32 +194,47 @@ async function retireCompletedJournalForNewSources(journalPath, expected) {
185
194
  }
186
195
  throw error;
187
196
  }
197
+ const parsed = JSON.parse(rawText);
188
198
  if (!parsed || typeof parsed !== 'object' || !('legacyRoots' in parsed)) {
189
199
  throw new Error('[Planu] Invalid or unsafe migration journal');
190
200
  }
191
- const rawRoots = parsed.legacyRoots;
201
+ const record = parsed;
202
+ const rawRoots = record.legacyRoots;
192
203
  if (!Array.isArray(rawRoots) || !rawRoots.every((root) => typeof root === 'string')) {
193
204
  throw new Error('[Planu] Invalid or unsafe migration journal');
194
205
  }
195
- if (JSON.stringify(rawRoots) === JSON.stringify(expected.legacyRoots)) {
196
- return;
206
+ const rootsChanged = JSON.stringify(rawRoots) !== JSON.stringify(expected.legacyRoots);
207
+ const previousRoots = rootsChanged
208
+ ? rawRoots.map((root) => assertAbsolute(root, 'journal legacyRoot'))
209
+ : [...expected.legacyRoots];
210
+ if (rootsChanged) {
211
+ for (const root of previousRoots) {
212
+ assertNarrowLegacyRoot(root);
213
+ if (isInside(root, expected.destinationRoot) || isInside(expected.destinationRoot, root)) {
214
+ throw new Error('[Planu] Invalid or unsafe migration journal');
215
+ }
216
+ }
197
217
  }
198
- const previousRoots = rawRoots.map((root) => assertAbsolute(root, 'journal legacyRoot'));
199
- for (const root of previousRoots) {
200
- assertNarrowLegacyRoot(root);
201
- if (isInside(root, expected.destinationRoot) || isInside(expected.destinationRoot, root)) {
202
- throw new Error('[Planu] Invalid or unsafe migration journal');
218
+ try {
219
+ const previous = validateJournal(parsed, { ...expected, legacyRoots: previousRoots });
220
+ if (!rootsChanged) {
221
+ return;
222
+ }
223
+ if (previous.phase !== 'completed') {
224
+ throw new Error('[Planu] Active migration journal does not match requested roots');
203
225
  }
226
+ // A completed destination remains live and may legitimately receive newer
227
+ // canonical records. Re-inventory its real directory instead of requiring
228
+ // the historical generation digest to remain frozen forever.
229
+ await inventoryStorageRoot(expected.destinationRoot);
230
+ await rm(journalPath, { force: true });
204
231
  }
205
- const previous = validateJournal(parsed, { ...expected, legacyRoots: previousRoots });
206
- if (previous.phase !== 'completed') {
207
- throw new Error('[Planu] Active migration journal does not match requested roots');
232
+ catch (error) {
233
+ if (!isTerminalPhaseValue(record.phase)) {
234
+ throw error;
235
+ }
236
+ await quarantineStaleJournal(journalPath);
208
237
  }
209
- // A completed destination remains live and may legitimately receive newer
210
- // canonical records. Re-inventory its real directory instead of requiring
211
- // the historical generation digest to remain frozen forever.
212
- await inventoryStorageRoot(expected.destinationRoot);
213
- await rm(journalPath, { force: true });
214
238
  }
215
239
  function recordTimestamp(value) {
216
240
  if (!value || typeof value !== 'object') {
@@ -1,6 +1,7 @@
1
1
  // storage/project-drift-store.ts — SPEC-666: Read/write drift signals from .planu/drift-commits.ndjson
2
2
  import { readFile, writeFile, unlink, mkdir } from 'node:fs/promises';
3
3
  import { 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 { analyzeCommitRecord } from '../engine/project-drift-detector.js';
5
6
  import { hashProjectPath, projectDataDir } from './base-store.js';
6
7
  import { reportClassifiedDegradation } from '../errors/classified-degradation.js';
@@ -3,6 +3,7 @@ import { lstat, mkdir, open, readFile, realpath, rename, rm, stat } from 'node:f
3
3
  import { basename, dirname, isAbsolute, join, normalize, relative, resolve, sep } from 'node:path';
4
4
  import { resolveStorageLayout } from './storage-layout.js';
5
5
  import { getCanonicalRoot, readLogicalProjectId } from './global-projects-store.js';
6
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
6
7
  import { isEphemeralProject } from '../engine/data-projects-gc/pattern-matcher.js';
7
8
  const IDENTITY_VERSION = 1;
8
9
  const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
@@ -2,27 +2,11 @@
2
2
  // Resolves a project from its data directory OR from disk fingerprints (planu/ + specs/).
3
3
  // Used by planu_status, challenge_spec, and snapshot_spec_hashes to avoid "Project not found"
4
4
  // when the knowledge entry is missing but the project clearly exists on disk.
5
- import { access } from 'node:fs/promises';
6
5
  import { join } from 'node:path';
7
6
  import { getKnowledge, saveKnowledge } from './knowledge-store/knowledge.js';
8
7
  import { hashProjectPath, projectDataDir } from './base-store.js';
9
8
  import { reportClassifiedDegradation } from '../errors/classified-degradation.js';
10
- /**
11
- * Check whether a file/directory path exists on disk (no-throw helper).
12
- */
13
- async function pathExists(p) {
14
- try {
15
- await access(p);
16
- return true;
17
- }
18
- catch (error) {
19
- if (error.code === 'ENOENT' ||
20
- (error instanceof Error && error.message === 'ENOENT')) {
21
- return false;
22
- }
23
- throw error;
24
- }
25
- }
9
+ import { pathExistsStrict as pathExists } from '../core/shared/fs.js';
26
10
  /**
27
11
  * Resolve a project from its projectPath.
28
12
  *
@@ -1,4 +1,6 @@
1
+ import { DURABLE_JOB_STATES, type DurableJobRecord, type DurableJobState } from '../types/durable-job.js';
1
2
  import { type ValidationReceiptCheckpointLimits } from '../types/durable-validation.js';
3
+ export { DURABLE_JOB_STATES, type DurableJobRecord, type DurableJobState };
2
4
  /** Count-only process diagnostic for deterministic resource lifecycle tests. */
3
5
  export declare function getRuntimeDatabaseDiagnosticsForTests(): {
4
6
  readonly openConnections: number;
@@ -50,26 +52,6 @@ export interface RuntimeProjectBundle {
50
52
  readonly outbox: readonly Record<string, unknown>[];
51
53
  readonly audit: readonly Record<string, unknown>[];
52
54
  }
53
- export declare const DURABLE_JOB_STATES: readonly ['accepted', 'running', 'checkpointed', 'cancelled', 'failed', 'dead-letter', 'completed'];
54
- export type DurableJobState = (typeof DURABLE_JOB_STATES)[number];
55
- export interface DurableJobRecord {
56
- readonly id: string;
57
- readonly projectId: string;
58
- readonly workspaceId: string;
59
- readonly state: DurableJobState;
60
- readonly payload: unknown;
61
- readonly checkpoint?: unknown;
62
- readonly result?: unknown;
63
- readonly error?: string;
64
- readonly attempts: number;
65
- readonly maxAttempts: number;
66
- readonly cancelRequested: boolean;
67
- readonly leaseOwner?: string;
68
- readonly leaseExpiresAt?: string;
69
- readonly fencingToken: number;
70
- readonly createdAt: string;
71
- readonly updatedAt: string;
72
- }
73
55
  export interface JobLeaseInput {
74
56
  readonly id: string;
75
57
  readonly projectId: string;
@@ -2,7 +2,9 @@
2
2
  import { mkdirSync } from 'node:fs';
3
3
  import { dirname, isAbsolute, resolve } from 'node:path';
4
4
  import { DatabaseSync } from 'node:sqlite';
5
+ import { DURABLE_JOB_STATES, } from '../types/durable-job.js';
5
6
  import { parseValidationReceiptPendingCheckpoint, } from '../types/durable-validation.js';
7
+ export { DURABLE_JOB_STATES };
6
8
  const CURRENT_SCHEMA_VERSION = 4;
7
9
  const DEFAULT_BUSY_TIMEOUT_MS = 5_000;
8
10
  const DEFAULT_MAX_CONNECTIONS = 4;
@@ -47,15 +49,6 @@ export function getRuntimeDatabaseDiagnosticsForTests() {
47
49
  }
48
50
  return { openConnections: count, integrityCheckedOpens, integrityBypassedOpens };
49
51
  }
50
- export const DURABLE_JOB_STATES = [
51
- 'accepted',
52
- 'running',
53
- 'checkpointed',
54
- 'cancelled',
55
- 'failed',
56
- 'dead-letter',
57
- 'completed',
58
- ];
59
52
  export class RuntimeDatabaseCorruptionError extends Error {
60
53
  databasePath;
61
54
  detail;
@@ -6,6 +6,7 @@
6
6
  import { createHash } from 'node:crypto';
7
7
  import { readJson, writeJson, projectDataDir } from './base-store.js';
8
8
  import { withFileLock } from './file-mutex.js';
9
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
9
10
  import { TFIDFEngine, TFIDF_SCHEMA_VERSION, tokenize } from '../engine/vector-store/tfidf.js';
10
11
  function hashContent(content) {
11
12
  return createHash('sha256').update(content).digest('hex');
@@ -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
  */
@@ -3,13 +3,18 @@ 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';
9
- import { isAbsolute } from 'node:path';
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
10
14
  import { acquireLock, releaseLock } from '../engine/safety/cross-process-lock.js';
11
15
  import { resolvePortableSpecPath, toPortableSpecPath, PortablePathError, } from './project-identity.js';
12
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
13
18
  import { hashEntry } from '../engine/audit-trail/hasher.js';
14
19
  // ---------------------------------------------------------------------------
15
20
  // SPEC-720: Guard error — direct status write forbidden
@@ -201,6 +206,21 @@ async function saveAll(projectId, specs) {
201
206
  export function invalidateSpecsCache(projectId) {
202
207
  specsCache.delete(projectId);
203
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
+ }
204
224
  // --- public API ---
205
225
  /**
206
226
  * List every spec for a project.
@@ -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 = [];