@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,7 +1,9 @@
1
1
  import { suggestArchivableSpecs, archiveSpecToPath } from '../context-manager.js';
2
2
  import { writeCheckpoint } from '../session/checkpoint-writer.js';
3
3
  import { sessionTracker } from '../session/session-tracker.js';
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, projectDataDir } from '../../storage/base-store.js';
6
8
  import { emitAutopilotEvent } from '../autopilot/event-bus.js';
7
9
  const WARN_THRESHOLD = 80;
@@ -1,8 +1,9 @@
1
1
  import { technologyValue } from '../technology-registry.js';
2
2
  // engine/convention-scanner/convention-parser.ts — SPEC-192
3
3
  // Parses CLAUDE.md and .claude/rules/*.md to extract ConventionRule[]
4
- import { readFileSync, readdirSync } from 'node:fs';
4
+ import { readdirSync } from 'node:fs';
5
5
  import { join, basename } from 'node:path';
6
+ import { readFileSafeSync as readFileSafe } from '../../core/shared/fs.js';
6
7
  // ── keyword maps ──────────────────────────────────────────────────────────────
7
8
  const NAMING_KEYWORDS = [
8
9
  'english',
@@ -68,14 +69,6 @@ const CODE_QUALITY_KEYWORDS = [
68
69
  'type assertion',
69
70
  ];
70
71
  // ── helpers ───────────────────────────────────────────────────────────────────
71
- function readFileSafe(path) {
72
- try {
73
- return readFileSync(path, 'utf-8');
74
- }
75
- catch {
76
- return '';
77
- }
78
- }
79
72
  function listRulesFiles(projectPath) {
80
73
  const rulesDir = join(projectPath, '.claude', 'rules');
81
74
  try {
@@ -1,4 +1,5 @@
1
1
  // engine/cost-guardrails.ts — Cost Guardrails computation logic (SPEC-393)
2
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
2
3
  import { getBudget } from '../storage/budget-store.js';
3
4
  /**
4
5
  * Compute the current budget status for a spec.
@@ -1,6 +1,7 @@
1
1
  // engine/cost-tracking/ledger.ts — Per-operation cost ledger (SPEC-475)
2
2
  import { appendFile, readFile, mkdir } from 'node:fs/promises';
3
3
  import { join, dirname } from 'node:path';
4
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
4
5
  import { hashProjectPath, projectDataDir } from '../../storage/base-store.js';
5
6
  // ---------------------------------------------------------------------------
6
7
  // Model pricing (USD per token)
@@ -12,7 +12,7 @@ export function normalizeCriterionText(value) {
12
12
  .normalize('NFKC')
13
13
  .replace(/^[-*+]\s*\[[ xX]\]\s*/, '')
14
14
  .replace(CRITERION_ID_PREFIX, '')
15
- .replace(/[\p{P}]+/gu, ' ')
15
+ .replace(/[\p{P}\x60]+/gu, ' ')
16
16
  .replace(/[\s\u00a0]+/g, ' ')
17
17
  .trim()
18
18
  .toLowerCase();
@@ -2,6 +2,7 @@
2
2
  // for the dashboard. All I/O is synchronous-style via fs promises.
3
3
  import { readFile, readdir, stat } from 'node:fs/promises';
4
4
  import { join } from 'node:path';
5
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
5
6
  import { resolveStorageLayout } from '../../storage/storage-layout.js';
6
7
  import { computeDashboardMetrics, computeHealthScore } from './kanban-logic.js';
7
8
  import { extractSectionBody } from '../spec-format/read-technical-section.js';
@@ -1,7 +1,9 @@
1
1
  // engine/dashboard/drift-score.ts — Planu drift score computation (SPEC-748)
2
2
  // Computes a 0-100 score reflecting drift between done specs and codebase.
3
3
  // Formula: (driftReviewCount / doneSpecsCount) * 100, rounded to 1 decimal.
4
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
4
5
  import { readJson, hashProjectPath } from '../../storage/base-store.js';
6
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
5
7
  import { listSpecs } from '../../storage/spec-store.js';
6
8
  import { join } from 'node:path';
7
9
  // ---------------------------------------------------------------------------
@@ -1,4 +1,6 @@
1
- import type { SpecStatusUpdateResult } from '../../types/index.js';
1
+ import type { SpecStatusUpdateResult, UpdateStatusHandler } from '../../types/index.js';
2
+ /** Wired by the tools layer at startup so this engine module never imports tools/. */
3
+ export declare function registerUpdateStatusHandler(handler: UpdateStatusHandler): void;
2
4
  /** Update a spec's status after validating the transition.
3
5
  *
4
6
  * SPEC-720: Routes through handleUpdateStatus so all gates (DoD/validate/QA) run.
@@ -1,7 +1,11 @@
1
1
  // engine/dashboard/spec-updater.ts — PATCH handler logic for spec status updates (SPEC-122)
2
2
  // SPEC-720: All status writes now route through handleUpdateStatus (full gates).
3
3
  import { isValidStatus, buildUpdateResult } from './kanban-logic.js';
4
- import { handleUpdateStatus } from '../../tools/update-status/index.js';
4
+ let updateStatusHandler;
5
+ /** Wired by the tools layer at startup so this engine module never imports tools/. */
6
+ export function registerUpdateStatusHandler(handler) {
7
+ updateStatusHandler = handler;
8
+ }
5
9
  /** Update a spec's status after validating the transition.
6
10
  *
7
11
  * SPEC-720: Routes through handleUpdateStatus so all gates (DoD/validate/QA) run.
@@ -19,8 +23,11 @@ export async function updateSpecStatus(projectId, specId, newStatus, projectPath
19
23
  // Fall back to cwd which is where the server runs.
20
24
  return process.cwd();
21
25
  })();
26
+ if (!updateStatusHandler) {
27
+ return buildUpdateResult(false, specId, newStatus, 'updateSpecStatus: no handler registered — call registerUpdateStatusHandler at startup');
28
+ }
22
29
  try {
23
- const result = await handleUpdateStatus({
30
+ const result = await updateStatusHandler({
24
31
  specId,
25
32
  status: newStatus,
26
33
  projectId,
@@ -1,5 +1,5 @@
1
- /** Escape HTML special characters to prevent XSS */
2
- export declare function escapeHtml(str: string): string;
1
+ import { escapeHtml } from '../../core/shared/strings.js';
2
+ export { escapeHtml };
3
3
  /** Minimal Markdown → HTML converter (headings, bold, lists, code blocks) */
4
4
  export declare function markdownToHtml(md: string): string;
5
5
  /** Base CSS for the dark theme dashboard (assembled from subfunctions) */
@@ -1,14 +1,7 @@
1
1
  // engine/dashboard/templates-layout.ts — Base layout and shared HTML helpers.
2
2
  // Dark theme, embedded CSS and JS. No external dependencies.
3
- /** Escape HTML special characters to prevent XSS */
4
- export function escapeHtml(str) {
5
- return str
6
- .replace(/&/g, '&')
7
- .replace(/</g, '&lt;')
8
- .replace(/>/g, '&gt;')
9
- .replace(/"/g, '&quot;')
10
- .replace(/'/g, '&#39;');
11
- }
3
+ import { escapeHtml } from '../../core/shared/strings.js';
4
+ export { escapeHtml };
12
5
  /** Minimal Markdown → HTML converter (headings, bold, lists, code blocks) */
13
6
  export function markdownToHtml(md) {
14
7
  const lines = md.split('\n');
@@ -1,13 +1,11 @@
1
1
  // engine/data-projects-gc/gc-runner.ts — SPEC-581
2
2
  // Orchestrates scan + optional deletion of data/projects/ garbage.
3
- import { access, mkdir, readFile, readdir, rename, rm } from 'node:fs/promises';
3
+ import { mkdir, readFile, readdir, rename, rm } from 'node:fs/promises';
4
4
  import { basename, dirname, isAbsolute, join, resolve } from 'node:path';
5
5
  import { scanProjectDirs } from './scanner.js';
6
+ import { pathExists } from '../../core/shared/fs.js';
6
7
  import { atomicWriteFile } from '../safety/atomic-write-file.js';
7
8
  const DEFAULT_TRASH_TTL_DAYS = 30;
8
- async function pathExists(path) {
9
- return access(path).then(() => true, () => false);
10
- }
11
9
  function parseTrashMetadata(value) {
12
10
  if (!value || typeof value !== 'object') {
13
11
  throw new Error('[Planu] Invalid GC trash metadata');
@@ -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 { readJson, writeJson, projectDataDir } from '../../storage/base-store.js';
2
3
  import { randomUUID } from 'node:crypto';
3
4
  function auditFile(projectId) {
@@ -1,11 +1,17 @@
1
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
1
2
  import { writeJson, projectDataDir } from '../../storage/base-store.js';
3
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
2
4
  import { listSpecs, getSpec, deleteSpec } from '../../storage/spec-store.js';
5
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
3
6
  import * as patternStore from '../../storage/pattern-store.js';
7
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
4
8
  import * as decisionStore from '../../storage/decision-store.js';
9
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
5
10
  import { moveToTrash, moveDataToTrash, countFiles, pathExists } from '../../storage/trash-store.js';
6
11
  import { appendAuditEntry } from './audit-logger.js';
7
12
  import { rm, mkdir, rename } from 'node:fs/promises';
8
13
  import { join } from 'node:path';
14
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
9
15
  import { resolveStorageLayout } from '../../storage/storage-layout.js';
10
16
  /**
11
17
  * Check if any specs reference the given specId as a dependency.
@@ -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 { loadManifest, restoreFromTrash, purgeTrashItem, purgeAllTrash, } from '../../storage/trash-store.js';
2
3
  import { appendAuditEntry } from './audit-logger.js';
3
4
  /**
@@ -1,18 +1,10 @@
1
1
  import { technologyValue } from './technology-registry.js';
2
2
  // engine/desktop-detector.ts — SPEC-014b desktop advanced detection
3
3
  // Detects IPC patterns, Tauri commands, .NET UI frameworks, macOS app types, Linux native frameworks.
4
- import { readFile } from 'node:fs/promises';
5
4
  import { join } from 'node:path';
6
5
  import { glob } from 'glob';
6
+ import { readFileOrNull as readFileSafe } from '../core/shared/fs.js';
7
7
  // --- Shared utilities ---
8
- async function readFileSafe(filePath) {
9
- try {
10
- return await readFile(filePath, 'utf-8');
11
- }
12
- catch {
13
- return null;
14
- }
15
- }
16
8
  async function globFirst(pattern, cwd) {
17
9
  try {
18
10
  const matches = await glob(pattern, { cwd, nodir: true, maxDepth: 5, dot: false });
@@ -1,6 +1,7 @@
1
1
  import type { StackSignatures, ArchPatternsFile } from '../types/index.js';
2
+ import { fileExistsIn as fileExists } from '../core/shared/fs.js';
3
+ export { fileExists };
2
4
  declare const IGNORE_DIRS: string[];
3
- export declare function fileExists(basePath: string, relativePath: string): Promise<boolean>;
4
5
  export declare function hasAnyFile(basePath: string, patterns: string[]): Promise<boolean>;
5
6
  export declare function collectDependencies(projectPath: string): Promise<Set<string>>;
6
7
  export declare function loadStackSignatures(): Promise<StackSignatures>;
@@ -1,7 +1,9 @@
1
1
  // Planu — Shared detection utilities for project analysis
2
- import { readFile, access } from 'node:fs/promises';
2
+ import { readFile } from 'node:fs/promises';
3
3
  import { join } from 'node:path';
4
4
  import { glob } from 'glob';
5
+ import { fileExistsIn as fileExists } from '../core/shared/fs.js';
6
+ export { fileExists };
5
7
  const IGNORE_DIRS = [
6
8
  'node_modules/**',
7
9
  'dist/**',
@@ -14,15 +16,6 @@ const IGNORE_DIRS = [
14
16
  'target/**',
15
17
  'coverage/**',
16
18
  ];
17
- export async function fileExists(basePath, relativePath) {
18
- try {
19
- await access(join(basePath, relativePath));
20
- return true;
21
- }
22
- catch {
23
- return false;
24
- }
25
- }
26
19
  export async function hasAnyFile(basePath, patterns) {
27
20
  for (const pattern of patterns) {
28
21
  try {
@@ -1,6 +1,7 @@
1
1
  import type { PackageJsonDeps } from '../../../types/index.js';
2
+ import { fileExistsByRead } from '../../../core/shared/fs.js';
3
+ export { readFileSafe as readFileContent } from '../../../core/shared/fs.js';
4
+ export { fileExistsByRead as fileExists };
2
5
  export declare function readPackageJson(projectPath: string): Promise<PackageJsonDeps>;
3
6
  export declare function getAllDeps(pkg: PackageJsonDeps): Set<string>;
4
- export declare function fileExists(filePath: string): Promise<boolean>;
5
- export declare function readFileContent(filePath: string): Promise<string>;
6
7
  //# sourceMappingURL=helpers.d.ts.map
@@ -2,6 +2,9 @@
2
2
  // Shared file I/O helpers for advanced framework detection.
3
3
  import { readFile } from 'node:fs/promises';
4
4
  import { join } from 'node:path';
5
+ import { fileExistsByRead } from '../../../core/shared/fs.js';
6
+ export { readFileSafe as readFileContent } from '../../../core/shared/fs.js';
7
+ export { fileExistsByRead as fileExists };
5
8
  export async function readPackageJson(projectPath) {
6
9
  try {
7
10
  const content = await readFile(join(projectPath, 'package.json'), 'utf-8');
@@ -17,21 +20,4 @@ export function getAllDeps(pkg) {
17
20
  ...Object.keys(pkg.devDependencies ?? {}),
18
21
  ]);
19
22
  }
20
- export async function fileExists(filePath) {
21
- try {
22
- await readFile(filePath, 'utf-8');
23
- return true;
24
- }
25
- catch {
26
- return false;
27
- }
28
- }
29
- export async function readFileContent(filePath) {
30
- try {
31
- return await readFile(filePath, 'utf-8');
32
- }
33
- catch {
34
- return '';
35
- }
36
- }
37
23
  //# sourceMappingURL=helpers.js.map
@@ -1,4 +1,5 @@
1
1
  import { technologyValue } from '../technology-registry.js';
2
+ import { fileExistsByRead } from '../../core/shared/fs.js';
2
3
  // engine/detectors/cicd-detector.ts — CI/CD platform detection (SPEC-026a)
3
4
  // Hierarchical detection: GitHub Actions > GitLab CI > CircleCI > Buildkite >
4
5
  // Azure DevOps > Jenkins > Drone > Woodpecker > Tekton > rest
@@ -112,7 +113,7 @@ async function findSignalFiles(projectPath, signal) {
112
113
  const found = [];
113
114
  // Check explicit paths
114
115
  for (const p of signal.paths) {
115
- const exists = await fileExists(join(projectPath, p));
116
+ const exists = await fileExistsByRead(join(projectPath, p));
116
117
  if (exists) {
117
118
  found.push(p);
118
119
  }
@@ -131,15 +132,6 @@ async function findSignalFiles(projectPath, signal) {
131
132
  }
132
133
  return found;
133
134
  }
134
- async function fileExists(filePath) {
135
- try {
136
- await readFile(filePath, 'utf-8');
137
- return true;
138
- }
139
- catch {
140
- return false;
141
- }
142
- }
143
135
  async function analyzeCiCdStages(projectPath, configFile) {
144
136
  try {
145
137
  const content = await readFile(join(projectPath, configFile), 'utf-8');
@@ -2,6 +2,7 @@
2
2
  // Detects CSS frameworks from package.json dependencies, config files, and import signals.
3
3
  import { readFile } from 'node:fs/promises';
4
4
  import { join } from 'node:path';
5
+ import { fileExistsByRead } from '../../core/shared/fs.js';
5
6
  // === Framework signal registry ===
6
7
  const FRAMEWORK_SIGNALS = {
7
8
  tailwind: {
@@ -117,7 +118,7 @@ async function checkConfigFiles(projectPath, scores, signals) {
117
118
  for (const fw of Object.keys(FRAMEWORK_SIGNALS)) {
118
119
  const frameworkSignals = FRAMEWORK_SIGNALS[fw];
119
120
  for (const configFile of frameworkSignals.configFiles) {
120
- const exists = await fileExists(join(projectPath, configFile));
121
+ const exists = await fileExistsByRead(join(projectPath, configFile));
121
122
  if (exists) {
122
123
  addScore(scores, fw, 2); // config file is medium-high confidence
123
124
  /* v8 ignore next 1 */ // signals[fw] is always initialized in detectCSSFramework
@@ -126,15 +127,6 @@ async function checkConfigFiles(projectPath, scores, signals) {
126
127
  }
127
128
  }
128
129
  }
129
- async function fileExists(filePath) {
130
- try {
131
- await readFile(filePath, 'utf-8');
132
- return true;
133
- }
134
- catch {
135
- return false;
136
- }
137
- }
138
130
  /** Map a numeric score to a confidence label. All real detections yield score ≥ 2. */
139
131
  function scoreToConfidence(score) {
140
132
  if (score >= 3) {
@@ -1,7 +1,7 @@
1
1
  import { technologyValue } from '../technology-registry.js';
2
+ import { fileExistsByRead } from '../../core/shared/fs.js';
2
3
  // engine/detectors/deployment-detector.ts — Deployment config detection (SPEC-026a)
3
4
  // Detects deployment targets, IaC tools, container orchestration, and cloud configs.
4
- import { readFile } from 'node:fs/promises';
5
5
  import { join } from 'node:path';
6
6
  import { glob } from 'glob';
7
7
  // === Detection signals ===
@@ -123,7 +123,7 @@ export async function detectDeployment(projectPath) {
123
123
  async function findDeploymentFiles(projectPath, signal) {
124
124
  const found = [];
125
125
  for (const p of signal.paths) {
126
- if (await fileExists(join(projectPath, p))) {
126
+ if (await fileExistsByRead(join(projectPath, p))) {
127
127
  found.push(p);
128
128
  }
129
129
  }
@@ -142,7 +142,7 @@ async function findDeploymentFiles(projectPath, signal) {
142
142
  }
143
143
  async function hasAnyPaths(projectPath, paths) {
144
144
  for (const p of paths) {
145
- if (await fileExists(join(projectPath, p))) {
145
+ if (await fileExistsByRead(join(projectPath, p))) {
146
146
  return true;
147
147
  }
148
148
  }
@@ -157,13 +157,4 @@ async function hasGlobMatches(projectPath, pattern) {
157
157
  return false;
158
158
  }
159
159
  }
160
- async function fileExists(filePath) {
161
- try {
162
- await readFile(filePath, 'utf-8');
163
- return true;
164
- }
165
- catch {
166
- return false;
167
- }
168
- }
169
160
  //# sourceMappingURL=deployment-detector.js.map
@@ -1,4 +1,5 @@
1
1
  import { technologyValue } from '../technology-registry.js';
2
+ import { fileExistsByRead } from '../../core/shared/fs.js';
2
3
  // engine/detectors/frontend-perf-detector.ts — SPEC-057
3
4
  // Detects frontend performance budget configs, web vitals dependency,
4
5
  // SSR/SSG frameworks, design system tooling, and E2E test frameworks.
@@ -63,15 +64,6 @@ const STORYBOOK_MARKERS = [
63
64
  // ---------------------------------------------------------------------------
64
65
  // Helpers
65
66
  // ---------------------------------------------------------------------------
66
- async function fileExists(filePath) {
67
- try {
68
- await readFile(filePath, 'utf-8');
69
- return true;
70
- }
71
- catch {
72
- return false;
73
- }
74
- }
75
67
  async function collectDeps(projectPath) {
76
68
  const deps = new Set();
77
69
  try {
@@ -95,7 +87,7 @@ async function collectDeps(projectPath) {
95
87
  async function detectPerformanceBudget(projectPath, deps) {
96
88
  let hasPerformanceBudget = false;
97
89
  for (const file of PERF_BUDGET_FILES) {
98
- if (await fileExists(join(projectPath, file))) {
90
+ if (await fileExistsByRead(join(projectPath, file))) {
99
91
  hasPerformanceBudget = true;
100
92
  break;
101
93
  }
@@ -3,6 +3,7 @@
3
3
  import { readFile } from 'node:fs/promises';
4
4
  import { join } from 'node:path';
5
5
  import { glob } from 'glob';
6
+ import { fileExistsByRead } from '../../core/shared/fs.js';
6
7
  // === GitOps detection signals ===
7
8
  const GITOPS_SIGNALS = [
8
9
  {
@@ -90,7 +91,7 @@ async function findGitOpsFiles(projectPath, signal) {
90
91
  const found = [];
91
92
  // Check explicit paths
92
93
  for (const p of signal.paths) {
93
- if (await fileExists(join(projectPath, p))) {
94
+ if (await fileExistsByRead(join(projectPath, p))) {
94
95
  found.push(p);
95
96
  }
96
97
  }
@@ -122,7 +123,7 @@ async function findPolicyFiles(projectPath, signal) {
122
123
  const found = [];
123
124
  // Check explicit paths
124
125
  for (const p of signal.paths) {
125
- if (await fileExists(join(projectPath, p))) {
126
+ if (await fileExistsByRead(join(projectPath, p))) {
126
127
  found.push(p);
127
128
  }
128
129
  }
@@ -158,13 +159,4 @@ async function fileMatchesContent(projectPath, filePath, patterns) {
158
159
  return false;
159
160
  }
160
161
  }
161
- async function fileExists(filePath) {
162
- try {
163
- await readFile(filePath, 'utf-8');
164
- return true;
165
- }
166
- catch {
167
- return false;
168
- }
169
- }
170
162
  //# sourceMappingURL=gitops-detector.js.map
@@ -3,6 +3,7 @@
3
3
  import { readFile } from 'node:fs/promises';
4
4
  import { join } from 'node:path';
5
5
  import { glob } from 'glob';
6
+ import { escapeRegex } from '../../core/shared/strings.js';
6
7
  // === Detection signals ===
7
8
  const IDP_SIGNALS = [
8
9
  {
@@ -120,7 +121,4 @@ function extractYamlField(content, fieldPath) {
120
121
  // Remove surrounding quotes if present
121
122
  return value.replace(/^['"]|['"]$/g, '');
122
123
  }
123
- function escapeRegex(str) {
124
- return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
125
- }
126
124
  //# sourceMappingURL=idp-detector.js.map
@@ -3,6 +3,7 @@
3
3
  import { readFile } from 'node:fs/promises';
4
4
  import { join } from 'node:path';
5
5
  import { glob } from 'glob';
6
+ import { fileExistsByRead } from '../../core/shared/fs.js';
6
7
  // === Detection signals ===
7
8
  /** Explicit config file paths that indicate K3s is in use. */
8
9
  const K3S_PATHS = [
@@ -29,13 +30,13 @@ const K3S_KUBECONFIG_MARKER = 'k3s';
29
30
  export async function detectK3s(projectPath) {
30
31
  // Check explicit config file paths
31
32
  for (const p of K3S_PATHS) {
32
- if (await fileExists(join(projectPath, p))) {
33
+ if (await fileExistsByRead(join(projectPath, p))) {
33
34
  return true;
34
35
  }
35
36
  }
36
37
  // Check K3s directories (presence of directory indicates K3s usage)
37
38
  for (const dir of K3S_DIRS) {
38
- if (await fileExists(join(projectPath, dir))) {
39
+ if (await fileExistsByRead(join(projectPath, dir))) {
39
40
  return true;
40
41
  }
41
42
  }
@@ -64,15 +65,6 @@ async function detectK3sInKubeconfig(projectPath) {
64
65
  }
65
66
  return false;
66
67
  }
67
- async function fileExists(filePath) {
68
- try {
69
- await readFile(filePath, 'utf-8');
70
- return true;
71
- }
72
- catch {
73
- return false;
74
- }
75
- }
76
68
  async function fileContains(filePath, substring) {
77
69
  try {
78
70
  const content = await readFile(filePath, 'utf-8');
@@ -1,4 +1,5 @@
1
- export declare function readFileOrNull(filePath: string): Promise<string | null>;
1
+ import { readFileOrNull } from '../../../core/shared/fs.js';
2
+ export { readFileOrNull };
2
3
  export declare function readPackageJson(projectPath: string): Promise<{
3
4
  deps: Record<string, string>;
4
5
  devDeps: Record<string, string>;
@@ -1,14 +1,7 @@
1
1
  // llm-detector/file-readers.ts — File reading utilities for LLM detection
2
- import { readFile } from 'node:fs/promises';
3
2
  import { join } from 'node:path';
4
- export async function readFileOrNull(filePath) {
5
- try {
6
- return await readFile(filePath, 'utf-8');
7
- }
8
- catch {
9
- return null;
10
- }
11
- }
3
+ import { readFileOrNull } from '../../../core/shared/fs.js';
4
+ export { readFileOrNull };
12
5
  export async function readPackageJson(projectPath) {
13
6
  const content = await readFileOrNull(join(projectPath, 'package.json'));
14
7
  if (!content) {
@@ -1,4 +1,5 @@
1
1
  import { technologyValue } from '../technology-registry.js';
2
+ import { fileExistsByRead } from '../../core/shared/fs.js';
2
3
  // engine/detectors/mfe-detector.ts — Micro-frontend and signals detection (SPEC-017 tech-debt)
3
4
  // Detects Islands Architecture, Module Federation, Single-SPA, Nx MFE, Reactive Signals.
4
5
  import { readFile } from 'node:fs/promises';
@@ -64,14 +65,14 @@ async function collectAllDeps(projectPath) {
64
65
  }
65
66
  async function detectIslands(projectPath, deps) {
66
67
  // Astro: astro.config.mjs / .ts / .js
67
- const hasAstroConfig = (await fileExists(join(projectPath, 'astro.config.mjs'))) ||
68
- (await fileExists(join(projectPath, 'astro.config.ts'))) ||
69
- (await fileExists(join(projectPath, 'astro.config.js')));
68
+ const hasAstroConfig = (await fileExistsByRead(join(projectPath, 'astro.config.mjs'))) ||
69
+ (await fileExistsByRead(join(projectPath, 'astro.config.ts'))) ||
70
+ (await fileExistsByRead(join(projectPath, 'astro.config.js')));
70
71
  if (hasAstroConfig || deps.has(technologyValue('technology-astro-23661e'))) {
71
72
  return { framework: technologyValue('technology-astro-23661e') };
72
73
  }
73
74
  // Fresh (Deno): fresh.config.ts
74
- if (await fileExists(join(projectPath, 'fresh.config.ts'))) {
75
+ if (await fileExistsByRead(join(projectPath, 'fresh.config.ts'))) {
75
76
  return { framework: 'fresh' };
76
77
  }
77
78
  return { framework: undefined };
@@ -151,13 +152,4 @@ function detectSignals(deps) {
151
152
  }
152
153
  return detected;
153
154
  }
154
- async function fileExists(filePath) {
155
- try {
156
- await readFile(filePath, 'utf-8');
157
- return true;
158
- }
159
- catch {
160
- return false;
161
- }
162
- }
163
155
  //# sourceMappingURL=mfe-detector.js.map
@@ -1,4 +1,5 @@
1
1
  import { technologyValue } from '../technology-registry.js';
2
+ import { fileExistsByRead } from '../../core/shared/fs.js';
2
3
  // engine/detectors/monitoring-detector.ts — Monitoring/observability stack detection (SPEC-026a)
3
4
  // Detects Prometheus, Datadog, New Relic, OpenTelemetry, CloudWatch, Sentry, and more.
4
5
  import { readFile } from 'node:fs/promises';
@@ -184,7 +185,7 @@ async function isToolDetected(projectPath, signal, deps, envContent, foundFiles)
184
185
  if (signal.configFiles) {
185
186
  /* v8 ignore start */
186
187
  for (const f of signal.configFiles) {
187
- if (await fileExists(join(projectPath, f))) {
188
+ if (await fileExistsByRead(join(projectPath, f))) {
188
189
  foundFiles.push(f);
189
190
  return true;
190
191
  }
@@ -256,14 +257,4 @@ async function safeGlob(projectPath, pattern) {
256
257
  return [];
257
258
  }
258
259
  }
259
- async function fileExists(filePath) {
260
- try {
261
- await readFile(filePath, 'utf-8');
262
- return true;
263
- /* v8 ignore next 2 */
264
- }
265
- catch {
266
- return false;
267
- }
268
- }
269
260
  //# sourceMappingURL=monitoring-detector.js.map
@@ -1,5 +1,6 @@
1
1
  import type { MonorepoTool, MonorepoDetectionResult } from '../../types/index.js';
2
2
  export type { MonorepoTool, MonorepoDetectionResult };
3
+ /** File existence check — returns true if file is accessible */
3
4
  /**
4
5
  * Detect which monorepo tool (if any) is used in the given project directory.
5
6
  *