@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
@@ -4,22 +4,64 @@ import { isAbsolute } from 'node:path';
4
4
  import { specStore } from '../storage/index.js';
5
5
  import { resolveVerifiedSpecPath } from '../storage/project-identity.js';
6
6
  import { buildCheckReadinessSummary } from '../engine/human-summary.js';
7
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
7
8
  import { validateSpecFormat } from '../core/spec-validator.js';
8
9
  import { parseFrontmatter } from '../engine/frontmatter-parser.js';
9
10
  import { resolveProjectId } from './resolve-project-id.js';
10
11
  const VALID_DIFFICULTIES = [1, 2, 3, 4, 5];
11
12
  const VALID_SCOPES = ['trivial', 'feature', 'cross-module', 'architectural'];
13
+ const VALID_SPEC_TYPES = [
14
+ 'feature',
15
+ 'refactor',
16
+ 'bugfix',
17
+ 'infra',
18
+ 'docs',
19
+ 'project',
20
+ 'agent',
21
+ 'tech-debt',
22
+ ];
23
+ const VALID_SPEC_TARGETS = [
24
+ 'frontend',
25
+ 'backend',
26
+ 'shared',
27
+ 'fullstack',
28
+ 'infrastructure',
29
+ 'database',
30
+ 'ios',
31
+ 'android',
32
+ ];
12
33
  function asDifficulty(value) {
13
34
  return VALID_DIFFICULTIES.find((candidate) => candidate === value);
14
35
  }
15
36
  function asSpecScope(value) {
16
37
  return VALID_SCOPES.find((candidate) => candidate === value);
17
38
  }
18
- /**
19
- * Re-derive difficulty/scope from the freshly-read spec.md frontmatter so the
20
- * readiness gate honors on-disk edits instead of the specs.json snapshot that
21
- * `specStore` caches in memory.
22
- */
39
+ function asSpecType(value) {
40
+ return VALID_SPEC_TYPES.find((candidate) => candidate === value);
41
+ }
42
+ function asSpecTarget(value) {
43
+ return VALID_SPEC_TARGETS.find((candidate) => candidate === value);
44
+ }
45
+ function asStringTags(value) {
46
+ return Array.isArray(value) ? value.filter((tag) => typeof tag === 'string') : [];
47
+ }
48
+ async function synthesizeSpecFromDiscoveredPath(specId, discoveredPath) {
49
+ const raw = await readFile(discoveredPath, 'utf-8');
50
+ const { metadata } = parseFrontmatter(raw);
51
+ return {
52
+ id: specId,
53
+ specPath: discoveredPath,
54
+ difficulty: asDifficulty(metadata.difficulty) ?? 3,
55
+ tags: asStringTags(metadata.tags),
56
+ dependencies: [],
57
+ scope: asSpecScope(metadata.scope) ?? 'feature',
58
+ target: asSpecTarget(metadata.target) ?? 'backend',
59
+ type: asSpecType(metadata.type) ?? 'feature',
60
+ title: typeof metadata.title === 'string' && metadata.title.trim().length > 0
61
+ ? metadata.title
62
+ : specId,
63
+ };
64
+ }
23
65
  async function readFreshDifficultyAndScope(specId, specPath, projectPath) {
24
66
  try {
25
67
  const resolvedPath = projectPath
@@ -43,8 +85,12 @@ async function resolveEffectiveSpecPath(specId, specPath, projectPath) {
43
85
  try {
44
86
  return await resolveVerifiedSpecPath(specId, specPath, projectPath);
45
87
  }
46
- catch {
47
- return specPath;
88
+ catch (error) {
89
+ const discovered = await specStore.discoverCanonicalSpecPath(specId, projectPath);
90
+ if (discovered === null) {
91
+ throw error;
92
+ }
93
+ return discovered;
48
94
  }
49
95
  }
50
96
  // ── Formatting helpers ───────────────────────────────────────────────────────
@@ -165,30 +211,58 @@ export async function handleCheckReadiness(args) {
165
211
  }
166
212
  const { specId, mode = 'strict' } = args;
167
213
  const spec = await specStore.getSpecFresh(projectId, specId, args.projectPath);
168
- if (!spec) {
169
- return {
170
- content: [
171
- {
172
- type: 'text',
173
- text: `Spec '${specId}' not found in project '${projectId}'`,
174
- },
175
- ],
176
- isError: true,
214
+ let effectiveSpec;
215
+ if (spec) {
216
+ const fresh = spec.specPath
217
+ ? await readFreshDifficultyAndScope(spec.id, spec.specPath, args.projectPath)
218
+ : {};
219
+ let resolvedSpecPath = spec.specPath;
220
+ if (spec.specPath) {
221
+ try {
222
+ resolvedSpecPath = await resolveEffectiveSpecPath(spec.id, spec.specPath, args.projectPath);
223
+ }
224
+ catch (error) {
225
+ const reason = error instanceof Error ? error.message : String(error);
226
+ return {
227
+ content: [
228
+ {
229
+ type: 'text',
230
+ text: `Spec '${specId}' path could not be resolved: ${reason}`,
231
+ },
232
+ ],
233
+ isError: true,
234
+ };
235
+ }
236
+ }
237
+ effectiveSpec = {
238
+ id: spec.id,
239
+ specPath: resolvedSpecPath,
240
+ difficulty: fresh.difficulty ?? spec.difficulty,
241
+ scope: fresh.scope ?? spec.scope,
242
+ target: spec.target,
243
+ type: spec.type,
244
+ title: spec.title,
245
+ tags: spec.tags,
246
+ dependencies: spec.dependencies,
177
247
  };
178
248
  }
179
- const fresh = spec.specPath
180
- ? await readFreshDifficultyAndScope(spec.id, spec.specPath, args.projectPath)
181
- : {};
182
- const resolvedSpecPath = spec.specPath
183
- ? await resolveEffectiveSpecPath(spec.id, spec.specPath, args.projectPath)
184
- : spec.specPath;
185
- const effectiveSpec = {
186
- ...spec,
187
- specPath: resolvedSpecPath,
188
- technicalPath: resolvedSpecPath,
189
- difficulty: fresh.difficulty ?? spec.difficulty,
190
- scope: fresh.scope ?? spec.scope,
191
- };
249
+ else {
250
+ const discoveredPath = args.projectPath
251
+ ? await specStore.discoverCanonicalSpecPath(specId, args.projectPath)
252
+ : null;
253
+ if (!discoveredPath) {
254
+ return {
255
+ content: [
256
+ {
257
+ type: 'text',
258
+ text: `Spec '${specId}' not found in project '${projectId}'`,
259
+ },
260
+ ],
261
+ isError: true,
262
+ };
263
+ }
264
+ effectiveSpec = await synthesizeSpecFromDiscoveredPath(specId, discoveredPath);
265
+ }
192
266
  // validateSpecFormat owns the readiness and quality evaluation so the response
193
267
  // cannot combine separately computed evidence from different reads of spec.md.
194
268
  const validationResult = await validateSpecFormat(effectiveSpec, { readinessMode: mode });
@@ -197,7 +271,7 @@ export async function handleCheckReadiness(args) {
197
271
  // report — MISSING_FRONTMATTER due to file-not-found is best-effort since
198
272
  // the readiness checker already handles missing files gracefully.
199
273
  const vr = validationResult;
200
- const report = vr.readinessReport ?? createFailClosedReport(spec.id, mode);
274
+ const report = vr.readinessReport ?? createFailClosedReport(effectiveSpec.id, mode);
201
275
  const hardFormatErrors = vr.errors.filter((e) => e.code !== 'MISSING_FRONTMATTER' && !(e.code === 'READINESS_CHECK_FAILED'));
202
276
  const hardFormatMessages = hardFormatErrors.map((e) => e.message);
203
277
  const formatWarnings = vr.warnings
@@ -1,6 +1,6 @@
1
1
  import type { ClarificationQuestion } from '../../types/index.js';
2
2
  /** Detected stack info from package files in the project directory. */
3
- export interface StackDetectionResult {
3
+ export interface ClarifyStackDetectionResult {
4
4
  framework: string | null;
5
5
  language: string | null;
6
6
  database: string | null;
@@ -11,12 +11,12 @@ export interface StackDetectionResult {
11
11
  * Detect the project stack by reading package.json and/or requirements.txt
12
12
  * from the given project path.
13
13
  */
14
- export declare function detectStack(projectPath: string): Promise<StackDetectionResult>;
14
+ export declare function detectStack(projectPath: string): Promise<ClarifyStackDetectionResult>;
15
15
  /**
16
16
  * Returns true if the question should be skipped because the stack already
17
17
  * provides a definitive answer.
18
18
  */
19
- export declare function shouldSkipQuestion(question: ClarificationQuestion, stack: StackDetectionResult): boolean;
19
+ export declare function shouldSkipQuestion(question: ClarificationQuestion, stack: ClarifyStackDetectionResult): boolean;
20
20
  /**
21
21
  * Attaches structured `options[]` to a question based on its content.
22
22
  * Each question gets 3-8 concrete choices + 'Other: ___' fallback.
@@ -1,5 +1,6 @@
1
1
  // configure-oauth-handler.ts — Handler for the configure_oauth MCP tool (SPEC-161).
2
2
  // Reads and displays the current OAuth config status (without exposing secrets).
3
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
3
4
  import { loadOAuthConfig, extractBearerToken, validateToken, } from '../transports/oauth-validator.js';
4
5
  function buildStatusLines(config) {
5
6
  const exampleCurl = config.enabled
@@ -26,14 +26,14 @@ function resolveHost(input) {
26
26
  // ---------------------------------------------------------------------------
27
27
  // Writers per host
28
28
  // ---------------------------------------------------------------------------
29
- async function writeSkillForClaudeCode(name, content, description, projectPath, overwrite) {
29
+ async function writeSkillForClaudeCode(name, content, description, projectPath, overwrite, managedByPlanu) {
30
30
  const dirPath = join(projectPath, '.claude', 'skills', name);
31
31
  const skillFilePath = join(dirPath, 'SKILL.md');
32
32
  // Overwrite protection
33
33
  try {
34
34
  const existing = await readFile(skillFilePath, 'utf-8');
35
35
  const existingHash = hashContent(existing);
36
- const newContent = buildSkillMd(name, description, content);
36
+ const newContent = buildSkillMd(name, description, content, managedByPlanu);
37
37
  const newHash = hashContent(newContent);
38
38
  if (existingHash !== newHash && !overwrite) {
39
39
  throw new Error(`Skill already exists at ${skillFilePath}. Pass overwriteExisting: true to replace.`);
@@ -46,13 +46,14 @@ async function writeSkillForClaudeCode(name, content, description, projectPath,
46
46
  // File doesn't exist — proceed
47
47
  }
48
48
  await mkdir(dirPath, { recursive: true });
49
- const skillContent = buildSkillMd(name, description, content);
49
+ const skillContent = buildSkillMd(name, description, content, managedByPlanu);
50
50
  await writeFile(skillFilePath, skillContent, 'utf-8');
51
51
  return { dirPath, skillFilePath };
52
52
  }
53
- function buildSkillMd(name, description, body) {
53
+ function buildSkillMd(name, description, body, managedByPlanu) {
54
54
  const desc = description.length > 0 ? description : `Auto-generated skill: ${name}`;
55
- return `---\nname: ${name}\ndescription: "${desc}"\n---\n\n${body}\n`;
55
+ const managedByLine = managedByPlanu ? 'managed-by: planu\n' : '';
56
+ return `---\nname: ${name}\ndescription: "${desc}"\n${managedByLine}---\n\n${body}\n`;
56
57
  }
57
58
  async function writeSkillForCodex(name, content, description, projectPath) {
58
59
  // For Codex, append to AGENTS.md with markers
@@ -80,13 +81,13 @@ async function writeSkillForCodex(name, content, description, projectPath) {
80
81
  await writeFile(agentsMdPath, updated, 'utf-8');
81
82
  return { dirPath: projectPath, skillFilePath: agentsMdPath };
82
83
  }
83
- async function writeSkillForGemini(name, content, description, projectPath) {
84
+ async function writeSkillForGemini(name, content, description, projectPath, managedByPlanu) {
84
85
  const geminiDir = join(projectPath, '.gemini');
85
86
  const skillsDir = join(geminiDir, 'skills');
86
87
  await mkdir(skillsDir, { recursive: true });
87
88
  const skillFilePath = join(skillsDir, `${name}.md`);
88
89
  const desc = description.length > 0 ? description : name;
89
- const skillContent = buildSkillMd(name, desc, content);
90
+ const skillContent = buildSkillMd(name, desc, content, managedByPlanu);
90
91
  await writeFile(skillFilePath, skillContent, 'utf-8');
91
92
  return { dirPath: skillsDir, skillFilePath };
92
93
  }
@@ -96,6 +97,7 @@ async function writeSkillForGemini(name, content, description, projectPath) {
96
97
  export async function handleCreateSkill(input) {
97
98
  const { projectPath, name, content, overwriteExisting } = input;
98
99
  const description = input.description ?? '';
100
+ const managedByPlanu = input.managedByPlanu === true;
99
101
  const host = resolveHost(input);
100
102
  const languageValidation = validateEnglishOnlyArtifactText(`${name}\n\n${description}\n\n${content}`, 'skill');
101
103
  if (!languageValidation.ok) {
@@ -121,13 +123,13 @@ export async function handleCreateSkill(input) {
121
123
  try {
122
124
  switch (host) {
123
125
  case 'claude-code':
124
- result = await writeSkillForClaudeCode(name, content, description, projectPath, overwriteExisting === true);
126
+ result = await writeSkillForClaudeCode(name, content, description, projectPath, overwriteExisting === true, managedByPlanu);
125
127
  break;
126
128
  case 'codex':
127
129
  result = await writeSkillForCodex(name, content, description, projectPath);
128
130
  break;
129
131
  case 'gemini':
130
- result = await writeSkillForGemini(name, content, description, projectPath);
132
+ result = await writeSkillForGemini(name, content, description, projectPath, managedByPlanu);
131
133
  break;
132
134
  }
133
135
  }
@@ -1,8 +1,6 @@
1
1
  import type { GitSetupResult, GitAutoSetupOptions } from '../types/index.js';
2
+ export { generateSpecId } from '../engine/spec-format/spec-id.js';
2
3
  export declare function slugify(text: string): string;
3
- export declare function generateSpecId(existingSpecs: {
4
- id: string;
5
- }[]): string;
6
4
  export declare function generateBranchName(specId: string, slug: string, type: string): string;
7
5
  /** Try auto-setup git branch. Returns result or undefined on failure. */
8
6
  export declare function tryAutoSetupGit(projectId: string, specId: string, options?: GitAutoSetupOptions): Promise<GitSetupResult | undefined>;
@@ -1,4 +1,5 @@
1
1
  import { handleAutoSetup } from './git/branch-ops.js';
2
+ export { generateSpecId } from '../engine/spec-format/spec-id.js';
2
3
  export function slugify(text) {
3
4
  return text
4
5
  .toLowerCase()
@@ -8,14 +9,6 @@ export function slugify(text) {
8
9
  .replace(/^-+|-+$/g, '')
9
10
  .slice(0, 60);
10
11
  }
11
- export function generateSpecId(existingSpecs) {
12
- const maxNum = existingSpecs.reduce((max, spec) => {
13
- const match = /^SPEC-(\d+)$/.exec(spec.id);
14
- const num = match?.[1] ? parseInt(match[1], 10) : 0;
15
- return Math.max(max, num);
16
- }, 0);
17
- return `SPEC-${String(maxNum + 1).padStart(3, '0')}`;
18
- }
19
12
  const BRANCH_PREFIXES = {
20
13
  feature: 'feat',
21
14
  refactor: 'refactor',
@@ -6,6 +6,7 @@ import { readTechnologySelectionContract } from '../storage/technology-selection
6
6
  import { toolResult, interactiveResult } from './response-helpers.js';
7
7
  import { readFile, stat as fsStat } from 'node:fs/promises';
8
8
  import { createHash, randomUUID } from 'node:crypto';
9
+ import { pathExistsByStat as pathExists } from '../core/shared/fs.js';
9
10
  import { basename as pathBasename, dirname as pathDirname, isAbsolute as pathIsAbsolute, join as pathJoin, relative as pathRelative, sep as pathSeparator, } from 'node:path';
10
11
  import { withFileLock } from '../storage/file-mutex.js';
11
12
  import { generateBranchName } from './create-spec-helpers.js';
@@ -261,19 +262,6 @@ function isDerivedFromGroundedSource(testPath, modifyFiles) {
261
262
  return testPath === `tests/${base}.test${ext}` || testPath === `tests/${withoutSrc}`;
262
263
  });
263
264
  }
264
- async function pathExists(path) {
265
- try {
266
- const fs = await import('node:fs/promises');
267
- if (typeof fs.stat !== 'function') {
268
- return false;
269
- }
270
- await fs.stat(path);
271
- return true;
272
- }
273
- catch {
274
- return false;
275
- }
276
- }
277
265
  const HIGH_RISK_WARNING = 'High-risk spec — consider: ' +
278
266
  '1) Is the approach technically feasible within the project constraints? ' +
279
267
  '2) What edge cases (network failure, concurrent writes, empty state) could break this? ' +
@@ -1,7 +1,12 @@
1
1
  // tools/dashboard.ts — MCP tool handlers for start_dashboard and stop_dashboard.
2
2
  import { startDashboardWithFallback, stopDashboardServer, registerCleanupHandlers, openBrowser, DEFAULT_DASHBOARD_PORT, } from '../engine/dashboard/server.js';
3
+ import { registerUpdateStatusHandler } from '../engine/dashboard/spec-updater.js';
4
+ import { handleUpdateStatus } from './update-status/index.js';
3
5
  // Register process-exit cleanup once at module load time
4
6
  registerCleanupHandlers();
7
+ // Wire the tools-layer status gate into the engine's dashboard status route
8
+ // (see engine/dashboard/spec-updater.ts — engine must not import tools/ directly).
9
+ registerUpdateStatusHandler(handleUpdateStatus);
5
10
  /** Handle start_dashboard tool invocation */
6
11
  export async function handleStartDashboard(args) {
7
12
  const port = args.port ?? DEFAULT_DASHBOARD_PORT;
@@ -3,6 +3,7 @@ import { createPlatformClient, getCurrentBranch, getRemoteUrl } from '../engine/
3
3
  import { detectAuth } from '../engine/github/auth.js';
4
4
  import { generatePRTitle, generatePRBody } from '../engine/github/pr-template.js';
5
5
  import { findLinkedPRs } from '../engine/github/spec-linker.js';
6
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
6
7
  import { validateSpecFormat } from '../core/spec-validator.js';
7
8
  import { readFile } from 'node:fs/promises';
8
9
  import { runAbortableProcess } from '../engine/abortable-process-runner.js';
@@ -1,6 +1,7 @@
1
1
  import type { ToolResult } from '../types/index.js';
2
2
  import type { ExecFileFn } from '../types/github.js';
3
3
  import type { EscalateResult } from '../types/escalator.js';
4
+ import './update-status/side-effects.js';
4
5
  /**
5
6
  * Returns a ToolResult error if stuck specs are detected and no bypass flag
6
7
  * is set, or null if release may proceed. Handles autoFixDrift by closing
@@ -8,6 +8,8 @@ import { readFile, writeFile } from 'node:fs/promises';
8
8
  import { join } from 'node:path';
9
9
  import { promisify } from 'node:util';
10
10
  import { withEscalation } from '../engine/escalator/with-escalation.js';
11
+ // Side-effect import: registers dispatchHookEvent on the cascade hook before runCascade() below.
12
+ import './update-status/side-effects.js';
11
13
  const defaultExec = async (cmd, args) => {
12
14
  return promisify(nodeExecFile)(cmd, args, { maxBuffer: 10 * 1024 * 1024 });
13
15
  };
@@ -127,14 +129,13 @@ export async function handleCreateRelease(args, exec = defaultExec) {
127
129
  draft: args.draft,
128
130
  prerelease: args.prerelease,
129
131
  });
130
- // SPEC-496: Regenerate session context on release
131
132
  try {
132
- const { generateSessionContext } = await import('../engine/session-context-generator.js');
133
+ const { refreshSessionArtifacts } = await import('../engine/session-state/session-artifact-refresher.js');
133
134
  const releasePath = process.cwd();
134
135
  const { resolveProjectIdOrAutoDetect } = await import('./resolve-project-id.js');
135
136
  const resolved = await resolveProjectIdOrAutoDetect({ projectPath: releasePath });
136
137
  if (resolved.ok) {
137
- void generateSessionContext(releasePath, resolved.projectId).catch(() => {
138
+ void refreshSessionArtifacts(releasePath, resolved.projectId).catch(() => {
138
139
  /* best-effort */
139
140
  });
140
141
  }
@@ -1,5 +1,5 @@
1
1
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { type SpecGraph } from '../engine/spec-dependency-graph/graph-builder.js';
2
+ import type { SpecGraph } from '../types/spec-dependency-graph.js';
3
3
  export type GraphSpecsResult = {
4
4
  format: 'json';
5
5
  graph: SpecGraph;
@@ -12,6 +12,7 @@ import { jaccard } from '../engine/spec-format/jaccard.js';
12
12
  import { replaceSectionInSpec } from '../engine/spec-format/replace-section.js';
13
13
  import { executionRemove } from '../engine/execution/deadline-io.js';
14
14
  import { buildMigrationDirective, scanLegacyArtifacts, } from '../engine/spec-migrator/legacy-classifier.js';
15
+ import { escapeRegex } from '../core/shared/strings.js';
15
16
  const SPANISH_INDICATORS = [
16
17
  'de',
17
18
  'del',
@@ -112,9 +113,6 @@ function removeTopLevelSection(content, sectionName) {
112
113
  }
113
114
  return `${before}\n\n${after.trimEnd()}\n`;
114
115
  }
115
- function escapeRegex(input) {
116
- return input.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
117
- }
118
116
  /** Local extraction of ## Technical body to avoid circular imports. */
119
117
  function extractTechnicalBodyLocal(content) {
120
118
  return extractSectionBodyLocal(content, 'Technical') ?? '';
@@ -1,4 +1,4 @@
1
- export interface GitSetupResult {
1
+ export interface InitGitSetupResult {
2
2
  hooksInstalled: string[];
3
3
  gitFlowType: string;
4
4
  gitignoreUpdated: boolean;
@@ -7,7 +7,7 @@ export interface GitSetupResult {
7
7
  }
8
8
  /** SPEC-001 + SPEC-539: Setup git hooks, detect branching model, and configure .gitignore.
9
9
  * SPEC-539: Only installs hooks if a git repository is detected — never creates .git. */
10
- export declare function runGitSetup(projectPath: string, projectId: string): Promise<GitSetupResult>;
10
+ export declare function runGitSetup(projectPath: string, projectId: string): Promise<InitGitSetupResult>;
11
11
  /** SPEC-466: Also exported for list_specs auto-cleanup. */
12
12
  export declare function configureGitignoreForPlanu(projectPath: string): Promise<boolean>;
13
13
  //# sourceMappingURL=git-setup.d.ts.map
@@ -1,8 +1,9 @@
1
1
  // tools/init-project/host-assets-writer.ts — Host-aware rules/skills installed by init_project
2
- import { access, readFile } from 'node:fs/promises';
2
+ import { readFile } from 'node:fs/promises';
3
3
  import { join } from 'node:path';
4
4
  import { detectHost } from '../../engine/host-detection/detect-host.js';
5
5
  import { handleCreateSkill } from '../create-skill.js';
6
+ import { fileExists } from '../../core/shared/fs.js';
6
7
  const CORE_SKILL_TEMPLATES = [
7
8
  'planu-new-spec.md',
8
9
  'planu-validate.md',
@@ -11,16 +12,10 @@ const CORE_SKILL_TEMPLATES = [
11
12
  'planu-native.md',
12
13
  'planu-multi-teammate-review.md',
13
14
  'planu-context-assets.md',
15
+ 'planu-review.md',
16
+ 'planu-implement.md',
17
+ 'planu-dogfood-bug.md',
14
18
  ];
15
- async function fileExists(path) {
16
- try {
17
- await access(path);
18
- return true;
19
- }
20
- catch {
21
- return false;
22
- }
23
- }
24
19
  function addHost(hosts, host) {
25
20
  if (!hosts.includes(host)) {
26
21
  hosts.push(host);
@@ -115,6 +110,9 @@ async function canRefreshCoreSkill(projectPath, host, name) {
115
110
  return (existing.includes(`<!-- planu:skills:${name} -->`) ||
116
111
  !existing.includes(`## Skill: ${name}`));
117
112
  }
113
+ if (existing.includes('managed-by: planu')) {
114
+ return true;
115
+ }
118
116
  return existing.includes(`name: ${name}`) && existing.includes(`# /${name}`);
119
117
  }
120
118
  catch {
@@ -138,6 +136,7 @@ async function installCoreSkillsForHost(projectPath, host) {
138
136
  description: template.description,
139
137
  content: template.content,
140
138
  overwriteExisting: true,
139
+ managedByPlanu: true,
141
140
  });
142
141
  if (result.isError === true) {
143
142
  continue;
@@ -22,11 +22,11 @@ export declare function generateAndWriteRules(projectPath: string): {
22
22
  };
23
23
  export declare function fireTelemetry(knowledge: ProjectKnowledge): Promise<boolean>;
24
24
  export declare function runConventionScanSafe(projectPath: string): Promise<'ok' | 'failed' | 'skipped'>;
25
- export interface SkillInstallResult {
25
+ export interface LifecycleSkillInstallResult {
26
26
  skillsAutoInstalled: string[];
27
27
  skillsPendingInstall: string[];
28
28
  skillsSkipped: string[];
29
29
  }
30
30
  /** Orchestrate skill discovery and installation with autoInstall logic. */
31
- export declare function orchestrateSkillInstalls(recommendedSkills: RecommendedSkill[], projectPath: string, autoInstallFromConfig: boolean): Promise<SkillInstallResult>;
31
+ export declare function orchestrateSkillInstalls(recommendedSkills: RecommendedSkill[], projectPath: string, autoInstallFromConfig: boolean): Promise<LifecycleSkillInstallResult>;
32
32
  //# sourceMappingURL=lifecycle-helpers.d.ts.map
@@ -1,5 +1,6 @@
1
1
  import { technologyValue } from '../../engine/technology-registry.js';
2
- import { readFile, writeFile, access } from 'node:fs/promises';
2
+ import { fileExists } from '../../core/shared/fs.js';
3
+ import { readFile, writeFile } from 'node:fs/promises';
3
4
  import { join } from 'node:path';
4
5
  const ESLINT_CONFIG_FILES = [
5
6
  'eslint.config.js',
@@ -22,15 +23,6 @@ const PRETTIER_CONFIG_FILES = [
22
23
  'prettier.config.js',
23
24
  'prettier.config.cjs',
24
25
  ];
25
- async function fileExists(filePath) {
26
- try {
27
- await access(filePath);
28
- return true;
29
- }
30
- catch {
31
- return false;
32
- }
33
- }
34
26
  async function anyFileExists(dir, names) {
35
27
  for (const name of names) {
36
28
  if (await fileExists(join(dir, name))) {
@@ -1,7 +1,7 @@
1
1
  import { detectModernPatterns, detectDdd } from '../../engine/architecture-pattern-detector.js';
2
2
  import { detectAgileProcess } from '../../engine/agile-config-builder.js';
3
3
  import { detectOrchestratorInfo, detectComposeMultiplatform } from './helpers.js';
4
- export interface StackDetectionResult {
4
+ export interface InitStackDetectionResult {
5
5
  modernPatterns: Awaited<ReturnType<typeof detectModernPatterns>>;
6
6
  dddConfig: Awaited<ReturnType<typeof detectDdd>>;
7
7
  agileDetection: Awaited<ReturnType<typeof detectAgileProcess>>;
@@ -12,5 +12,5 @@ export interface StackDetectionResult {
12
12
  * SPEC-033: Detect modern architecture patterns, DDD config, agile process,
13
13
  * container orchestrator, and Compose Multiplatform — all in parallel.
14
14
  */
15
- export declare function detectStackPatterns(projectPath: string): Promise<StackDetectionResult>;
15
+ export declare function detectStackPatterns(projectPath: string): Promise<InitStackDetectionResult>;
16
16
  //# sourceMappingURL=stack-detector.d.ts.map
@@ -1,10 +1,10 @@
1
1
  import type { ToolResult } from '../types/index.js';
2
- export interface ReconcileResult {
2
+ export interface HookReconcileResult {
3
3
  hookInstalled: boolean;
4
4
  settingsUpdated: boolean;
5
5
  humanSummary: string;
6
6
  }
7
- export declare function reconcileInteractiveQuestionHooks(projectPath: string): Promise<ReconcileResult>;
7
+ export declare function reconcileInteractiveQuestionHooks(projectPath: string): Promise<HookReconcileResult>;
8
8
  export declare function handleReconcileInteractiveQuestionHooks(args: {
9
9
  projectPath: string;
10
10
  }): Promise<ToolResult>;
@@ -1,5 +1,6 @@
1
1
  // register-sdd-tools.ts — Canonical MCP surface for Planu's SDD workflow.
2
2
  import { z } from 'zod';
3
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
3
4
  import { registerResources } from '../resources/registry.js';
4
5
  import { registerFromEntries } from './tool-entry.js';
5
6
  import coreToolsRegistry from './tool-registry/core-tools.js';
@@ -31,6 +31,7 @@ import { loadCompactThresholds } from '../engine/compact/registry-loader.js';
31
31
  import { applyCompactMode } from '../engine/compact/compact-middleware.js';
32
32
  import { globalCompactStateStore } from '../engine/compact/state-store.js';
33
33
  import { recordCompactDecision, recordVerboseDecision, recordNoHeader, } from '../engine/compact/metrics.js';
34
+ // eslint-disable-next-line no-restricted-imports -- grandfathered layer violation, remediation SPEC-1661 SPEC-1662 SPEC-1663
34
35
  import { getSessionContext } from '../transports/session-context.js';
35
36
  import { LocalExecutionSpan } from '../engine/observability/local-execution-spans.js';
36
37
  import { classifyBoundaryFailure } from '../errors/error-taxonomy.js';
@@ -1,7 +1,2 @@
1
- import { z } from 'zod';
2
- export declare const SPEC_ID_PATTERN: RegExp;
3
- export declare const SPEC_DIR_NAME_PATTERN: RegExp;
4
- export declare const SpecIdSchema: z.ZodString;
5
- export declare const SpecDirNameSchema: z.ZodString;
6
- export declare function isCanonicalSpecId(value: string): boolean;
1
+ export { SPEC_ID_PATTERN, SPEC_DIR_NAME_PATTERN, SpecIdSchema, SpecDirNameSchema, isCanonicalSpecId, } from '../../engine/spec-format/spec-id.js';
7
2
  //# sourceMappingURL=spec-id.d.ts.map
@@ -1,17 +1,2 @@
1
- import { z } from 'zod';
2
- export const SPEC_ID_PATTERN = /^SPEC-\d+$/;
3
- export const SPEC_DIR_NAME_PATTERN = /^SPEC-\d+(?:-[a-z0-9]+(?:-[a-z0-9]+)*)?$/;
4
- export const SpecIdSchema = z
5
- .string()
6
- .min(1)
7
- .max(50)
8
- .regex(SPEC_ID_PATTERN, 'Spec ID must use canonical numeric format like SPEC-042.');
9
- export const SpecDirNameSchema = z
10
- .string()
11
- .min(1)
12
- .max(200)
13
- .regex(SPEC_DIR_NAME_PATTERN, 'Spec directory must start with a canonical numeric ID like SPEC-042 or SPEC-042-my-feature.');
14
- export function isCanonicalSpecId(value) {
15
- return SPEC_ID_PATTERN.test(value);
16
- }
1
+ export { SPEC_ID_PATTERN, SPEC_DIR_NAME_PATTERN, SpecIdSchema, SpecDirNameSchema, isCanonicalSpecId, } from '../../engine/spec-format/spec-id.js';
17
2
  //# sourceMappingURL=spec-id.js.map
@@ -15,7 +15,7 @@ export type ToolInputSchema = Record<string, ZodType>;
15
15
  * The `wrap` field controls which safe-handler wrapper is applied by
16
16
  * registerFromEntries(). Defaults to 'tracked' when omitted.
17
17
  */
18
- export interface ToolEntry {
18
+ export interface McpToolEntry {
19
19
  /** MCP tool name, e.g. 'generate_batch_script'. snake_case. */
20
20
  name: string;
21
21
  /** Human-readable description surfaced to LLMs. */
@@ -49,5 +49,5 @@ export interface ToolEntry {
49
49
  *
50
50
  * Drop-in replacement for calling register*Tools(server) on each migrated file.
51
51
  */
52
- export declare function registerFromEntries(server: McpServer, entries: ToolEntry[]): void;
52
+ export declare function registerFromEntries(server: McpServer, entries: McpToolEntry[]): void;
53
53
  //# sourceMappingURL=tool-entry.d.ts.map
@@ -1,4 +1,4 @@
1
- // tools/tool-entry.ts — Declarative ToolEntry type for registry-based tool registration.
1
+ // tools/tool-entry.ts — Declarative McpToolEntry type for registry-based tool registration.
2
2
  //
3
3
  // Phase 1 (refactor/declarative-registry): replaces the register-*-tools.ts boilerplate pattern:
4
4
  // server.registerTool(name, { description, inputSchema, annotations }, safeXxx(name, handler))
@@ -1,4 +1,4 @@
1
- import type { ToolEntry } from '../tool-entry.js';
2
- declare const coreToolsRegistry: ToolEntry[];
1
+ import type { McpToolEntry } from '../tool-entry.js';
2
+ declare const coreToolsRegistry: McpToolEntry[];
3
3
  export default coreToolsRegistry;
4
4
  //# sourceMappingURL=core-tools.d.ts.map