@planu/cli 4.13.0 → 4.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (787) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +24 -24
  3. package/dist/cli/commands/inspect.d.ts +4 -0
  4. package/dist/cli/commands/inspect.js +144 -0
  5. package/dist/cli/commands/install.d.ts +19 -1
  6. package/dist/cli/commands/install.js +145 -43
  7. package/dist/cli/commands/job.d.ts +3 -0
  8. package/dist/cli/commands/job.js +119 -0
  9. package/dist/cli/commands/offline.d.ts +15 -0
  10. package/dist/cli/commands/offline.js +132 -0
  11. package/dist/cli/commands/serve.js +4 -0
  12. package/dist/cli/commands/spec.js +1 -1
  13. package/dist/cli/commands/storage.d.ts +3 -0
  14. package/dist/cli/commands/storage.js +102 -0
  15. package/dist/cli/commands/uninstall.d.ts +10 -0
  16. package/dist/cli/commands/uninstall.js +93 -7
  17. package/dist/cli/commands/validate.js +1 -1
  18. package/dist/cli/index.js +2 -0
  19. package/dist/cli/router.js +9 -1
  20. package/dist/config/crash-shield-framework-rules.json +93 -0
  21. package/dist/config/environment-schema.json +149 -0
  22. package/dist/config/hardcode-exceptions.json +4 -0
  23. package/dist/config/license-plans.json +7 -0
  24. package/dist/config/native-release-public-key.pem +3 -0
  25. package/dist/config/native-targets.json +87 -0
  26. package/dist/config/product-public.d.ts +89 -0
  27. package/dist/config/product-public.js +140 -0
  28. package/dist/config/product-public.json +312 -0
  29. package/dist/config/product-public.ts +148 -0
  30. package/dist/config/release-compatibility.json +13 -0
  31. package/dist/config/release-policy.json +26 -0
  32. package/dist/config/runtime-policy.json +44 -0
  33. package/dist/config/skill-templates/planu-validate.md +7 -4
  34. package/dist/config/subagent-templates/planu-spec-implementer.md +7 -3
  35. package/dist/config/subagent-templates/planu-validator.md +10 -5
  36. package/dist/config/technology-registry.json +120 -0
  37. package/dist/config/version.js +7 -8
  38. package/dist/config/version.ts +10 -7
  39. package/dist/engine/abortable-process-runner.js +40 -9
  40. package/dist/engine/advanced-testing/accessibility-checker.js +12 -14
  41. package/dist/engine/advanced-testing/mutation-advisor.js +3 -4
  42. package/dist/engine/advanced-testing/property-based.js +2 -3
  43. package/dist/engine/advanced-testing/test-data-advisor.js +2 -3
  44. package/dist/engine/agent-generator.js +2 -1
  45. package/dist/engine/agent-handoff-store.js +2 -1
  46. package/dist/engine/agent-prompt-generator.js +7 -5
  47. package/dist/engine/agent-telemetry.js +2 -1
  48. package/dist/engine/ai-integration/gemini/extensions-advisor.js +41 -9
  49. package/dist/engine/ambiguity-detector.js +12 -11
  50. package/dist/engine/analyzer/db-engine.js +2 -3
  51. package/dist/engine/analyzer/detectors.js +13 -14
  52. package/dist/engine/analyzer/env-setup.js +9 -10
  53. package/dist/engine/analyzer-env-scanner/env-example.js +7 -8
  54. package/dist/engine/api-spec-generator/graphql-parser.js +2 -2
  55. package/dist/engine/api-validation/graphql-schema-validator.js +2 -1
  56. package/dist/engine/api-validation/openapi-impl-validator.js +6 -7
  57. package/dist/engine/architecture-detector.js +10 -8
  58. package/dist/engine/auth/config.d.ts +1 -1
  59. package/dist/engine/auth/config.js +4 -3
  60. package/dist/engine/auto-updater/atomic-upgrade.d.ts +8 -0
  61. package/dist/engine/auto-updater/atomic-upgrade.js +381 -0
  62. package/dist/engine/auto-updater/config-detector.js +9 -3
  63. package/dist/engine/auto-updater/config-patcher.d.ts +0 -4
  64. package/dist/engine/auto-updater/config-patcher.js +10 -15
  65. package/dist/engine/auto-updater/index.d.ts +3 -1
  66. package/dist/engine/auto-updater/index.js +44 -30
  67. package/dist/engine/auto-updater/npm-registry.js +10 -2
  68. package/dist/engine/auto-updater/release-verifier.d.ts +3 -0
  69. package/dist/engine/auto-updater/release-verifier.js +112 -0
  70. package/dist/engine/auto-updater/upgrade-lock.d.ts +6 -0
  71. package/dist/engine/auto-updater/upgrade-lock.js +28 -0
  72. package/dist/engine/auto-updater/upgrade-trust-state.d.ts +7 -0
  73. package/dist/engine/auto-updater/upgrade-trust-state.js +59 -0
  74. package/dist/engine/autopilot/audit-logger.js +2 -5
  75. package/dist/engine/best-practices-library.js +2 -1
  76. package/dist/engine/browser-validator.js +2 -1
  77. package/dist/engine/build-tool-detector.js +3 -2
  78. package/dist/engine/ci-generator/context-builders.js +7 -5
  79. package/dist/engine/ci-generator/stack-detector.js +0 -2
  80. package/dist/engine/ci-generator/yaml-builder.js +0 -2
  81. package/dist/engine/claude-config-auditor/rules-auditor.js +4 -3
  82. package/dist/engine/code-transforms/typescript/ast-utils.js +2 -3
  83. package/dist/engine/complexity-budget/trivial-detector.js +2 -1
  84. package/dist/engine/compliance-test-generator/index.js +7 -2
  85. package/dist/engine/compliance-test-generator/test-formatter.js +2 -2
  86. package/dist/engine/config-health/mcp-config-checker.js +2 -1
  87. package/dist/engine/config-health/ts-checker-scripts.js +4 -3
  88. package/dist/engine/config-health/ts-checker.js +3 -2
  89. package/dist/engine/convention-injector.js +5 -7
  90. package/dist/engine/convention-scanner/convention-parser.js +3 -2
  91. package/dist/engine/core-bridge-duplicate-blocks.d.ts +3 -0
  92. package/dist/engine/core-bridge-duplicate-blocks.js +57 -0
  93. package/dist/engine/core-bridge-gaps.d.ts +4 -0
  94. package/dist/engine/core-bridge-gaps.js +75 -0
  95. package/dist/engine/core-bridge.d.ts +9 -9
  96. package/dist/engine/core-bridge.js +196 -283
  97. package/dist/engine/cost-tracking/ledger.js +2 -5
  98. package/dist/engine/coverage-gap-analyzer.js +10 -1
  99. package/dist/engine/crash-shield/detectors/framework-detector.d.ts +2 -0
  100. package/dist/engine/crash-shield/detectors/framework-detector.js +110 -192
  101. package/dist/engine/crash-shield/detectors/typescript-detector.js +2 -1
  102. package/dist/engine/dashboard/data-loader.js +2 -1
  103. package/dist/engine/data-projects-gc/gc-runner.d.ts +7 -0
  104. package/dist/engine/data-projects-gc/gc-runner.js +113 -3
  105. package/dist/engine/data-projects-gc/scanner.js +5 -1
  106. package/dist/engine/decision-store.js +11 -14
  107. package/dist/engine/deleter/core.js +5 -5
  108. package/dist/engine/dep-auditor/abandonment-data.js +2 -1
  109. package/dist/engine/dep-auditor/abandonment-registry.js +3 -1
  110. package/dist/engine/dep-auditor/cve-fetcher.js +3 -0
  111. package/dist/engine/dep-auditor/dep-duplicates-detector.js +36 -4
  112. package/dist/engine/dep-auditor/license-registry.js +2 -0
  113. package/dist/engine/dependency-evaluator.d.ts +14 -0
  114. package/dist/engine/dependency-evaluator.js +81 -0
  115. package/dist/engine/deploy/providers/fly.js +7 -7
  116. package/dist/engine/deploy/providers/netlify.js +7 -7
  117. package/dist/engine/deploy/providers/railway.js +10 -12
  118. package/dist/engine/deploy/providers/vercel.js +7 -9
  119. package/dist/engine/deprecation-scanner/pattern-loader.js +0 -2
  120. package/dist/engine/desktop-detector.js +2 -3
  121. package/dist/engine/detect-duplication.js +2 -1
  122. package/dist/engine/detectors/advanced-framework-detector/css-state-detector.js +2 -1
  123. package/dist/engine/detectors/advanced-framework-detector/legacy-detector.js +2 -3
  124. package/dist/engine/detectors/advanced-framework-detector/modern-detector.js +3 -4
  125. package/dist/engine/detectors/agent-framework-detector.js +3 -2
  126. package/dist/engine/detectors/ai-native-detector.js +4 -6
  127. package/dist/engine/detectors/cache-db-detector.js +4 -3
  128. package/dist/engine/detectors/cicd-detector.js +4 -3
  129. package/dist/engine/detectors/deployment-detector.js +11 -12
  130. package/dist/engine/detectors/frontend-perf-detector.js +14 -9
  131. package/dist/engine/detectors/library-detector-multilang-a.js +16 -3
  132. package/dist/engine/detectors/library-detector-node.js +14 -4
  133. package/dist/engine/detectors/library-detector-python.js +7 -1
  134. package/dist/engine/detectors/library-detector.js +0 -2
  135. package/dist/engine/detectors/llm-detector/provider-maps.js +3 -2
  136. package/dist/engine/detectors/mcp-candidate-detector.js +12 -16
  137. package/dist/engine/detectors/mfe-detector.js +6 -7
  138. package/dist/engine/detectors/monitoring-detector.js +4 -3
  139. package/dist/engine/detectors/otel-detector.js +3 -2
  140. package/dist/engine/detectors/otel-ecosystem-detectors.d.ts +2 -2
  141. package/dist/engine/detectors/otel-ecosystem-detectors.js +4 -3
  142. package/dist/engine/detectors/platform-specialty-detector.js +3 -5
  143. package/dist/engine/detectors/template-engine-detector.js +3 -4
  144. package/dist/engine/doc-generator/builders.js +2 -3
  145. package/dist/engine/doc-generator/mobile-distribution-guide.js +13 -17
  146. package/dist/engine/doc-generator/portal/dirty-flag-map.d.ts +2 -2
  147. package/dist/engine/doc-generator/portal/portal-regenerator.js +3 -47
  148. package/dist/engine/domain-detector.js +3 -6
  149. package/dist/engine/dynamic-knowledge/knowledge-cache.js +3 -4
  150. package/dist/engine/dynamic-knowledge/knowledge-merger.js +17 -2
  151. package/dist/engine/dynamic-knowledge/web-researcher.js +15 -14
  152. package/dist/engine/dynamic-migration-detector/manifest-readers-extended.js +0 -2
  153. package/dist/engine/e2e-test-generator.js +4 -3
  154. package/dist/engine/ecosystem-absorber/knowledge-cache.js +2 -1
  155. package/dist/engine/ecosystem-absorber/platform-crawler.js +2 -2
  156. package/dist/engine/escalator/retry-counter.js +2 -1
  157. package/dist/engine/evidence-gates/artifact-reader.d.ts +6 -0
  158. package/dist/engine/evidence-gates/artifact-reader.js +105 -21
  159. package/dist/engine/evidence-gates/lifecycle-gate.d.ts +2 -1
  160. package/dist/engine/evidence-gates/lifecycle-gate.js +54 -0
  161. package/dist/engine/execution/context.d.ts +19 -0
  162. package/dist/engine/execution/context.js +127 -0
  163. package/dist/engine/execution/deadline-io.d.ts +21 -0
  164. package/dist/engine/execution/deadline-io.js +45 -0
  165. package/dist/engine/execution/job-executor.d.ts +16 -0
  166. package/dist/engine/execution/job-executor.js +140 -0
  167. package/dist/engine/execution/job-runtime.d.ts +78 -0
  168. package/dist/engine/execution/job-runtime.js +220 -0
  169. package/dist/engine/execution/native-relevance-scorer.d.ts +6 -0
  170. package/dist/engine/execution/native-relevance-scorer.js +64 -0
  171. package/dist/engine/execution/native-worker-dispatch.d.ts +3 -0
  172. package/dist/engine/execution/native-worker-dispatch.js +46 -0
  173. package/dist/engine/execution/native-worker-protocol.d.ts +6 -0
  174. package/dist/engine/execution/native-worker-protocol.js +33 -0
  175. package/dist/engine/execution/native-worker-runtime.d.ts +4 -0
  176. package/dist/engine/execution/native-worker-runtime.js +177 -0
  177. package/dist/engine/execution/native-worker-thread.d.ts +2 -0
  178. package/dist/engine/execution/native-worker-thread.js +66 -0
  179. package/dist/engine/execution/operation-journal.d.ts +66 -0
  180. package/dist/engine/execution/operation-journal.js +260 -0
  181. package/dist/engine/execution/outbox-worker.d.ts +31 -0
  182. package/dist/engine/execution/outbox-worker.js +192 -0
  183. package/dist/engine/execution/validate-job-executor.d.ts +24 -0
  184. package/dist/engine/execution/validate-job-executor.js +342 -0
  185. package/dist/engine/execution/validate-job-payload.d.ts +5 -0
  186. package/dist/engine/execution/validate-job-payload.js +87 -0
  187. package/dist/engine/execution/validate-job-recovery.d.ts +4 -0
  188. package/dist/engine/execution/validate-job-recovery.js +47 -0
  189. package/dist/engine/execution/validate-worker-runtime.d.ts +5 -0
  190. package/dist/engine/execution/validate-worker-runtime.js +100 -0
  191. package/dist/engine/execution/validate-worker-thread.d.ts +2 -0
  192. package/dist/engine/execution/validate-worker-thread.js +71 -0
  193. package/dist/engine/execution-plan/desktop-distribution.js +3 -7
  194. package/dist/engine/execution-plan/mobile-distribution.js +4 -9
  195. package/dist/engine/execution-plan/phases.js +4 -5
  196. package/dist/engine/execution-plan/plan-utils.js +8 -5
  197. package/dist/engine/facilitate/context-loader.js +3 -9
  198. package/dist/engine/figma/code-connect-fetcher.js +9 -8
  199. package/dist/engine/filesystem-watcher/index.d.ts +3 -3
  200. package/dist/engine/filesystem-watcher/index.js +5 -5
  201. package/dist/engine/framework-detector.js +14 -15
  202. package/dist/engine/git/planu-autocommit.js +8 -7
  203. package/dist/engine/git/repository-probe.d.ts +3 -0
  204. package/dist/engine/git/repository-probe.js +13 -0
  205. package/dist/engine/global-rules-manager.js +2 -2
  206. package/dist/engine/handoff-artifacts/io.js +2 -3
  207. package/dist/engine/handoff-artifacts/schemas/red-tests-handoff.js +8 -1
  208. package/dist/engine/handoff-artifacts/schemas.d.ts +4 -0
  209. package/dist/engine/handoff-artifacts/schemas.js +5 -0
  210. package/dist/engine/hook-generator/stack-hook-templates.js +4 -4
  211. package/dist/engine/hooks/config-loader.js +1 -1
  212. package/dist/engine/hooks/context-injector.js +4 -7
  213. package/dist/engine/hooks/file-watcher.js +1 -14
  214. package/dist/engine/hooks-reconciler.js +6 -4
  215. package/dist/engine/infrastructure/component-mapper.js +5 -7
  216. package/dist/engine/infrastructure/docker-compose-generator.js +8 -10
  217. package/dist/engine/infrastructure/index.js +6 -3
  218. package/dist/engine/infrastructure/kubernetes-generator.js +2 -2
  219. package/dist/engine/infrastructure/railway-generator.js +10 -8
  220. package/dist/engine/infrastructure/signal-detector.js +6 -8
  221. package/dist/engine/infrastructure/terraform-generator.js +6 -8
  222. package/dist/engine/legal-compliance/detector.js +3 -2
  223. package/dist/engine/local-first/storage-advisor.js +5 -6
  224. package/dist/engine/macos-keychain-native-port.d.ts +5 -0
  225. package/dist/engine/macos-keychain-native-port.js +26 -0
  226. package/dist/engine/marketplace-fetcher/cache.js +3 -1
  227. package/dist/engine/mcp-config/mcp-config-writer.d.ts +2 -2
  228. package/dist/engine/mcp-config/mcp-config-writer.js +10 -8
  229. package/dist/engine/migration/db-migrator.js +2 -5
  230. package/dist/engine/migration/equivalence-mapper.js +12 -13
  231. package/dist/engine/migration/service-catalogs.js +6 -7
  232. package/dist/engine/migration/service-migrator-catalogs.js +6 -7
  233. package/dist/engine/mobile-detector-ios.js +2 -3
  234. package/dist/engine/mobile-detector.js +16 -4
  235. package/dist/engine/model-router/complexity-analyzer.js +4 -7
  236. package/dist/engine/multi-agent-review/security-analyzer.js +3 -1
  237. package/dist/engine/multi-app-detector/app-type.js +26 -21
  238. package/dist/engine/multi-app-detector/core.js +3 -2
  239. package/dist/engine/multi-teammate-review/disagreement-counter.js +2 -1
  240. package/dist/engine/multi-teammate-review/panel-orchestrator.js +0 -2
  241. package/dist/engine/mutation-config-generator.js +10 -7
  242. package/dist/engine/native-capability-policy.d.ts +4 -0
  243. package/dist/engine/native-capability-policy.js +24 -0
  244. package/dist/engine/native-platform.d.ts +3 -0
  245. package/dist/engine/native-platform.js +44 -0
  246. package/dist/engine/native-runtime-handshake.d.ts +20 -0
  247. package/dist/engine/native-runtime-handshake.js +230 -0
  248. package/dist/engine/network-policy.d.ts +27 -0
  249. package/dist/engine/network-policy.js +174 -0
  250. package/dist/engine/next-spec-resolver/dependency-filter.js +2 -22
  251. package/dist/engine/nfr-profile-detector.js +12 -16
  252. package/dist/engine/nli-keywords.js +8 -9
  253. package/dist/engine/oauth/config-guard.js +4 -5
  254. package/dist/engine/observability/local-execution-spans.d.ts +15 -0
  255. package/dist/engine/observability/local-execution-spans.js +63 -0
  256. package/dist/engine/orchestrator/runtime.js +0 -1
  257. package/dist/engine/package-registry.js +2 -6
  258. package/dist/engine/performance-analyzer.js +2 -5
  259. package/dist/engine/permissions-merger/stack-detectors.js +5 -5
  260. package/dist/engine/planu-core.darwin-arm64.node.manifest.json +39 -0
  261. package/dist/engine/planu-core.darwin-arm64.node.sbom.json +1310 -0
  262. package/dist/engine/planu-core.darwin-x64.node.manifest.json +39 -0
  263. package/dist/engine/planu-core.darwin-x64.node.sbom.json +1310 -0
  264. package/dist/engine/planu-core.linux-arm64-gnu.node.manifest.json +38 -0
  265. package/dist/engine/planu-core.linux-arm64-gnu.node.sbom.json +1310 -0
  266. package/dist/engine/planu-core.linux-arm64-musl.node.manifest.json +38 -0
  267. package/dist/engine/planu-core.linux-arm64-musl.node.sbom.json +1310 -0
  268. package/dist/engine/planu-core.linux-x64-gnu.node.manifest.json +38 -0
  269. package/dist/engine/planu-core.linux-x64-gnu.node.sbom.json +1310 -0
  270. package/dist/engine/planu-core.linux-x64-musl.node.manifest.json +38 -0
  271. package/dist/engine/planu-core.linux-x64-musl.node.sbom.json +1310 -0
  272. package/dist/engine/planu-core.win32-arm64-msvc.node.manifest.json +38 -0
  273. package/dist/engine/planu-core.win32-arm64-msvc.node.sbom.json +1310 -0
  274. package/dist/engine/planu-core.win32-x64-msvc.node.manifest.json +38 -0
  275. package/dist/engine/planu-core.win32-x64-msvc.node.sbom.json +1310 -0
  276. package/dist/engine/platform-detector/desktop.js +15 -2
  277. package/dist/engine/platform-detector/extensions.js +2 -1
  278. package/dist/engine/platform-detector/games.js +2 -1
  279. package/dist/engine/platform-detector.js +3 -2
  280. package/dist/engine/platform-engineering/idp-detector.js +2 -1
  281. package/dist/engine/plugin-installer/stack-matcher.js +9 -17
  282. package/dist/engine/plugins/lifecycle.js +6 -2
  283. package/dist/engine/prior-decisions/contradiction-detector.js +60 -30
  284. package/dist/engine/project-dna/stack-detector.js +15 -17
  285. package/dist/engine/project-graph/builder.js +11 -0
  286. package/dist/engine/project-graph/cache.js +1 -1
  287. package/dist/engine/project-graph/freshness-projection.d.ts +16 -0
  288. package/dist/engine/project-graph/freshness-projection.js +95 -0
  289. package/dist/engine/project-graph/index.d.ts +1 -0
  290. package/dist/engine/project-graph/index.js +1 -0
  291. package/dist/engine/project-graph/query.js +15 -25
  292. package/dist/engine/project-health-checker.js +3 -4
  293. package/dist/engine/project-scanner/stack-detector.js +17 -17
  294. package/dist/engine/property-test-generator.js +2 -3
  295. package/dist/engine/qa-gate.d.ts +1 -0
  296. package/dist/engine/qa-gate.js +6 -4
  297. package/dist/engine/quality-gates/gate-catalog.js +47 -46
  298. package/dist/engine/quality-gates/gate-injector.js +9 -4
  299. package/dist/engine/registry/core.js +0 -2
  300. package/dist/engine/registry/loader.js +9 -12
  301. package/dist/engine/registry/matcher.js +129 -24
  302. package/dist/engine/resilience-detector/concurrency-detector.js +4 -4
  303. package/dist/engine/resilience-detector/middleware-detector.js +11 -13
  304. package/dist/engine/resilience-detector/validation-detector.js +17 -4
  305. package/dist/engine/reverse-engineer/config-analyzer.js +9 -8
  306. package/dist/engine/reverse-engineer/orchestrator.js +5 -9
  307. package/dist/engine/reverse-engineer/test-file-parser.js +6 -3
  308. package/dist/engine/rules-generator/index.js +6 -5
  309. package/dist/engine/runtime-policy.d.ts +7 -0
  310. package/dist/engine/runtime-policy.js +101 -0
  311. package/dist/engine/runtime-security/checkers/content-security.js +21 -6
  312. package/dist/engine/runtime-security/checkers/file-permissions.js +0 -2
  313. package/dist/engine/safety/atomic-write-file.js +20 -9
  314. package/dist/engine/safety/atomic-writer.js +10 -3
  315. package/dist/engine/safety/cross-process-lock.d.ts +3 -40
  316. package/dist/engine/safety/cross-process-lock.js +268 -272
  317. package/dist/engine/safety/file-mutex.d.ts +2 -9
  318. package/dist/engine/safety/file-mutex.js +155 -87
  319. package/dist/engine/safety/health-monitor.js +15 -6
  320. package/dist/engine/safety/lock-lease-store.d.ts +79 -0
  321. package/dist/engine/safety/lock-lease-store.js +372 -0
  322. package/dist/engine/safety/lock-scavenger.d.ts +2 -5
  323. package/dist/engine/safety/lock-scavenger.js +158 -76
  324. package/dist/engine/safety/lock-staleness.js +4 -1
  325. package/dist/engine/safety/obsolete-lock-guard.d.ts +8 -0
  326. package/dist/engine/safety/obsolete-lock-guard.js +31 -0
  327. package/dist/engine/safety/transaction.js +3 -3
  328. package/dist/engine/sandbox/index.js +2 -1
  329. package/dist/engine/sandbox/runner-detect.js +3 -2
  330. package/dist/engine/sandbox/runner-docker.js +4 -3
  331. package/dist/engine/scan-project/module-discoverer.js +3 -2
  332. package/dist/engine/schema-generator.js +16 -9
  333. package/dist/engine/security-analyzer/criteria-generator.js +2 -3
  334. package/dist/engine/self-healing/healer.js +4 -4
  335. package/dist/engine/session-safeguard/learnings-buffer.d.ts +1 -2
  336. package/dist/engine/session-safeguard/learnings-buffer.js +42 -65
  337. package/dist/engine/shared-agent-memory.js +66 -74
  338. package/dist/engine/skill-adapter/command-rewriter.js +3 -2
  339. package/dist/engine/skill-adapter/index.js +3 -3
  340. package/dist/engine/skill-adapter/placeholder-map.js +3 -2
  341. package/dist/engine/skill-bootstrap/stack-matcher.js +47 -48
  342. package/dist/engine/skill-generation/stack-content-generator.js +0 -2
  343. package/dist/engine/skill-generator/workflow-skill-generator.js +2 -1
  344. package/dist/engine/skill-registry/ttl-refresh.js +3 -1
  345. package/dist/engine/skills/skills-fetcher.js +3 -6
  346. package/dist/engine/skills-reconciler.js +19 -39
  347. package/dist/engine/spec-coverage/test-finder.js +7 -6
  348. package/dist/engine/spec-diff-engine.js +3 -3
  349. package/dist/engine/spec-generator/api-key-resolver.d.ts +1 -1
  350. package/dist/engine/spec-generator/api-key-resolver.js +3 -24
  351. package/dist/engine/spec-generators/issue-extractor.js +9 -3
  352. package/dist/engine/spec-migrator/drift-detector.js +5 -13
  353. package/dist/engine/spec-migrator/filesystem-import.js +14 -10
  354. package/dist/engine/spec-migrator/planu-canonical-policy.js +10 -1
  355. package/dist/engine/spec-migrator/strict-planu-cleanup.js +24 -25
  356. package/dist/engine/spec-registry/adapter.d.ts +0 -5
  357. package/dist/engine/spec-registry/adapter.js +45 -46
  358. package/dist/engine/spec-registry/client.js +2 -0
  359. package/dist/engine/spec-source-sync.js +3 -2
  360. package/dist/engine/spec-templates/custom-loader.js +2 -3
  361. package/dist/engine/spec-templates/templates-domain-specific.js +8 -5
  362. package/dist/engine/spec-templates/templates-perf-integration.js +2 -3
  363. package/dist/engine/stack-auditor/manifest-reader.js +0 -2
  364. package/dist/engine/staleness/stale-implementing.js +7 -7
  365. package/dist/engine/tdd-scaffold-generator.js +24 -11
  366. package/dist/engine/teammate-router/green-phase-verifier.js +2 -1
  367. package/dist/engine/teammate-router/red-phase-verifier.js +2 -1
  368. package/dist/engine/technology-registry.d.ts +11 -0
  369. package/dist/engine/technology-registry.js +142 -0
  370. package/dist/engine/telemetry/error-reporter.d.ts +1 -2
  371. package/dist/engine/telemetry/error-reporter.js +11 -18
  372. package/dist/engine/telemetry/health-checker.js +5 -14
  373. package/dist/engine/telemetry/index.d.ts +0 -1
  374. package/dist/engine/telemetry/index.js +0 -1
  375. package/dist/engine/telemetry/stance.js +3 -2
  376. package/dist/engine/telemetry/telemetry-client.d.ts +1 -5
  377. package/dist/engine/telemetry/telemetry-client.js +45 -29
  378. package/dist/engine/telemetry/telemetry-store.d.ts +3 -3
  379. package/dist/engine/telemetry/telemetry-store.js +30 -23
  380. package/dist/engine/test-framework-detector/detectors.js +8 -8
  381. package/dist/engine/test-framework-detector/strategy.js +8 -9
  382. package/dist/engine/test-generators/agent-test-templates.js +2 -3
  383. package/dist/engine/test-generators/contract-test-generator.d.ts +1 -1
  384. package/dist/engine/test-generators/contract-test-generator.js +9 -202
  385. package/dist/engine/test-generators/platform-test-templates-b.js +2 -3
  386. package/dist/engine/test-generators/platform-test-templates.js +2 -5
  387. package/dist/engine/test-mocks-generator.js +4 -3
  388. package/dist/engine/test-plan-generator.js +30 -12
  389. package/dist/engine/test-scaffold-generator/advanced-scaffold.js +4 -5
  390. package/dist/engine/test-scaffold-generator/unit-scaffold.js +5 -6
  391. package/dist/engine/timing/budget.d.ts +6 -17
  392. package/dist/engine/timing/budget.js +80 -64
  393. package/dist/engine/tool-groups/group-manager.js +3 -3
  394. package/dist/engine/universal-rules/installer.js +1 -1
  395. package/dist/engine/universal-rules/rules/planu-modes.js +2 -0
  396. package/dist/engine/universal-rules/rules/planu-release-policy.js +1 -0
  397. package/dist/engine/update-notifier.js +8 -5
  398. package/dist/engine/validation/approved-spec-portability.d.ts +12 -0
  399. package/dist/engine/validation/approved-spec-portability.js +107 -0
  400. package/dist/engine/validation/durable-validation.d.ts +36 -0
  401. package/dist/engine/validation/durable-validation.js +335 -0
  402. package/dist/engine/validation/validation-freshness.d.ts +36 -0
  403. package/dist/engine/validation/validation-freshness.js +427 -0
  404. package/dist/engine/validation/validation-receipt-codec.d.ts +13 -0
  405. package/dist/engine/validation/validation-receipt-codec.js +182 -0
  406. package/dist/engine/validation/validation-receipt.d.ts +59 -0
  407. package/dist/engine/validation/validation-receipt.js +282 -0
  408. package/dist/engine/validation/validation-source-policy.d.ts +4 -0
  409. package/dist/engine/validation/validation-source-policy.js +16 -0
  410. package/dist/engine/validation/validation-submission.d.ts +36 -0
  411. package/dist/engine/validation/validation-submission.js +128 -0
  412. package/dist/engine/validation-evidence-ledger.js +41 -0
  413. package/dist/engine/validation-impact-planner.js +25 -9
  414. package/dist/engine/validator/spec-compliance-runner.d.ts +1 -1
  415. package/dist/engine/validator/spec-compliance-runner.js +17 -8
  416. package/dist/engine/validator/validation-report-writer.js +1 -1
  417. package/dist/engine/validator.js +2 -1
  418. package/dist/engine/verify-integrations/index.js +1 -1
  419. package/dist/engine/version-resolver.js +5 -6
  420. package/dist/engine/web-fetcher/stack-advisor.js +156 -92
  421. package/dist/engine/web-fetcher/stack-detector.js +114 -54
  422. package/dist/engine/workspace-manager.js +3 -2
  423. package/dist/errors/classified-degradation.d.ts +3 -0
  424. package/dist/errors/classified-degradation.js +10 -0
  425. package/dist/errors/degradation-sink.d.ts +3 -0
  426. package/dist/errors/degradation-sink.js +5 -0
  427. package/dist/errors/error-taxonomy.d.ts +12 -0
  428. package/dist/errors/error-taxonomy.js +62 -0
  429. package/dist/hosts/claude-code/ux/mcp-prompts.js +10 -4
  430. package/dist/hosts/claude-code/ux/mcp-resources.js +4 -2
  431. package/dist/hosts/codex/config-scaffold.js +4 -3
  432. package/dist/hosts/gemini/config-scaffold.js +2 -1
  433. package/dist/hosts/gemini/multimodal-spec-flow.js +7 -4
  434. package/dist/index.js +21 -6
  435. package/dist/resources/patterns.js +3 -1
  436. package/dist/resources/specs.js +3 -1
  437. package/dist/resources/templates.js +3 -1
  438. package/dist/security/adapters/environment.d.ts +12 -0
  439. package/dist/security/adapters/environment.js +25 -0
  440. package/dist/security/adapters/linux-secret-service.d.ts +8 -0
  441. package/dist/security/adapters/linux-secret-service.js +60 -0
  442. package/dist/security/adapters/macos-keychain.d.ts +18 -0
  443. package/dist/security/adapters/macos-keychain.js +90 -0
  444. package/dist/security/adapters/windows-credential-manager.d.ts +8 -0
  445. package/dist/security/adapters/windows-credential-manager.js +58 -0
  446. package/dist/security/redactor.d.ts +5 -0
  447. package/dist/security/redactor.js +58 -0
  448. package/dist/security/secret-field.d.ts +5 -0
  449. package/dist/security/secret-field.js +17 -0
  450. package/dist/security/secret-migration.d.ts +3 -0
  451. package/dist/security/secret-migration.js +123 -0
  452. package/dist/security/secret-provider.d.ts +23 -0
  453. package/dist/security/secret-provider.js +145 -0
  454. package/dist/security/secure-json.d.ts +3 -0
  455. package/dist/security/secure-json.js +29 -0
  456. package/dist/storage/api-surfaces-store.js +2 -2
  457. package/dist/storage/approval-operation-lock.d.ts +1 -1
  458. package/dist/storage/approval-operation-lock.js +5 -3
  459. package/dist/storage/audit-trail-store.d.ts +1 -1
  460. package/dist/storage/audit-trail-store.js +48 -62
  461. package/dist/storage/autopilot-log-store.js +12 -5
  462. package/dist/storage/base-store.d.ts +8 -8
  463. package/dist/storage/base-store.js +57 -20
  464. package/dist/storage/checkpoint-store.js +5 -2
  465. package/dist/storage/comments-store.js +2 -2
  466. package/dist/storage/compliance-audit-store.js +5 -2
  467. package/dist/storage/compliance-gate-config-store.js +7 -4
  468. package/dist/storage/compliance-store.js +2 -2
  469. package/dist/storage/context-profile-store.js +2 -2
  470. package/dist/storage/crash-shield-store.js +8 -4
  471. package/dist/storage/feedback-store.js +10 -6
  472. package/dist/storage/figma-store.js +8 -4
  473. package/dist/storage/file-mutex.js +9 -1
  474. package/dist/storage/gaps-log.js +7 -4
  475. package/dist/storage/global-projects-store.js +4 -2
  476. package/dist/storage/ideas-store.js +2 -2
  477. package/dist/storage/index.d.ts +5 -0
  478. package/dist/storage/index.js +5 -0
  479. package/dist/storage/knowledge-store/knowledge.js +27 -33
  480. package/dist/storage/lessons-store.js +2 -2
  481. package/dist/storage/license-store.js +13 -41
  482. package/dist/storage/migrations/canonical-storage.d.ts +15 -0
  483. package/dist/storage/migrations/canonical-storage.js +599 -0
  484. package/dist/storage/oauth-store.js +36 -8
  485. package/dist/storage/path-resolver.js +16 -3
  486. package/dist/storage/pr-store.js +2 -2
  487. package/dist/storage/project-drift-store.js +20 -8
  488. package/dist/storage/project-identity.d.ts +32 -0
  489. package/dist/storage/project-identity.js +194 -0
  490. package/dist/storage/project-resolver.js +14 -7
  491. package/dist/storage/release-notes-store.js +2 -6
  492. package/dist/storage/runtime-db.d.ts +186 -0
  493. package/dist/storage/runtime-db.js +1054 -0
  494. package/dist/storage/schema-registry.d.ts +5 -0
  495. package/dist/storage/schema-registry.js +74 -0
  496. package/dist/storage/sentry-store.js +20 -9
  497. package/dist/storage/session-state-store.js +12 -5
  498. package/dist/storage/session-store.js +12 -4
  499. package/dist/storage/skill-registry-storage.d.ts +1 -1
  500. package/dist/storage/skill-registry-storage.js +13 -11
  501. package/dist/storage/slack-store.js +10 -5
  502. package/dist/storage/spec-store.js +31 -24
  503. package/dist/storage/status-store/file-lock.js +31 -9
  504. package/dist/storage/status-store/self-healing.js +10 -5
  505. package/dist/storage/status-store/version-sync.js +8 -6
  506. package/dist/storage/steering-store.js +2 -2
  507. package/dist/storage/storage-bundle.d.ts +5 -0
  508. package/dist/storage/storage-bundle.js +117 -0
  509. package/dist/storage/storage-catalog-validation.d.ts +3 -0
  510. package/dist/storage/storage-catalog-validation.js +20 -0
  511. package/dist/storage/storage-catalog.d.ts +25 -0
  512. package/dist/storage/storage-catalog.js +390 -0
  513. package/dist/storage/storage-layout.d.ts +24 -0
  514. package/dist/storage/storage-layout.js +101 -0
  515. package/dist/storage/storybook-store.js +2 -2
  516. package/dist/storage/supabase-store.js +24 -6
  517. package/dist/storage/tdd-policy-store.js +8 -6
  518. package/dist/storage/tech-debt-store.js +3 -3
  519. package/dist/storage/technology-selection-store.d.ts +1 -1
  520. package/dist/storage/technology-selection-store.js +6 -3
  521. package/dist/storage/token-cache-store.js +3 -3
  522. package/dist/storage/token-ledger-store.js +13 -8
  523. package/dist/storage/transition-log.js +7 -4
  524. package/dist/storage/trash-store.js +15 -6
  525. package/dist/storage/vector-store/migrator.js +7 -2
  526. package/dist/storage/vector-store/sqlite-adapter.js +4 -1
  527. package/dist/storage/webhook-server-store.js +2 -2
  528. package/dist/tools/api-spec-generator-handler.js +3 -2
  529. package/dist/tools/auto-update-handler.d.ts +1 -1
  530. package/dist/tools/auto-update-handler.js +1 -1
  531. package/dist/tools/browser-validate-handler.js +2 -1
  532. package/dist/tools/challenge-spec/platform-challenge-scenarios-b.js +8 -5
  533. package/dist/tools/challenge-spec/scenarios-desktop.js +8 -3
  534. package/dist/tools/challenge-spec/scenarios-failure.js +7 -2
  535. package/dist/tools/challenge-spec/security-challenge-scenarios.js +3 -3
  536. package/dist/tools/clarify-requirements/multiple-choice.js +53 -41
  537. package/dist/tools/comments-handler.js +2 -3
  538. package/dist/tools/compliance-test-handler.js +2 -2
  539. package/dist/tools/configure-telemetry.js +11 -11
  540. package/dist/tools/create-spec/auto-pipeline.js +13 -1
  541. package/dist/tools/create-spec/autopilot-analyzer.d.ts +1 -1
  542. package/dist/tools/create-spec/autopilot-analyzer.js +2 -4
  543. package/dist/tools/create-spec/mcp-tool-contract.d.ts +10 -4
  544. package/dist/tools/create-spec/mcp-tool-contract.js +7 -36
  545. package/dist/tools/create-spec/post-creation.d.ts +2 -1
  546. package/dist/tools/create-spec/post-creation.js +56 -54
  547. package/dist/tools/create-spec/relevance-scorer.d.ts +1 -1
  548. package/dist/tools/create-spec/relevance-scorer.js +17 -1
  549. package/dist/tools/create-spec/spec-builder.js +2 -12
  550. package/dist/tools/create-spec/spec-created-outbox-consumer.d.ts +14 -0
  551. package/dist/tools/create-spec/spec-created-outbox-consumer.js +176 -0
  552. package/dist/tools/create-spec.js +385 -520
  553. package/dist/tools/define-ui-contract/agent-interaction-contract.js +2 -4
  554. package/dist/tools/define-ui-contract-desktop/desktop-contract.js +12 -4
  555. package/dist/tools/define-ui-contract-desktop/native-contract.js +7 -3
  556. package/dist/tools/define-ui-contract-extensions.js +2 -3
  557. package/dist/tools/define-ui-contract-mobile.js +5 -9
  558. package/dist/tools/define-ui-contract-web/component-tree.js +4 -3
  559. package/dist/tools/define-ui-contract.js +7 -4
  560. package/dist/tools/deploy/deploy-spec.js +2 -4
  561. package/dist/tools/deploy/deploy-status.js +2 -4
  562. package/dist/tools/design-schema/nosql-category-schemas.js +2 -3
  563. package/dist/tools/design-schema-sql/migrations.js +3 -2
  564. package/dist/tools/design-schema-sql/tables.js +4 -1
  565. package/dist/tools/design-schema.js +4 -3
  566. package/dist/tools/feedback-handler.js +2 -4
  567. package/dist/tools/gc-data-projects.js +5 -5
  568. package/dist/tools/generate-execution-plan.js +3 -4
  569. package/dist/tools/generate-sub-agent.js +2 -1
  570. package/dist/tools/generate-tests/generators/a11y-tests-generator.js +5 -4
  571. package/dist/tools/generate-tests/generators/advanced-testing-generator.js +5 -4
  572. package/dist/tools/generate-tests/generators/concurrency-test-generator/js-templates.js +9 -4
  573. package/dist/tools/generate-tests/generators/concurrency-test-generator.js +8 -4
  574. package/dist/tools/generate-tests/generators/database/detectors.js +9 -3
  575. package/dist/tools/generate-tests/generators/database/index.js +2 -4
  576. package/dist/tools/generate-tests/generators/event-test-generator.js +5 -4
  577. package/dist/tools/generate-tests/generators/game-tests-generator.js +2 -1
  578. package/dist/tools/generate-tests/generators/graphql-test-generator.js +11 -5
  579. package/dist/tools/generate-tests/generators/grpc-test-generator.js +2 -3
  580. package/dist/tools/generate-tests/generators/llm-security-test-generator.js +4 -3
  581. package/dist/tools/generate-tests/generators/local-first-test-generator.js +4 -3
  582. package/dist/tools/generate-tests/generators/mcp-tests-generator.js +11 -9
  583. package/dist/tools/generate-tests/generators/microservices/index.js +2 -3
  584. package/dist/tools/generate-tests/generators/otel-test-generator.js +6 -3
  585. package/dist/tools/generate-tests/generators/security/detectors.js +2 -5
  586. package/dist/tools/generate-tests/generators/security/index.js +2 -4
  587. package/dist/tools/generate-tests/generators/supply-chain-test-generator.js +2 -3
  588. package/dist/tools/generate-tests/generators/visual-regression-generator.js +14 -17
  589. package/dist/tools/generate-tests/generators/websocket-test-generator.js +2 -3
  590. package/dist/tools/generate-tests/test-helpers.js +11 -12
  591. package/dist/tools/generate-tests-content.js +4 -3
  592. package/dist/tools/generate-tests.js +7 -4
  593. package/dist/tools/git/git-helpers.d.ts +0 -2
  594. package/dist/tools/git/git-helpers.js +7 -7
  595. package/dist/tools/github-pr-handler.js +10 -3
  596. package/dist/tools/heal-spec-docs.js +6 -53
  597. package/dist/tools/hook-generator-handler.js +6 -6
  598. package/dist/tools/init-constitution/platform-principles.js +4 -2
  599. package/dist/tools/init-project/agents-md-writer.js +14 -5
  600. package/dist/tools/init-project/claude-md-generator.js +19 -12
  601. package/dist/tools/init-project/handler.js +165 -73
  602. package/dist/tools/init-project/host-assets-writer.d.ts +1 -1
  603. package/dist/tools/init-project/host-assets-writer.js +4 -2
  604. package/dist/tools/init-project/lifecycle-helpers.js +3 -5
  605. package/dist/tools/init-project/lint-scaffolder.js +6 -2
  606. package/dist/tools/init-project/migration-runner.d.ts +10 -1
  607. package/dist/tools/init-project/migration-runner.js +68 -3
  608. package/dist/tools/init-project/per-client-files-writer.js +14 -4
  609. package/dist/tools/init-project/rules-generator.js +10 -2
  610. package/dist/tools/init-project/scaffold-writer.d.ts +1 -1
  611. package/dist/tools/init-project/scaffold-writer.js +17 -15
  612. package/dist/tools/jobs/handlers.d.ts +15 -0
  613. package/dist/tools/jobs/handlers.js +126 -0
  614. package/dist/tools/list-specs.js +35 -34
  615. package/dist/tools/manage-plugins-handler.js +17 -9
  616. package/dist/tools/migrate-tech/advanced-handlers.js +3 -2
  617. package/dist/tools/migrate-tech/build-tool-handlers.js +3 -2
  618. package/dist/tools/migrate-tech/core-handlers.js +5 -2
  619. package/dist/tools/migrate-tech/data-handlers.js +6 -3
  620. package/dist/tools/migrate-tech-advanced/rollback-handlers.js +3 -2
  621. package/dist/tools/migrate-tech-advanced/service-handlers.js +5 -2
  622. package/dist/tools/oauth-handler.js +7 -1
  623. package/dist/tools/register-sdd-tools.d.ts +1 -1
  624. package/dist/tools/register-sdd-tools.js +5 -0
  625. package/dist/tools/register-spec-tools/core-spec-tools.js +31 -0
  626. package/dist/tools/registry/auth.js +13 -5
  627. package/dist/tools/registry/publish.js +7 -4
  628. package/dist/tools/resolve-project-path.d.ts +2 -2
  629. package/dist/tools/resolve-project-path.js +7 -7
  630. package/dist/tools/reverse-engineer/analyzer.js +14 -14
  631. package/dist/tools/rollback-release.js +3 -2
  632. package/dist/tools/safe-handler.js +295 -171
  633. package/dist/tools/schema-generator-handler.js +2 -1
  634. package/dist/tools/schemas/output-schemas.d.ts +88 -82
  635. package/dist/tools/schemas/output-schemas.js +12 -94
  636. package/dist/tools/schemas/plugins-schemas.js +0 -2
  637. package/dist/tools/schemas/registry.js +0 -2
  638. package/dist/tools/schemas/skill-registry-schemas.js +0 -2
  639. package/dist/tools/schemas/validate-output-schema.d.ts +256 -0
  640. package/dist/tools/schemas/validate-output-schema.js +212 -0
  641. package/dist/tools/sentry-handler.js +6 -1
  642. package/dist/tools/skill-bootstrap-handler.js +7 -4
  643. package/dist/tools/status-handler.js +4 -0
  644. package/dist/tools/storage-bundle-handler.d.ts +9 -0
  645. package/dist/tools/storage-bundle-handler.js +29 -0
  646. package/dist/tools/storage-paths-handler.d.ts +9 -0
  647. package/dist/tools/storage-paths-handler.js +17 -0
  648. package/dist/tools/suggest-mcp-server.js +11 -5
  649. package/dist/tools/suggest-mcps.js +29 -9
  650. package/dist/tools/suggest-tooling/advanced-testing-catalog.js +4 -5
  651. package/dist/tools/suggest-tooling/build-tool-catalog.js +2 -1
  652. package/dist/tools/suggest-tooling/css-framework-catalog.js +13 -7
  653. package/dist/tools/suggest-tooling/framework-catalog.js +3 -5
  654. package/dist/tools/suggest-tooling/frontend-perf-catalog.js +2 -6
  655. package/dist/tools/suggest-tooling/handler.js +10 -4
  656. package/dist/tools/suggest-tooling/hypermedia-catalog.js +11 -3
  657. package/dist/tools/suggest-tooling/linting-catalog.js +4 -7
  658. package/dist/tools/suggest-tooling/llm-security-catalog.js +2 -1
  659. package/dist/tools/suggest-tooling/local-first-catalog.js +7 -5
  660. package/dist/tools/suggest-tooling/observability-catalog.js +3 -4
  661. package/dist/tools/suggest-tooling/otel-catalog.js +4 -1
  662. package/dist/tools/suggest-tooling/resilience-catalog.js +16 -5
  663. package/dist/tools/suggest-tooling/skills-catalog.js +10 -9
  664. package/dist/tools/suggest-tooling/supply-chain-catalog.js +2 -3
  665. package/dist/tools/supabase-handler.js +2 -1
  666. package/dist/tools/token-intelligence-handler.js +2 -2
  667. package/dist/tools/token-recording.js +2 -2
  668. package/dist/tools/token-savings-handler.js +2 -2
  669. package/dist/tools/tool-registry/core-tools.js +131 -0
  670. package/dist/tools/tool-registry/group-infra.js +10 -12
  671. package/dist/tools/tool-registry/group-quality-compliance.js +5 -12
  672. package/dist/tools/update-status/approval-gates.d.ts +13 -0
  673. package/dist/tools/update-status/approval-gates.js +81 -0
  674. package/dist/tools/update-status/batch.js +4 -2
  675. package/dist/tools/update-status/dod-gates.d.ts +6 -24
  676. package/dist/tools/update-status/dod-gates.js +60 -135
  677. package/dist/tools/update-status/done-receipt-verifier.d.ts +15 -0
  678. package/dist/tools/update-status/done-receipt-verifier.js +145 -0
  679. package/dist/tools/update-status/evidence-gate.js +154 -2
  680. package/dist/tools/update-status/file-sync.js +23 -12
  681. package/dist/tools/update-status/gate-harness.d.ts +7 -0
  682. package/dist/tools/update-status/gate-harness.js +8 -0
  683. package/dist/tools/update-status/index.js +228 -325
  684. package/dist/tools/update-status/qa-gate.d.ts +1 -1
  685. package/dist/tools/update-status/qa-gate.js +2 -2
  686. package/dist/tools/update-status/side-effects.js +30 -37
  687. package/dist/tools/update-status/transition-guard.d.ts +4 -2
  688. package/dist/tools/update-status/transition-guard.js +57 -10
  689. package/dist/tools/update-status-convention-gate.js +24 -23
  690. package/dist/tools/update-status-reconcile.js +2 -2
  691. package/dist/tools/validate-api-contract-handler.js +3 -3
  692. package/dist/tools/validate-lint.js +20 -13
  693. package/dist/tools/validate.d.ts +3 -1
  694. package/dist/tools/validate.js +213 -5
  695. package/dist/transports/http-transport.js +84 -61
  696. package/dist/transports/middleware/with-telemetry.js +3 -2
  697. package/dist/types/abortable-process.d.ts +2 -0
  698. package/dist/types/advanced-framework.js +0 -2
  699. package/dist/types/atomic-upgrade.d.ts +71 -0
  700. package/dist/types/atomic-upgrade.js +2 -0
  701. package/dist/types/ci.js +0 -2
  702. package/dist/types/core-bridge.d.ts +78 -1
  703. package/dist/types/crash-shield-framework-rules.d.ts +24 -0
  704. package/dist/types/crash-shield-framework-rules.js +2 -0
  705. package/dist/types/data-gc.d.ts +16 -0
  706. package/dist/types/deploy.js +0 -2
  707. package/dist/types/durable-job.d.ts +78 -0
  708. package/dist/types/durable-job.js +2 -0
  709. package/dist/types/durable-validation.d.ts +60 -0
  710. package/dist/types/durable-validation.js +2 -0
  711. package/dist/types/estimation.d.ts +2 -0
  712. package/dist/types/evidence-gates.d.ts +9 -1
  713. package/dist/types/execution.d.ts +43 -0
  714. package/dist/types/handoff-artifacts.d.ts +2 -0
  715. package/dist/types/index.d.ts +2 -0
  716. package/dist/types/index.js +2 -0
  717. package/dist/types/infrastructure.js +0 -2
  718. package/dist/types/lifecycle.js +0 -2
  719. package/dist/types/migration/canonical-storage.d.ts +37 -0
  720. package/dist/types/migration/canonical-storage.js +2 -0
  721. package/dist/types/migration/index.d.ts +1 -1
  722. package/dist/types/native-worker.d.ts +48 -0
  723. package/dist/types/native-worker.js +2 -0
  724. package/dist/types/network-policy.d.ts +12 -0
  725. package/dist/types/network-policy.js +2 -0
  726. package/dist/types/oauth.js +0 -2
  727. package/dist/types/observability.d.ts +32 -0
  728. package/dist/types/outbox-worker.d.ts +35 -0
  729. package/dist/types/outbox-worker.js +11 -0
  730. package/dist/types/permissions-config.d.ts +0 -27
  731. package/dist/types/permissions-config.js +0 -2
  732. package/dist/types/plugin-install.d.ts +0 -11
  733. package/dist/types/plugin-install.js +0 -2
  734. package/dist/types/portal.d.ts +1 -0
  735. package/dist/types/product-public.d.ts +75 -0
  736. package/dist/types/product-public.js +2 -0
  737. package/dist/types/project/inputs.d.ts +2 -0
  738. package/dist/types/project/mfe-detection.js +0 -2
  739. package/dist/types/project/platform-mobile.js +0 -2
  740. package/dist/types/project/platform-specialty.js +0 -2
  741. package/dist/types/project-knowledge-graph.d.ts +7 -0
  742. package/dist/types/runtime-database.d.ts +10 -0
  743. package/dist/types/runtime-database.js +2 -0
  744. package/dist/types/runtime-policy.d.ts +40 -0
  745. package/dist/types/runtime-policy.js +2 -0
  746. package/dist/types/safety.d.ts +4 -5
  747. package/dist/types/schema-registry.d.ts +12 -0
  748. package/dist/types/schema-registry.js +2 -0
  749. package/dist/types/security.d.ts +52 -0
  750. package/dist/types/skill-registry.js +0 -2
  751. package/dist/types/spec/inputs.d.ts +2 -0
  752. package/dist/types/spec-lock-v2.d.ts +13 -7
  753. package/dist/types/spec-lock-v2.js +1 -1
  754. package/dist/types/spec-registry.js +0 -2
  755. package/dist/types/storage-bundle.d.ts +13 -0
  756. package/dist/types/storage-bundle.js +2 -0
  757. package/dist/types/storage-catalog.d.ts +18 -0
  758. package/dist/types/storage-catalog.js +2 -0
  759. package/dist/types/team-planner.js +0 -2
  760. package/dist/types/technology-registry.d.ts +35 -0
  761. package/dist/types/technology-registry.js +2 -0
  762. package/dist/types/technology-symbols.generated.d.ts +117 -0
  763. package/dist/types/technology-symbols.generated.js +2 -0
  764. package/dist/types/telemetry.d.ts +3 -3
  765. package/dist/types/transport.d.ts +2 -0
  766. package/dist/types/validate-worker.d.ts +44 -0
  767. package/dist/types/validate-worker.js +2 -0
  768. package/dist/types/validation-evidence.d.ts +1 -1
  769. package/dist/types/validation-receipt.d.ts +104 -0
  770. package/dist/types/validation-receipt.js +2 -0
  771. package/package.json +31 -20
  772. package/planu-native.json +1 -1
  773. package/planu-plugin.json +1 -1
  774. package/dist/engine/telemetry/geo-resolver.d.ts +0 -9
  775. package/dist/engine/telemetry/geo-resolver.js +0 -43
  776. package/dist/storage/data-dir-discovery.d.ts +0 -31
  777. package/dist/storage/data-dir-discovery.js +0 -140
  778. package/dist/storage/migrations/cwd-to-absolute.d.ts +0 -25
  779. package/dist/storage/migrations/cwd-to-absolute.js +0 -281
  780. package/dist/tools/create-spec/adapters/prior-decisions-hint.d.ts +0 -14
  781. package/dist/tools/create-spec/adapters/prior-decisions-hint.js +0 -30
  782. package/dist/tools/init-project/ancestor-data-detector.d.ts +0 -22
  783. package/dist/tools/init-project/ancestor-data-detector.js +0 -81
  784. package/dist/tools/update-status/force-done-audit.d.ts +0 -2
  785. package/dist/tools/update-status/force-done-audit.js +0 -23
  786. package/dist/types/migration/cwd-to-absolute.d.ts +0 -8
  787. package/dist/types/migration/cwd-to-absolute.js +0 -3
@@ -1,219 +1,137 @@
1
- // Next.js: getServerSideProps without try/catch
2
- const NEXT_GSP = /export\s+(?:const|async\s+function|function)\s+getServerSideProps/;
3
- const HAS_TRY = /\btry\s*\{/;
4
- // Express: async route handler without error handling
5
- const EXPRESS_ASYNC_ROUTE = /(?:app|router)\.\w+\s*\([^,)]+,\s*async\s*(?:\([^)]*\)|[a-z]+)\s*=>/;
6
- const HAS_CATCH_OR_NEXT = /(?:\.catch\s*\(|next\s*\(\s*(?:err|error)|\btry\s*\{)/;
7
- // Prisma: findUnique/findFirst without null check
8
- const PRISMA_FIND = /await\s+\w+\.\w+\.(?:findUnique|findFirst)\s*\(/;
9
- // Matches: if (!result), if (result === null), if (result !== null), result ?? fallback
10
- const PRISMA_NULL_CHECK = /(?:if\s*\(\s*!\s*\w+|if\s*\(\s*\w+\s*(?:===|!==)\s*null|\?\?)/;
11
- // Django: Model.objects.get() without DoesNotExist handler
12
- const DJANGO_OBJECTS_GET = /\w+\.objects\.get\s*\(/;
13
- // Gin: ShouldBindJSON with ignored error
14
- const GIN_BIND = /\.ShouldBindJSON\s*\(&?\w+\)/;
15
- const GIN_BIND_ERROR_HANDLED = /(?:if\s+err\s*!=\s*nil|if\s+\w+\s*:?=\s*.*ShouldBind)/;
16
- // Actix: unwrap in request handler function
17
- const ACTIX_HANDLER = /(?:async\s+fn\s+\w+\s*\([^)]*(?:HttpRequest|web::Data|web::Json|web::Path)[^)]*\))/;
18
- function splitLines(content) {
19
- return content.split('\n');
1
+ // engine/crash-shield/detectors/framework-detector.ts data-driven crash rules (SPEC-442/597)
2
+ import frameworkRulesJson from '../../../config/crash-shield-framework-rules.json' with { type: 'json' };
3
+ function isStringArray(value) {
4
+ return Array.isArray(value) && value.every((entry) => typeof entry === 'string');
20
5
  }
21
- function isNextJsFile(filePath, content) {
22
- return (filePath.endsWith('.tsx') ||
23
- filePath.endsWith('.jsx') ||
24
- content.includes('next/') ||
25
- content.includes("from 'next"));
6
+ function isNonNegativeInteger(value) {
7
+ return value === undefined || (Number.isInteger(value) && Number(value) >= 0);
26
8
  }
27
- function isExpressFile(content) {
28
- return content.includes("from 'express'") || content.includes("require('express')");
29
- }
30
- function isPrismaFile(content) {
31
- return content.includes('@prisma/client') || content.includes('PrismaClient');
32
- }
33
- function isDjangoFile(filePath, content) {
34
- return (filePath.endsWith('.py') &&
35
- (content.includes('from django') || content.includes('import django')));
36
- }
37
- function isGinFile(content) {
38
- return content.includes('"github.com/gin-gonic/gin"');
39
- }
40
- function isActixFile(content) {
41
- return content.includes('actix_web') || content.includes('use actix_web');
42
- }
43
- function detectNextJs(filePath, content) {
44
- const risks = [];
45
- if (!isNextJsFile(filePath, content) || !NEXT_GSP.test(content)) {
46
- return risks;
9
+ function hasValidGuard(value) {
10
+ if (value === undefined) {
11
+ return true;
47
12
  }
48
- // Find the function and check if it has try/catch
49
- if (!HAS_TRY.test(content)) {
50
- const lines = splitLines(content);
51
- for (let i = 0; i < lines.length; i++) {
52
- if (NEXT_GSP.test(lines[i] ?? '')) {
53
- risks.push({
54
- file: filePath,
55
- line: i + 1,
56
- pattern: 'NEXTJS_GSP_NO_TRY',
57
- severity: 'HIGH',
58
- description: 'getServerSideProps without try/catch. Any uncaught error will crash the entire page render.',
59
- suggestedFix: 'Wrap the body of getServerSideProps in try/catch and return { notFound: true } or redirect on error.',
60
- autoFixable: false,
61
- });
62
- }
63
- }
13
+ if (typeof value !== 'object' || value === null) {
14
+ return false;
64
15
  }
65
- return risks;
16
+ const guard = value;
17
+ return (['file', 'line', 'window'].includes(String(guard.scope)) &&
18
+ isStringArray(guard.patterns) &&
19
+ isNonNegativeInteger(guard.before) &&
20
+ isNonNegativeInteger(guard.after));
66
21
  }
67
- function detectExpress(filePath, content) {
68
- const risks = [];
69
- if (!isExpressFile(content)) {
70
- return risks;
71
- }
72
- const lines = splitLines(content);
73
- for (let i = 0; i < lines.length; i++) {
74
- const line = lines[i] ?? '';
75
- if (EXPRESS_ASYNC_ROUTE.test(line) && !HAS_CATCH_OR_NEXT.test(content)) {
76
- risks.push({
77
- file: filePath,
78
- line: i + 1,
79
- pattern: 'EXPRESS_ASYNC_ROUTE_NO_ERROR_HANDLER',
80
- severity: 'HIGH',
81
- description: 'Async Express route handler without .catch() or next(err). Unhandled promise rejections crash the server in Node.js.',
82
- suggestedFix: 'Add .catch(next) at the end, wrap in try/catch and call next(err), or use an async wrapper like express-async-errors.',
83
- autoFixable: false,
84
- });
22
+ function hasValidPatterns(rule) {
23
+ try {
24
+ for (const pattern of [
25
+ rule.finding,
26
+ ...rule.contentAny,
27
+ ...(rule.contentAll ?? []),
28
+ ...(rule.guard?.patterns ?? []),
29
+ ]) {
30
+ new RegExp(pattern, 'i');
85
31
  }
32
+ return true;
33
+ }
34
+ catch {
35
+ return false;
86
36
  }
87
- return risks;
88
37
  }
89
- function detectPrisma(filePath, content) {
90
- const risks = [];
91
- if (!isPrismaFile(content)) {
92
- return risks;
38
+ export function parseFrameworkRules(value) {
39
+ if (typeof value !== 'object' ||
40
+ value === null ||
41
+ !('rules' in value) ||
42
+ !('schemaVersion' in value) ||
43
+ value.schemaVersion !== 1) {
44
+ throw new Error('[Planu] Invalid crash-shield framework rule catalog.');
93
45
  }
94
- const lines = splitLines(content);
95
- for (let i = 0; i < lines.length; i++) {
96
- const line = lines[i] ?? '';
97
- if (PRISMA_FIND.test(line)) {
98
- // Check surrounding lines for null check
99
- const windowStart = Math.max(0, i - 1);
100
- const windowEnd = Math.min(lines.length - 1, i + 5);
101
- let hasNullCheck = false;
102
- for (let j = windowStart; j <= windowEnd; j++) {
103
- if (PRISMA_NULL_CHECK.test(lines[j] ?? '')) {
104
- hasNullCheck = true;
105
- break;
106
- }
107
- }
108
- if (!hasNullCheck) {
109
- risks.push({
110
- file: filePath,
111
- line: i + 1,
112
- pattern: 'PRISMA_FIND_NO_NULL_CHECK',
113
- severity: 'HIGH',
114
- description: 'Prisma findUnique/findFirst can return null when record is not found. Accessing fields without null check crashes.',
115
- suggestedFix: 'Check for null: if (!result) { throw new NotFoundError() } or use findUniqueOrThrow().',
116
- autoFixable: false,
117
- });
118
- }
119
- }
46
+ const rules = value.rules;
47
+ if (!Array.isArray(rules)) {
48
+ throw new Error('[Planu] Crash-shield framework rules must be an array.');
120
49
  }
121
- return risks;
50
+ return rules.map((candidate) => {
51
+ if (typeof candidate !== 'object' || candidate === null) {
52
+ throw new Error('[Planu] Invalid crash-shield framework rule entry.');
53
+ }
54
+ const rule = candidate;
55
+ if (typeof rule.id !== 'string' ||
56
+ typeof rule.framework !== 'string' ||
57
+ !isStringArray(rule.fileExtensions) ||
58
+ !isStringArray(rule.contentAny) ||
59
+ (rule.contentAll !== undefined && !isStringArray(rule.contentAll)) ||
60
+ !hasValidGuard(rule.guard) ||
61
+ typeof rule.finding !== 'string' ||
62
+ typeof rule.pattern !== 'string' ||
63
+ typeof rule.description !== 'string' ||
64
+ typeof rule.suggestedFix !== 'string' ||
65
+ !['content', 'file-and-content', 'file-or-content'].includes(rule.activationMode ?? '') ||
66
+ !['HIGH', 'CRITICAL'].includes(rule.severity ?? '')) {
67
+ throw new Error(`[Planu] Invalid crash-shield framework rule: ${rule.id ?? 'unknown'}.`);
68
+ }
69
+ const parsedRule = rule;
70
+ if (!hasValidPatterns(parsedRule)) {
71
+ throw new Error(`[Planu] Invalid regex in crash-shield framework rule: ${parsedRule.id}.`);
72
+ }
73
+ return parsedRule;
74
+ });
122
75
  }
123
- function detectDjango(filePath, content) {
124
- const risks = [];
125
- if (!isDjangoFile(filePath, content)) {
126
- return risks;
76
+ const rules = parseFrameworkRules(frameworkRulesJson);
77
+ function matches(pattern, content) {
78
+ return new RegExp(pattern, 'i').test(content);
79
+ }
80
+ function isActive(rule, filePath, content) {
81
+ const fileMatch = rule.fileExtensions.some((extension) => filePath.endsWith(extension));
82
+ const contentMatch = rule.contentAny.some((pattern) => matches(pattern, content));
83
+ const allContentMatch = (rule.contentAll ?? []).every((pattern) => matches(pattern, content));
84
+ if (!allContentMatch) {
85
+ return false;
127
86
  }
128
- const lines = splitLines(content);
129
- for (let i = 0; i < lines.length; i++) {
130
- const line = lines[i] ?? '';
131
- if (DJANGO_OBJECTS_GET.test(line) && !content.includes('DoesNotExist')) {
132
- risks.push({
133
- file: filePath,
134
- line: i + 1,
135
- pattern: 'DJANGO_GET_NO_DOES_NOT_EXIST',
136
- severity: 'HIGH',
137
- description: 'Model.objects.get() raises DoesNotExist exception if no record matches. Not catching it crashes the view.',
138
- suggestedFix: 'Use try/except Model.DoesNotExist, or use get_object_or_404(), or filter().first().',
139
- autoFixable: false,
140
- });
141
- }
87
+ if (rule.activationMode === 'file-and-content') {
88
+ return fileMatch && contentMatch;
142
89
  }
143
- return risks;
90
+ if (rule.activationMode === 'file-or-content') {
91
+ return fileMatch || contentMatch;
92
+ }
93
+ return contentMatch;
144
94
  }
145
- function detectGin(filePath, content) {
146
- const risks = [];
147
- if (!isGinFile(content)) {
148
- return risks;
95
+ function isGuarded(rule, lines, lineIndex, content) {
96
+ if (!rule.guard) {
97
+ return false;
149
98
  }
150
- const lines = splitLines(content);
151
- for (let i = 0; i < lines.length; i++) {
152
- const line = lines[i] ?? '';
153
- if (GIN_BIND.test(line) && !GIN_BIND_ERROR_HANDLED.test(line)) {
154
- // Check nearby lines for error handling
155
- const windowStart = Math.max(0, i - 1);
156
- const windowEnd = Math.min(lines.length - 1, i + 3);
157
- let handled = false;
158
- for (let j = windowStart; j <= windowEnd; j++) {
159
- if (/if\s+err\s*!=\s*nil/.test(lines[j] ?? '')) {
160
- handled = true;
161
- break;
162
- }
163
- }
164
- if (!handled) {
165
- risks.push({
166
- file: filePath,
167
- line: i + 1,
168
- pattern: 'GIN_BIND_ERROR_IGNORED',
169
- severity: 'HIGH',
170
- description: 'Gin ShouldBindJSON error not checked. Binding failures are silently ignored, leading to zero-value structs.',
171
- suggestedFix: 'Check the error: if err := c.ShouldBindJSON(&input); err != nil { c.JSON(400, gin.H{"error": err.Error()}); return }',
172
- autoFixable: false,
173
- });
174
- }
175
- }
99
+ if (rule.guard.scope === 'file') {
100
+ return rule.guard.patterns.some((pattern) => matches(pattern, content));
176
101
  }
177
- return risks;
102
+ const before = rule.guard.scope === 'line' ? 0 : (rule.guard.before ?? 0);
103
+ const after = rule.guard.scope === 'line' ? 0 : (rule.guard.after ?? 0);
104
+ const window = lines.slice(Math.max(0, lineIndex - before), lineIndex + after + 1).join('\n');
105
+ return rule.guard.patterns.some((pattern) => matches(pattern, window));
178
106
  }
179
- function detectActix(filePath, content) {
180
- const risks = [];
181
- if (!isActixFile(content) || !filePath.endsWith('.rs')) {
182
- return risks;
183
- }
184
- if (!ACTIX_HANDLER.test(content) || !content.includes('.unwrap()')) {
185
- return risks;
107
+ function detectRule(rule, filePath, content) {
108
+ if (!isActive(rule, filePath, content)) {
109
+ return [];
186
110
  }
187
- const lines = splitLines(content);
188
- for (let i = 0; i < lines.length; i++) {
189
- const line = lines[i] ?? '';
190
- if (line.includes('.unwrap()')) {
191
- risks.push({
111
+ const lines = content.split('\n');
112
+ return lines.flatMap((line, index) => {
113
+ if (!matches(rule.finding, line) || isGuarded(rule, lines, index, content)) {
114
+ return [];
115
+ }
116
+ return [
117
+ {
192
118
  file: filePath,
193
- line: i + 1,
194
- pattern: 'ACTIX_UNWRAP_IN_HANDLER',
195
- severity: 'CRITICAL',
196
- description: 'unwrap() in Actix-web request handler panics and crashes the worker thread on error.',
197
- suggestedFix: 'Return a proper error response: use ? operator with impl ResponseError, or map_err() to return HttpResponse::InternalServerError().',
119
+ line: index + 1,
120
+ pattern: rule.pattern,
121
+ severity: rule.severity,
122
+ description: rule.description,
123
+ suggestedFix: rule.suggestedFix,
198
124
  autoFixable: false,
199
- });
200
- }
201
- }
202
- return risks;
125
+ },
126
+ ];
127
+ });
203
128
  }
204
129
  export const frameworkDetector = {
205
130
  language: 'multi',
206
- frameworks: ['Next.js', 'Express', 'Prisma', 'Django', 'Gin', 'Actix'],
207
- fileExtensions: ['.ts', '.tsx', '.js', '.jsx', '.py', '.go', '.rs'],
131
+ frameworks: rules.map((rule) => rule.framework),
132
+ fileExtensions: [...new Set(rules.flatMap((rule) => rule.fileExtensions))],
208
133
  detect(filePath, content) {
209
- return [
210
- ...detectNextJs(filePath, content),
211
- ...detectExpress(filePath, content),
212
- ...detectPrisma(filePath, content),
213
- ...detectDjango(filePath, content),
214
- ...detectGin(filePath, content),
215
- ...detectActix(filePath, content),
216
- ];
134
+ return rules.flatMap((rule) => detectRule(rule, filePath, content));
217
135
  },
218
136
  };
219
137
  //# sourceMappingURL=framework-detector.js.map
@@ -1,3 +1,4 @@
1
+ import { technologyValue } from '../../technology-registry.js';
1
2
  // P1: JSON.parse without Partial — CRITICAL
2
3
  const JSON_PARSE_CAST = /JSON\.parse\([^)]+\)\s+as\s+(?!Partial<|unknown|Record<string)[A-Z]/;
3
4
  // P2: Incomplete optional chaining — HIGH
@@ -178,7 +179,7 @@ function detectP5(filePath, content) {
178
179
  return risks;
179
180
  }
180
181
  export const typescriptDetector = {
181
- language: 'TypeScript',
182
+ language: technologyValue('technology-typescript-ed0504'),
182
183
  fileExtensions: ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'],
183
184
  detect(filePath, content) {
184
185
  if (isFileSuppressed(content)) {
@@ -2,10 +2,11 @@
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
+ import { resolveStorageLayout } from '../../storage/storage-layout.js';
5
6
  import { computeDashboardMetrics, computeHealthScore } from './kanban-logic.js';
6
7
  import { extractSectionBody } from '../spec-format/read-technical-section.js';
7
8
  /** Root data directory for all project data */
8
- const DATA_DIR = join(process.cwd(), 'data');
9
+ const DATA_DIR = resolveStorageLayout().data;
9
10
  /** Safely read and parse a JSON file; returns null on any error */
10
11
  async function readJsonFile(filePath) {
11
12
  try {
@@ -1,4 +1,9 @@
1
1
  import type { GcRunOptions, GcRunResult } from '../../types/index.js';
2
+ /** Permanently remove catalog-owned trash entries whose TTL has elapsed. */
3
+ export declare function purgeExpiredGcTrash(trashDir: string, nowMs?: number): Promise<{
4
+ purged: string[];
5
+ errors: string[];
6
+ }>;
2
7
  /**
3
8
  * Run the GC pipeline:
4
9
  * 1. Scan data/projects/ for test-named, inactive, and orphaned directories.
@@ -8,4 +13,6 @@ import type { GcRunOptions, GcRunResult } from '../../types/index.js';
8
13
  * @param options - Run configuration (dataProjectsDir, apply, inactiveDays, …)
9
14
  */
10
15
  export declare function runGC(options: GcRunOptions): Promise<GcRunResult>;
16
+ /** Restore one catalog-owned GC entry while its TTL metadata is present. */
17
+ export declare function restoreGcTrash(trashEntryPath: string, dataProjectsDir: string): Promise<string>;
11
18
  //# sourceMappingURL=gc-runner.d.ts.map
@@ -1,7 +1,59 @@
1
1
  // engine/data-projects-gc/gc-runner.ts — SPEC-581
2
2
  // Orchestrates scan + optional deletion of data/projects/ garbage.
3
- import { rm } from 'node:fs/promises';
3
+ import { access, mkdir, readFile, readdir, rename, rm } from 'node:fs/promises';
4
+ import { basename, dirname, isAbsolute, join, resolve } from 'node:path';
4
5
  import { scanProjectDirs } from './scanner.js';
6
+ import { atomicWriteFile } from '../safety/atomic-write-file.js';
7
+ const DEFAULT_TRASH_TTL_DAYS = 30;
8
+ async function pathExists(path) {
9
+ return access(path).then(() => true, () => false);
10
+ }
11
+ function parseTrashMetadata(value) {
12
+ if (!value || typeof value !== 'object') {
13
+ throw new Error('[Planu] Invalid GC trash metadata');
14
+ }
15
+ const parsed = value;
16
+ if (parsed.schemaVersion !== 1 ||
17
+ typeof parsed.originalPath !== 'string' ||
18
+ typeof parsed.trashedPath !== 'string' ||
19
+ typeof parsed.trashedAt !== 'string' ||
20
+ typeof parsed.expiresAt !== 'string' ||
21
+ !['test-named', 'inactive', 'orphaned'].includes(String(parsed.reason)) ||
22
+ Number.isNaN(Date.parse(parsed.trashedAt)) ||
23
+ Number.isNaN(Date.parse(parsed.expiresAt))) {
24
+ throw new Error('[Planu] Invalid GC trash metadata');
25
+ }
26
+ return parsed;
27
+ }
28
+ /** Permanently remove catalog-owned trash entries whose TTL has elapsed. */
29
+ export async function purgeExpiredGcTrash(trashDir, nowMs = Date.now()) {
30
+ if (!isAbsolute(trashDir) || !Number.isFinite(nowMs)) {
31
+ throw new Error('[Planu] GC purge requires an absolute trash path and valid time');
32
+ }
33
+ const root = resolve(trashDir);
34
+ const metadataFiles = (await readdir(root).catch(() => [])).filter((name) => name.endsWith('.trash.json'));
35
+ const purged = [];
36
+ const errors = [];
37
+ for (const name of metadataFiles) {
38
+ const metadataPath = join(root, name);
39
+ try {
40
+ const metadata = parseTrashMetadata(JSON.parse(await readFile(metadataPath, 'utf8')));
41
+ const trashedPath = resolve(metadata.trashedPath);
42
+ if (dirname(trashedPath) !== root ||
43
+ `${trashedPath}.trash.json` !== metadataPath ||
44
+ Date.parse(metadata.expiresAt) > nowMs) {
45
+ continue;
46
+ }
47
+ await rm(trashedPath, { recursive: true, force: true });
48
+ await rm(metadataPath, { force: true });
49
+ purged.push(trashedPath);
50
+ }
51
+ catch (error) {
52
+ errors.push(`${name}: ${error instanceof Error ? error.message : String(error)}`);
53
+ }
54
+ }
55
+ return { purged, errors };
56
+ }
5
57
  /**
6
58
  * Run the GC pipeline:
7
59
  * 1. Scan data/projects/ for test-named, inactive, and orphaned directories.
@@ -10,8 +62,12 @@ import { scanProjectDirs } from './scanner.js';
10
62
  *
11
63
  * @param options - Run configuration (dataProjectsDir, apply, inactiveDays, …)
12
64
  */
65
+ // eslint-disable-next-line max-lines-per-function -- scan, recoverable move and TTL metadata form one atomic GC pipeline
13
66
  export async function runGC(options) {
14
- const { dataProjectsDir, apply = false, inactiveDays = 90, registeredHashes, includeOrphans = false, } = options;
67
+ const { dataProjectsDir, apply = false, inactiveDays = 90, registeredHashes, includeOrphans = false, trashDir, trashTtlDays = DEFAULT_TRASH_TTL_DAYS, } = options;
68
+ if (!Number.isSafeInteger(trashTtlDays) || trashTtlDays < 1 || trashTtlDays > 3650) {
69
+ throw new Error('[Planu] trashTtlDays must be an integer between 1 and 3650');
70
+ }
15
71
  const scanResult = await scanProjectDirs(dataProjectsDir, {
16
72
  inactiveDays,
17
73
  registeredHashes,
@@ -24,11 +80,40 @@ export async function runGC(options) {
24
80
  ];
25
81
  const deleted = [];
26
82
  const errors = [];
83
+ const trashed = [];
84
+ const purgedExpired = [];
27
85
  if (apply) {
86
+ if (!trashDir) {
87
+ throw new Error('[Planu] trashDir is required when applying GC');
88
+ }
89
+ await mkdir(trashDir, { recursive: true, mode: 0o700 });
90
+ const purge = await purgeExpiredGcTrash(trashDir);
91
+ purgedExpired.push(...purge.purged);
92
+ errors.push(...purge.errors);
28
93
  for (const entry of candidates) {
29
94
  try {
30
- await rm(entry.fullPath, { recursive: true, force: true });
95
+ const destination = join(trashDir, `${Date.now().toString()}-${entry.reason}-${entry.name}`);
96
+ await rename(entry.fullPath, destination);
97
+ const trashedAt = new Date();
98
+ const metadata = {
99
+ schemaVersion: 1,
100
+ originalPath: entry.fullPath,
101
+ trashedPath: destination,
102
+ trashedAt: trashedAt.toISOString(),
103
+ expiresAt: new Date(trashedAt.getTime() + trashTtlDays * 24 * 60 * 60 * 1000).toISOString(),
104
+ reason: entry.reason,
105
+ };
106
+ try {
107
+ await atomicWriteFile(`${destination}.trash.json`, `${JSON.stringify(metadata, null, 2)}\n`, {
108
+ mode: 0o600,
109
+ });
110
+ }
111
+ catch (error) {
112
+ await rename(destination, entry.fullPath);
113
+ throw error;
114
+ }
31
115
  deleted.push(entry.name);
116
+ trashed.push(destination);
32
117
  }
33
118
  catch (err) {
34
119
  /* v8 ignore next 4 -- deletion error: typically OS-level permission or race condition */
@@ -44,8 +129,33 @@ export async function runGC(options) {
44
129
  orphaned: scanResult.orphaned,
45
130
  candidateCount: candidates.length,
46
131
  deleted,
132
+ trashed,
133
+ purgedExpired,
47
134
  errors,
48
135
  inactiveDays,
49
136
  };
50
137
  }
138
+ /** Restore one catalog-owned GC entry while its TTL metadata is present. */
139
+ export async function restoreGcTrash(trashEntryPath, dataProjectsDir) {
140
+ if (!isAbsolute(trashEntryPath) || !isAbsolute(dataProjectsDir)) {
141
+ throw new Error('[Planu] GC restore paths must be absolute');
142
+ }
143
+ const source = resolve(trashEntryPath);
144
+ const metadataPath = `${source}.trash.json`;
145
+ const parsed = parseTrashMetadata(JSON.parse(await readFile(metadataPath, 'utf8')));
146
+ const destination = resolve(parsed.originalPath);
147
+ if (resolve(parsed.trashedPath) !== source ||
148
+ dirname(destination) !== resolve(dataProjectsDir) ||
149
+ basename(destination) !== basename(parsed.originalPath) ||
150
+ Date.parse(parsed.expiresAt) <= Date.now()) {
151
+ throw new Error('[Planu] Invalid or expired GC trash metadata');
152
+ }
153
+ if (await pathExists(destination)) {
154
+ throw new Error(`[Planu] Cannot restore over existing project data: ${destination}`);
155
+ }
156
+ await mkdir(dirname(destination), { recursive: true, mode: 0o700 });
157
+ await rename(source, destination);
158
+ await rm(metadataPath, { force: true });
159
+ return destination;
160
+ }
51
161
  //# sourceMappingURL=gc-runner.js.map
@@ -21,10 +21,14 @@ async function newestMtime(dirPath) {
21
21
  const dir = await opendir(dirPath);
22
22
  for await (const entry of dir) {
23
23
  try {
24
- const s = await stat(join(dirPath, entry.name));
24
+ const entryPath = join(dirPath, entry.name);
25
+ const s = await stat(entryPath);
25
26
  if (s.mtimeMs > newest) {
26
27
  newest = s.mtimeMs;
27
28
  }
29
+ if (entry.isDirectory()) {
30
+ newest = Math.max(newest, await newestMtime(entryPath));
31
+ }
28
32
  }
29
33
  catch {
30
34
  /* v8 ignore next 2 -- unreadable entry: OS-level permission error */
@@ -1,18 +1,15 @@
1
- // SPEC-597-EXEMPT: canonical mapping (npm-package↔framework, keyword catalogue)
2
- // — must enumerate framework names by design; no detection logic to migrate.
3
- // engine/decision-store.ts — Search and conflict detection for decisions (SPEC-040)
4
- // Pure functions — no I/O. All persistence is in storage/decision-store.ts.
1
+ import { technologyValue } from './technology-registry.js';
5
2
  // ---------------------------------------------------------------------------
6
3
  // Keyword maps
7
4
  // ---------------------------------------------------------------------------
8
5
  const STACK_KEYWORDS = [
9
- 'react',
10
- 'vue',
11
- 'angular',
12
- 'svelte',
6
+ technologyValue('technology-react-275976'),
7
+ technologyValue('technology-vue-564382'),
8
+ technologyValue('technology-angular-a39f89'),
9
+ technologyValue('technology-svelte-c190ac'),
13
10
  'next',
14
- 'nuxt',
15
- 'remix',
11
+ technologyValue('technology-nuxt-22c407'),
12
+ technologyValue('technology-remix-0c5d96'),
16
13
  'node',
17
14
  'deno',
18
15
  'bun',
@@ -20,16 +17,16 @@ const STACK_KEYWORDS = [
20
17
  'java',
21
18
  'kotlin',
22
19
  'swift',
23
- 'flutter',
20
+ technologyValue('technology-flutter-be1396'),
24
21
  'expo',
25
- 'typescript',
22
+ technologyValue('technology-typescript-969545'),
26
23
  'javascript',
27
24
  'rust',
28
25
  'go',
29
26
  'postgres',
30
27
  'mysql',
31
28
  'mongodb',
32
- 'redis',
29
+ technologyValue('technology-redis-34fb46'),
33
30
  'sqlite',
34
31
  ];
35
32
  const ARCHITECTURE_KEYWORDS = [
@@ -44,7 +41,7 @@ const ARCHITECTURE_KEYWORDS = [
44
41
  'clean architecture',
45
42
  'layered',
46
43
  'rest',
47
- 'graphql',
44
+ technologyValue('technology-graphql-aed31c'),
48
45
  'grpc',
49
46
  'message queue',
50
47
  'kafka',
@@ -4,8 +4,9 @@ import * as patternStore from '../../storage/pattern-store.js';
4
4
  import * as decisionStore from '../../storage/decision-store.js';
5
5
  import { moveToTrash, moveDataToTrash, countFiles, pathExists } from '../../storage/trash-store.js';
6
6
  import { appendAuditEntry } from './audit-logger.js';
7
- import { rm, mkdir, cp } from 'node:fs/promises';
7
+ import { rm, mkdir, rename } from 'node:fs/promises';
8
8
  import { join } from 'node:path';
9
+ import { resolveStorageLayout } from '../../storage/storage-layout.js';
9
10
  /**
10
11
  * Check if any specs reference the given specId as a dependency.
11
12
  * Returns a list of dependent spec IDs for cascade awareness.
@@ -132,13 +133,12 @@ export async function executeDeleteProject(projectId, force) {
132
133
  if (!force) {
133
134
  // For soft delete of a project, move the entire directory
134
135
  // Use a global trash since project dir itself is being deleted
135
- const globalTrashDir = 'data/projects/.trash';
136
+ const globalTrashDir = join(resolveStorageLayout().trash, 'projects');
136
137
  const timestamp = Date.now();
137
138
  const trashSubdir = `${String(timestamp)}-project-${projectId}`;
138
139
  const destPath = join(globalTrashDir, trashSubdir);
139
- await mkdir(destPath, { recursive: true });
140
- await cp(dataDir, destPath, { recursive: true });
141
- await rm(dataDir, { recursive: true, force: true });
140
+ await mkdir(globalTrashDir, { recursive: true });
141
+ await rename(dataDir, destPath);
142
142
  }
143
143
  else {
144
144
  await rm(dataDir, { recursive: true, force: true });
@@ -1,3 +1,4 @@
1
+ import { technologyValue } from '../technology-registry.js';
1
2
  // Heuristic abandonment registry — no npm registry calls.
2
3
  const KNOWN_ABANDONED = {
3
4
  request: { months: 60, alternative: 'axios or native fetch' },
@@ -9,7 +10,7 @@ const KNOWN_ABANDONED = {
9
10
  moment: { months: 24, alternative: 'dayjs or date-fns (moment in maintenance mode)' },
10
11
  'node-uuid': { months: 84, alternative: 'uuid (v9+)' },
11
12
  'uglify-js': { months: 48, alternative: 'esbuild or terser' },
12
- coffeescript: { months: 60, alternative: 'TypeScript' },
13
+ coffeescript: { months: 60, alternative: technologyValue('technology-typescript-ed0504') },
13
14
  };
14
15
  export function getAbandonedInfo(name) {
15
16
  const entry = KNOWN_ABANDONED[name];