@planu/cli 4.13.0 → 5.0.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 (1066) hide show
  1. package/CHANGELOG.md +64 -1
  2. package/LICENSE +55 -12
  3. package/README.md +33 -25
  4. package/dist/cli/commands/inspect.d.ts +4 -0
  5. package/dist/cli/commands/inspect.js +144 -0
  6. package/dist/cli/commands/install.d.ts +19 -12
  7. package/dist/cli/commands/install.js +148 -102
  8. package/dist/cli/commands/job.d.ts +3 -0
  9. package/dist/cli/commands/job.js +120 -0
  10. package/dist/cli/commands/offline.d.ts +15 -0
  11. package/dist/cli/commands/offline.js +132 -0
  12. package/dist/cli/commands/serve.js +4 -0
  13. package/dist/cli/commands/spec.js +1 -1
  14. package/dist/cli/commands/storage.d.ts +3 -0
  15. package/dist/cli/commands/storage.js +102 -0
  16. package/dist/cli/commands/uninstall.d.ts +10 -0
  17. package/dist/cli/commands/uninstall.js +93 -7
  18. package/dist/cli/commands/validate.js +1 -1
  19. package/dist/cli/index.js +2 -0
  20. package/dist/cli/router.js +9 -3
  21. package/dist/config/crash-shield-framework-rules.json +93 -0
  22. package/dist/config/environment-schema.json +147 -0
  23. package/dist/config/hardcode-exceptions.json +4 -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/official-sdd-tools.d.ts +4 -0
  27. package/dist/config/official-sdd-tools.js +35 -0
  28. package/dist/config/product-public.d.ts +225 -0
  29. package/dist/config/product-public.js +147 -0
  30. package/dist/config/product-public.json +283 -0
  31. package/dist/config/registries/hosts/codex.json +20 -363
  32. package/dist/config/release-compatibility.json +13 -0
  33. package/dist/config/release-policy.json +108 -0
  34. package/dist/config/runtime-policy.json +55 -0
  35. package/dist/config/skill-templates/planu-resume-work.md +2 -2
  36. package/dist/config/skill-templates/planu-validate.md +7 -4
  37. package/dist/config/subagent-templates/planu-spec-implementer.md +7 -3
  38. package/dist/config/subagent-templates/planu-validator.md +10 -5
  39. package/dist/config/technology-registry.json +120 -0
  40. package/dist/config/version.js +7 -8
  41. package/dist/core/index.d.ts +1 -1
  42. package/dist/core/spec-validator.d.ts +4 -4
  43. package/dist/core/spec-validator.js +1 -1
  44. package/dist/engine/abortable-process-runner.d.ts +20 -2
  45. package/dist/engine/abortable-process-runner.js +267 -67
  46. package/dist/engine/advanced-testing/accessibility-checker.js +12 -14
  47. package/dist/engine/advanced-testing/mutation-advisor.js +3 -4
  48. package/dist/engine/advanced-testing/property-based.js +2 -3
  49. package/dist/engine/advanced-testing/test-data-advisor.js +2 -3
  50. package/dist/engine/agent-generator.js +2 -1
  51. package/dist/engine/agent-handoff-store.js +2 -1
  52. package/dist/engine/agent-prompt-generator.js +7 -5
  53. package/dist/engine/agent-telemetry.js +2 -1
  54. package/dist/engine/ai-integration/gemini/extensions-advisor.js +41 -9
  55. package/dist/engine/ambiguity-detector.js +12 -11
  56. package/dist/engine/ambiguity-scorer.js +4 -26
  57. package/dist/engine/analyzer/db-engine.js +2 -3
  58. package/dist/engine/analyzer/detectors.js +13 -14
  59. package/dist/engine/analyzer/env-setup.js +9 -10
  60. package/dist/engine/analyzer-env-scanner/env-example.js +7 -8
  61. package/dist/engine/api-spec-generator/graphql-parser.js +2 -2
  62. package/dist/engine/api-validation/graphql-schema-validator.js +2 -1
  63. package/dist/engine/api-validation/openapi-impl-validator.js +6 -7
  64. package/dist/engine/architecture-detector.js +10 -8
  65. package/dist/engine/auth/config.d.ts +1 -1
  66. package/dist/engine/auth/config.js +4 -3
  67. package/dist/engine/auth/scope-mapper.js +1 -7
  68. package/dist/engine/auto-updater/atomic-upgrade.d.ts +8 -0
  69. package/dist/engine/auto-updater/atomic-upgrade.js +381 -0
  70. package/dist/engine/auto-updater/config-detector.js +9 -3
  71. package/dist/engine/auto-updater/config-patcher.d.ts +0 -4
  72. package/dist/engine/auto-updater/config-patcher.js +10 -15
  73. package/dist/engine/auto-updater/index.d.ts +3 -1
  74. package/dist/engine/auto-updater/index.js +44 -30
  75. package/dist/engine/auto-updater/npm-registry.js +10 -2
  76. package/dist/engine/auto-updater/release-verifier.d.ts +3 -0
  77. package/dist/engine/auto-updater/release-verifier.js +112 -0
  78. package/dist/engine/auto-updater/upgrade-lock.d.ts +6 -0
  79. package/dist/engine/auto-updater/upgrade-lock.js +28 -0
  80. package/dist/engine/auto-updater/upgrade-trust-state.d.ts +7 -0
  81. package/dist/engine/auto-updater/upgrade-trust-state.js +59 -0
  82. package/dist/engine/autopilot/audit-logger.js +2 -5
  83. package/dist/engine/autopilot/state-updater.js +4 -4
  84. package/dist/engine/best-practices-library.js +2 -1
  85. package/dist/engine/browser-validator.js +2 -1
  86. package/dist/engine/build-tool-detector.js +3 -2
  87. package/dist/engine/cascade-hooks/hooks/review-enricher.hook.js +9 -6
  88. package/dist/engine/cascade-hooks/state-drift-detector.d.ts +3 -3
  89. package/dist/engine/cascade-hooks/state-drift-detector.js +1 -1
  90. package/dist/engine/ci-generator/context-builders.js +7 -5
  91. package/dist/engine/ci-generator/planu-config.js +1 -7
  92. package/dist/engine/ci-generator/stack-detector.js +0 -2
  93. package/dist/engine/ci-generator/yaml-builder.js +0 -2
  94. package/dist/engine/clarification-gate/gate.d.ts +3 -3
  95. package/dist/engine/claude-config-auditor/rules-auditor.js +4 -3
  96. package/dist/engine/code-scanner/layer-scanner.js +6 -22
  97. package/dist/engine/code-transforms/typescript/ast-utils.js +2 -3
  98. package/dist/engine/complexity-budget/trivial-detector.js +2 -1
  99. package/dist/engine/compliance-test-generator/index.js +7 -2
  100. package/dist/engine/compliance-test-generator/test-formatter.js +2 -2
  101. package/dist/engine/config-health/mcp-config-checker.js +2 -1
  102. package/dist/engine/config-health/ts-checker-scripts.js +4 -3
  103. package/dist/engine/config-health/ts-checker.js +3 -2
  104. package/dist/engine/convention-injector.js +5 -7
  105. package/dist/engine/convention-scanner/convention-parser.js +3 -2
  106. package/dist/engine/core-bridge-duplicate-blocks.d.ts +3 -0
  107. package/dist/engine/core-bridge-duplicate-blocks.js +57 -0
  108. package/dist/engine/core-bridge-gaps.d.ts +4 -0
  109. package/dist/engine/core-bridge-gaps.js +75 -0
  110. package/dist/engine/core-bridge.d.ts +10 -10
  111. package/dist/engine/core-bridge.js +196 -283
  112. package/dist/engine/cost-guardrails.d.ts +1 -1
  113. package/dist/engine/cost-guardrails.js +1 -1
  114. package/dist/engine/cost-tracking/ledger.js +2 -5
  115. package/dist/engine/coverage-gap-analyzer.js +10 -1
  116. package/dist/engine/crash-shield/detectors/framework-detector.d.ts +2 -0
  117. package/dist/engine/crash-shield/detectors/framework-detector.js +110 -192
  118. package/dist/engine/crash-shield/detectors/typescript-detector.js +2 -1
  119. package/dist/engine/criterion-identity.d.ts +1 -0
  120. package/dist/engine/criterion-identity.js +7 -0
  121. package/dist/engine/dashboard/data-loader.js +4 -8
  122. package/dist/engine/dashboard/templates-layout.js +0 -3
  123. package/dist/engine/dashboard/templates-project.js +1 -13
  124. package/dist/engine/data-projects-gc/gc-runner.d.ts +7 -0
  125. package/dist/engine/data-projects-gc/gc-runner.js +113 -3
  126. package/dist/engine/data-projects-gc/scanner.js +5 -1
  127. package/dist/engine/decision-store.js +11 -14
  128. package/dist/engine/deleter/core.js +5 -5
  129. package/dist/engine/dep-auditor/abandonment-data.js +2 -1
  130. package/dist/engine/dep-auditor/abandonment-registry.js +3 -1
  131. package/dist/engine/dep-auditor/cve-fetcher.js +3 -0
  132. package/dist/engine/dep-auditor/dep-duplicates-detector.js +36 -4
  133. package/dist/engine/dep-auditor/license-registry.js +2 -0
  134. package/dist/engine/dependency-evaluator.d.ts +14 -0
  135. package/dist/engine/dependency-evaluator.js +81 -0
  136. package/dist/engine/deploy/providers/fly.js +7 -7
  137. package/dist/engine/deploy/providers/netlify.js +7 -7
  138. package/dist/engine/deploy/providers/railway.js +10 -12
  139. package/dist/engine/deploy/providers/vercel.js +7 -9
  140. package/dist/engine/deprecation-scanner/pattern-loader.js +0 -2
  141. package/dist/engine/desktop-detector.js +2 -3
  142. package/dist/engine/detect-duplication.js +2 -1
  143. package/dist/engine/detectors/advanced-framework-detector/css-state-detector.js +2 -1
  144. package/dist/engine/detectors/advanced-framework-detector/legacy-detector.js +2 -3
  145. package/dist/engine/detectors/advanced-framework-detector/modern-detector.js +3 -4
  146. package/dist/engine/detectors/agent-framework-detector.js +3 -2
  147. package/dist/engine/detectors/ai-native-detector.js +4 -6
  148. package/dist/engine/detectors/cache-db-detector.js +4 -3
  149. package/dist/engine/detectors/cicd-detector.js +4 -3
  150. package/dist/engine/detectors/deployment-detector.js +11 -12
  151. package/dist/engine/detectors/frontend-perf-detector.js +14 -9
  152. package/dist/engine/detectors/library-detector-multilang-a.js +16 -3
  153. package/dist/engine/detectors/library-detector-node.js +14 -4
  154. package/dist/engine/detectors/library-detector-python.js +7 -1
  155. package/dist/engine/detectors/library-detector.js +0 -2
  156. package/dist/engine/detectors/llm-detector/provider-maps.js +3 -2
  157. package/dist/engine/detectors/mcp-candidate-detector.js +12 -16
  158. package/dist/engine/detectors/mfe-detector.js +6 -7
  159. package/dist/engine/detectors/monitoring-detector.js +4 -3
  160. package/dist/engine/detectors/otel-detector.js +3 -2
  161. package/dist/engine/detectors/otel-ecosystem-detectors.d.ts +2 -2
  162. package/dist/engine/detectors/otel-ecosystem-detectors.js +4 -3
  163. package/dist/engine/detectors/platform-specialty-detector.js +3 -5
  164. package/dist/engine/detectors/template-engine-detector.js +3 -4
  165. package/dist/engine/doc-generator/builders.js +2 -3
  166. package/dist/engine/doc-generator/mobile-distribution-guide.js +13 -17
  167. package/dist/engine/doc-generator/portal/dirty-flag-map.d.ts +2 -2
  168. package/dist/engine/doc-generator/portal/portal-regenerator.js +3 -47
  169. package/dist/engine/docs-site-generator/data-collector.d.ts +1 -1
  170. package/dist/engine/docs-site-generator/data-collector.js +7 -28
  171. package/dist/engine/docs-site-generator/tools-renderer.js +3 -10
  172. package/dist/engine/domain-detector.js +3 -6
  173. package/dist/engine/dynamic-knowledge/knowledge-cache.js +3 -4
  174. package/dist/engine/dynamic-knowledge/knowledge-merger.js +17 -2
  175. package/dist/engine/dynamic-knowledge/web-researcher.js +15 -14
  176. package/dist/engine/dynamic-migration-detector/manifest-readers-extended.js +0 -2
  177. package/dist/engine/e2e-test-generator.js +4 -3
  178. package/dist/engine/ecosystem-absorber/knowledge-cache.js +2 -1
  179. package/dist/engine/ecosystem-absorber/platform-crawler.js +2 -2
  180. package/dist/engine/escalator/retry-counter.js +2 -1
  181. package/dist/engine/evidence-gates/artifact-reader.d.ts +16 -1
  182. package/dist/engine/evidence-gates/artifact-reader.js +220 -23
  183. package/dist/engine/evidence-gates/lifecycle-gate.d.ts +2 -1
  184. package/dist/engine/evidence-gates/lifecycle-gate.js +58 -3
  185. package/dist/engine/evidence-gates/reconciliation-freshness.d.ts +11 -0
  186. package/dist/engine/evidence-gates/reconciliation-freshness.js +72 -0
  187. package/dist/engine/evidence-index/done-drift.d.ts +1 -1
  188. package/dist/engine/evidence-index/done-drift.js +40 -18
  189. package/dist/engine/execution/context.d.ts +19 -0
  190. package/dist/engine/execution/context.js +130 -0
  191. package/dist/engine/execution/deadline-io.d.ts +21 -0
  192. package/dist/engine/execution/deadline-io.js +45 -0
  193. package/dist/engine/execution/durable-job-heartbeat-runtime.d.ts +4 -0
  194. package/dist/engine/execution/durable-job-heartbeat-runtime.js +400 -0
  195. package/dist/engine/execution/job-executor.d.ts +16 -0
  196. package/dist/engine/execution/job-executor.js +140 -0
  197. package/dist/engine/execution/job-runtime.d.ts +108 -0
  198. package/dist/engine/execution/job-runtime.js +328 -0
  199. package/dist/engine/execution/native-relevance-scorer.d.ts +6 -0
  200. package/dist/engine/execution/native-relevance-scorer.js +64 -0
  201. package/dist/engine/execution/native-worker-dispatch.d.ts +3 -0
  202. package/dist/engine/execution/native-worker-dispatch.js +46 -0
  203. package/dist/engine/execution/native-worker-protocol.d.ts +6 -0
  204. package/dist/engine/execution/native-worker-protocol.js +33 -0
  205. package/dist/engine/execution/native-worker-runtime.d.ts +4 -0
  206. package/dist/engine/execution/native-worker-runtime.js +177 -0
  207. package/dist/engine/execution/native-worker-thread.d.ts +2 -0
  208. package/dist/engine/execution/native-worker-thread.js +66 -0
  209. package/dist/engine/execution/operation-journal.d.ts +66 -0
  210. package/dist/engine/execution/operation-journal.js +260 -0
  211. package/dist/engine/execution/outbox-worker.d.ts +31 -0
  212. package/dist/engine/execution/outbox-worker.js +192 -0
  213. package/dist/engine/execution/public-job-sanitizer.d.ts +4 -0
  214. package/dist/engine/execution/public-job-sanitizer.js +31 -0
  215. package/dist/engine/execution/validate-job-executor.d.ts +35 -0
  216. package/dist/engine/execution/validate-job-executor.js +805 -0
  217. package/dist/engine/execution/validate-job-payload.d.ts +5 -0
  218. package/dist/engine/execution/validate-job-payload.js +144 -0
  219. package/dist/engine/execution/validate-job-recovery.d.ts +4 -0
  220. package/dist/engine/execution/validate-job-recovery.js +47 -0
  221. package/dist/engine/execution/validate-worker-runtime.d.ts +10 -0
  222. package/dist/engine/execution/validate-worker-runtime.js +188 -0
  223. package/dist/engine/execution/validate-worker-thread.d.ts +2 -0
  224. package/dist/engine/execution/validate-worker-thread.js +64 -0
  225. package/dist/engine/execution-plan/desktop-distribution.js +3 -7
  226. package/dist/engine/execution-plan/mobile-distribution.js +4 -9
  227. package/dist/engine/execution-plan/phases.js +4 -5
  228. package/dist/engine/execution-plan/plan-utils.js +8 -5
  229. package/dist/engine/facilitate/context-loader.js +3 -9
  230. package/dist/engine/figma/code-connect-fetcher.js +9 -8
  231. package/dist/engine/filesystem-watcher/index.d.ts +3 -3
  232. package/dist/engine/filesystem-watcher/index.js +5 -5
  233. package/dist/engine/framework-detector.js +14 -15
  234. package/dist/engine/git/planu-autocommit.js +8 -7
  235. package/dist/engine/git/repository-probe.d.ts +3 -0
  236. package/dist/engine/git/repository-probe.js +13 -0
  237. package/dist/engine/global-rules-manager.js +2 -2
  238. package/dist/engine/handoff-artifacts/io.js +2 -3
  239. package/dist/engine/handoff-artifacts/schemas/red-tests-handoff.js +8 -1
  240. package/dist/engine/handoff-artifacts/schemas.d.ts +6 -1
  241. package/dist/engine/handoff-artifacts/schemas.js +38 -0
  242. package/dist/engine/handoff-packager.d.ts +19 -0
  243. package/dist/engine/handoff-packager.js +415 -13
  244. package/dist/engine/hook-generator/stack-hook-templates.js +4 -4
  245. package/dist/engine/hooks/config-loader.js +1 -1
  246. package/dist/engine/hooks/context-injector.js +4 -7
  247. package/dist/engine/hooks/effort-configurator.js +1 -1
  248. package/dist/engine/hooks/file-watcher.js +1 -14
  249. package/dist/engine/hooks-reconciler.js +6 -4
  250. package/dist/engine/impact-detector/test-break-predictor.js +3 -3
  251. package/dist/engine/impact-detector/tool-registration.js +1 -1
  252. package/dist/engine/implementation-contract/renderer.js +23 -8
  253. package/dist/engine/infrastructure/component-mapper.js +5 -7
  254. package/dist/engine/infrastructure/docker-compose-generator.js +8 -10
  255. package/dist/engine/infrastructure/index.js +6 -3
  256. package/dist/engine/infrastructure/kubernetes-generator.js +2 -2
  257. package/dist/engine/infrastructure/railway-generator.js +10 -8
  258. package/dist/engine/infrastructure/signal-detector.js +6 -8
  259. package/dist/engine/infrastructure/terraform-generator.js +6 -8
  260. package/dist/engine/legal-compliance/detector.js +3 -2
  261. package/dist/engine/lifecycle-reconciliation-io.d.ts +11 -0
  262. package/dist/engine/lifecycle-reconciliation-io.js +180 -0
  263. package/dist/engine/lifecycle-reconciliation.d.ts +16 -0
  264. package/dist/engine/lifecycle-reconciliation.js +406 -0
  265. package/dist/engine/local-first/storage-advisor.js +5 -6
  266. package/dist/engine/local-first/tool-classification.js +2 -0
  267. package/dist/engine/macos-keychain-native-port.d.ts +10 -0
  268. package/dist/engine/macos-keychain-native-port.js +38 -0
  269. package/dist/engine/marketplace-fetcher/cache.js +3 -1
  270. package/dist/engine/mcp-config/mcp-config-writer.d.ts +2 -2
  271. package/dist/engine/mcp-config/mcp-config-writer.js +10 -8
  272. package/dist/engine/migration/db-migrator.js +2 -5
  273. package/dist/engine/migration/equivalence-mapper.js +12 -13
  274. package/dist/engine/migration/service-catalogs.js +6 -7
  275. package/dist/engine/migration/service-migrator-catalogs.js +6 -7
  276. package/dist/engine/migrations/remove-commercial-state.d.ts +3 -0
  277. package/dist/engine/migrations/remove-commercial-state.js +343 -0
  278. package/dist/engine/mobile-detector-ios.js +2 -3
  279. package/dist/engine/mobile-detector.js +16 -4
  280. package/dist/engine/model-router/complexity-analyzer.js +4 -7
  281. package/dist/engine/multi-agent-review/security-analyzer.js +3 -1
  282. package/dist/engine/multi-app-detector/app-type.js +26 -21
  283. package/dist/engine/multi-app-detector/core.js +3 -2
  284. package/dist/engine/multi-teammate-review/disagreement-counter.js +2 -1
  285. package/dist/engine/multi-teammate-review/panel-orchestrator.js +0 -2
  286. package/dist/engine/mutation-config-generator.js +10 -7
  287. package/dist/engine/native-capability-policy.d.ts +4 -0
  288. package/dist/engine/native-capability-policy.js +24 -0
  289. package/dist/engine/native-platform.d.ts +3 -0
  290. package/dist/engine/native-platform.js +44 -0
  291. package/dist/engine/native-runtime-handshake.d.ts +20 -0
  292. package/dist/engine/native-runtime-handshake.js +230 -0
  293. package/dist/engine/network-policy.d.ts +27 -0
  294. package/dist/engine/network-policy.js +175 -0
  295. package/dist/engine/next-spec-resolver/dependency-filter.js +2 -22
  296. package/dist/engine/nfr-profile-detector.js +12 -16
  297. package/dist/engine/nli-keywords.js +8 -9
  298. package/dist/engine/oauth/config-guard.js +4 -5
  299. package/dist/engine/observability/local-execution-spans.d.ts +15 -0
  300. package/dist/engine/observability/local-execution-spans.js +63 -0
  301. package/dist/engine/orchestrator/runtime.js +0 -1
  302. package/dist/engine/package-registry.js +2 -6
  303. package/dist/engine/performance-analyzer.js +2 -5
  304. package/dist/engine/permissions-merger/stack-detectors.js +5 -5
  305. package/dist/engine/planu-core.darwin-arm64.node.manifest.json +39 -0
  306. package/dist/engine/planu-core.darwin-arm64.node.sbom.json +1310 -0
  307. package/dist/engine/planu-core.darwin-x64.node.manifest.json +39 -0
  308. package/dist/engine/planu-core.darwin-x64.node.sbom.json +1310 -0
  309. package/dist/engine/planu-core.linux-arm64-gnu.node.manifest.json +38 -0
  310. package/dist/engine/planu-core.linux-arm64-gnu.node.sbom.json +1310 -0
  311. package/dist/engine/planu-core.linux-arm64-musl.node.manifest.json +38 -0
  312. package/dist/engine/planu-core.linux-arm64-musl.node.sbom.json +1310 -0
  313. package/dist/engine/planu-core.linux-x64-gnu.node.manifest.json +38 -0
  314. package/dist/engine/planu-core.linux-x64-gnu.node.sbom.json +1310 -0
  315. package/dist/engine/planu-core.linux-x64-musl.node.manifest.json +38 -0
  316. package/dist/engine/planu-core.linux-x64-musl.node.sbom.json +1310 -0
  317. package/dist/engine/planu-core.win32-arm64-msvc.node.manifest.json +38 -0
  318. package/dist/engine/planu-core.win32-arm64-msvc.node.sbom.json +1310 -0
  319. package/dist/engine/planu-core.win32-x64-msvc.node.manifest.json +38 -0
  320. package/dist/engine/planu-core.win32-x64-msvc.node.sbom.json +1310 -0
  321. package/dist/engine/platform-detector/desktop.js +15 -2
  322. package/dist/engine/platform-detector/extensions.js +2 -1
  323. package/dist/engine/platform-detector/games.js +2 -1
  324. package/dist/engine/platform-detector.js +3 -2
  325. package/dist/engine/platform-engineering/idp-detector.js +2 -1
  326. package/dist/engine/plugin-installer/stack-matcher.js +9 -17
  327. package/dist/engine/plugins/lifecycle.js +6 -2
  328. package/dist/engine/prior-decisions/contradiction-detector.js +60 -30
  329. package/dist/engine/project-dna/stack-detector.js +15 -17
  330. package/dist/engine/project-graph/builder.js +11 -0
  331. package/dist/engine/project-graph/cache.js +1 -1
  332. package/dist/engine/project-graph/freshness-projection.d.ts +16 -0
  333. package/dist/engine/project-graph/freshness-projection.js +95 -0
  334. package/dist/engine/project-graph/index.d.ts +1 -0
  335. package/dist/engine/project-graph/index.js +1 -0
  336. package/dist/engine/project-graph/query.js +15 -25
  337. package/dist/engine/project-health-checker.js +3 -4
  338. package/dist/engine/project-scanner/stack-detector.js +17 -17
  339. package/dist/engine/property-test-generator.js +2 -3
  340. package/dist/engine/qa-gate.d.ts +1 -0
  341. package/dist/engine/qa-gate.js +6 -4
  342. package/dist/engine/quality-gates/gate-catalog.js +47 -46
  343. package/dist/engine/quality-gates/gate-injector.js +9 -4
  344. package/dist/engine/readiness-checker.d.ts +1 -16
  345. package/dist/engine/readiness-checker.js +27 -88
  346. package/dist/engine/registry/core.js +0 -2
  347. package/dist/engine/registry/loader.js +9 -12
  348. package/dist/engine/registry/matcher.js +129 -24
  349. package/dist/engine/resilience-detector/concurrency-detector.js +4 -4
  350. package/dist/engine/resilience-detector/middleware-detector.js +11 -13
  351. package/dist/engine/resilience-detector/validation-detector.js +17 -4
  352. package/dist/engine/reverse-engineer/config-analyzer.js +9 -8
  353. package/dist/engine/reverse-engineer/orchestrator.js +5 -9
  354. package/dist/engine/reverse-engineer/test-file-parser.js +6 -3
  355. package/dist/engine/rules-generator/index.js +6 -5
  356. package/dist/engine/runtime-policy.d.ts +9 -0
  357. package/dist/engine/runtime-policy.js +138 -0
  358. package/dist/engine/runtime-security/checkers/content-security.js +21 -6
  359. package/dist/engine/runtime-security/checkers/file-permissions.js +0 -2
  360. package/dist/engine/runtime-security/rate-limiter.js +0 -1
  361. package/dist/engine/safety/atomic-write-file.js +20 -9
  362. package/dist/engine/safety/atomic-writer.js +10 -3
  363. package/dist/engine/safety/contained-project-file.d.ts +3 -0
  364. package/dist/engine/safety/contained-project-file.js +23 -0
  365. package/dist/engine/safety/cross-process-lock.d.ts +3 -40
  366. package/dist/engine/safety/cross-process-lock.js +268 -272
  367. package/dist/engine/safety/file-mutex.d.ts +2 -9
  368. package/dist/engine/safety/file-mutex.js +155 -87
  369. package/dist/engine/safety/health-monitor.js +15 -6
  370. package/dist/engine/safety/lock-lease-store.d.ts +79 -0
  371. package/dist/engine/safety/lock-lease-store.js +372 -0
  372. package/dist/engine/safety/lock-scavenger.d.ts +2 -5
  373. package/dist/engine/safety/lock-scavenger.js +158 -76
  374. package/dist/engine/safety/lock-staleness.js +4 -1
  375. package/dist/engine/safety/obsolete-lock-guard.d.ts +8 -0
  376. package/dist/engine/safety/obsolete-lock-guard.js +31 -0
  377. package/dist/engine/safety/transaction.js +3 -3
  378. package/dist/engine/sandbox/index.js +2 -1
  379. package/dist/engine/sandbox/runner-detect.js +3 -2
  380. package/dist/engine/sandbox/runner-docker.js +4 -3
  381. package/dist/engine/scan-project/module-discoverer.js +3 -2
  382. package/dist/engine/schema-generator.js +16 -9
  383. package/dist/engine/scope-boundaries/contradiction-checker.js +63 -1
  384. package/dist/engine/scope-boundaries/scope-validator.js +45 -7
  385. package/dist/engine/security-analyzer/criteria-generator.js +2 -3
  386. package/dist/engine/self-healing/healer.js +4 -4
  387. package/dist/engine/session/checkpoint-writer.js +0 -9
  388. package/dist/engine/shared-agent-memory.js +66 -74
  389. package/dist/engine/skill-adapter/command-rewriter.js +3 -2
  390. package/dist/engine/skill-adapter/index.js +3 -3
  391. package/dist/engine/skill-adapter/placeholder-map.js +3 -2
  392. package/dist/engine/skill-bootstrap/stack-matcher.js +47 -48
  393. package/dist/engine/skill-generation/stack-content-generator.js +0 -2
  394. package/dist/engine/skill-generator/workflow-skill-generator.js +2 -1
  395. package/dist/engine/skill-registry/ttl-refresh.js +3 -1
  396. package/dist/engine/skills/skills-fetcher.js +3 -6
  397. package/dist/engine/skills-reconciler.js +19 -39
  398. package/dist/engine/spec-coverage/test-finder.js +7 -6
  399. package/dist/engine/spec-diff-engine.js +3 -3
  400. package/dist/engine/spec-format/acceptance-criteria.d.ts +6 -2
  401. package/dist/engine/spec-format/acceptance-criteria.js +77 -18
  402. package/dist/engine/spec-format/markdown-sections.d.ts +14 -0
  403. package/dist/engine/spec-format/markdown-sections.js +105 -0
  404. package/dist/engine/spec-format/read-technical-section.js +33 -5
  405. package/dist/engine/spec-format/technical-md-populator.js +3 -2
  406. package/dist/engine/spec-format/unified-spec-builder.d.ts +7 -0
  407. package/dist/engine/spec-format/unified-spec-builder.js +202 -0
  408. package/dist/engine/spec-generator/api-key-resolver.d.ts +1 -1
  409. package/dist/engine/spec-generator/api-key-resolver.js +3 -24
  410. package/dist/engine/spec-generators/issue-extractor.js +9 -3
  411. package/dist/engine/spec-migrator/canonical-deduplicator.d.ts +18 -0
  412. package/dist/engine/spec-migrator/canonical-deduplicator.js +479 -0
  413. package/dist/engine/spec-migrator/drift-detector.js +5 -13
  414. package/dist/engine/spec-migrator/filesystem-import.d.ts +4 -8
  415. package/dist/engine/spec-migrator/filesystem-import.js +134 -23
  416. package/dist/engine/spec-migrator/frontmatter-parser.js +32 -15
  417. package/dist/engine/spec-migrator/index.d.ts +1 -0
  418. package/dist/engine/spec-migrator/index.js +1 -0
  419. package/dist/engine/spec-migrator/planu-canonical-policy.js +10 -1
  420. package/dist/engine/spec-migrator/strict-planu-cleanup.js +24 -25
  421. package/dist/engine/spec-registry/adapter.d.ts +0 -5
  422. package/dist/engine/spec-registry/adapter.js +45 -46
  423. package/dist/engine/spec-registry/client.js +2 -0
  424. package/dist/engine/spec-source-sync.js +3 -2
  425. package/dist/engine/spec-state-machine/transition-spec.d.ts +6 -1
  426. package/dist/engine/spec-state-machine/transition-spec.js +10 -1
  427. package/dist/engine/spec-templates/custom-loader.js +2 -3
  428. package/dist/engine/spec-templates/templates-domain-specific.js +8 -5
  429. package/dist/engine/spec-templates/templates-perf-integration.js +2 -3
  430. package/dist/engine/stack-auditor/manifest-reader.js +0 -2
  431. package/dist/engine/staleness/stale-implementing.js +7 -7
  432. package/dist/engine/tdd-scaffold-generator.js +24 -11
  433. package/dist/engine/teammate-router/green-phase-verifier.js +2 -1
  434. package/dist/engine/teammate-router/red-phase-verifier.js +2 -1
  435. package/dist/engine/technical-enricher/index.js +16 -8
  436. package/dist/engine/technical-enricher/render-enriched.d.ts +1 -0
  437. package/dist/engine/technical-enricher/render-enriched.js +42 -14
  438. package/dist/engine/technology-registry.d.ts +11 -0
  439. package/dist/engine/technology-registry.js +142 -0
  440. package/dist/engine/telemetry/error-reporter.d.ts +1 -2
  441. package/dist/engine/telemetry/error-reporter.js +11 -18
  442. package/dist/engine/telemetry/health-checker.js +58 -31
  443. package/dist/engine/telemetry/index.d.ts +0 -1
  444. package/dist/engine/telemetry/index.js +0 -1
  445. package/dist/engine/telemetry/stance.js +3 -2
  446. package/dist/engine/telemetry/telemetry-client.d.ts +1 -5
  447. package/dist/engine/telemetry/telemetry-client.js +69 -35
  448. package/dist/engine/telemetry/telemetry-store.d.ts +3 -3
  449. package/dist/engine/telemetry/telemetry-store.js +30 -23
  450. package/dist/engine/test-framework-detector/detectors.js +8 -8
  451. package/dist/engine/test-framework-detector/strategy.js +8 -9
  452. package/dist/engine/test-generators/agent-test-templates.js +2 -3
  453. package/dist/engine/test-generators/contract-test-generator.d.ts +1 -1
  454. package/dist/engine/test-generators/contract-test-generator.js +9 -202
  455. package/dist/engine/test-generators/platform-test-templates-b.js +2 -3
  456. package/dist/engine/test-generators/platform-test-templates.js +2 -5
  457. package/dist/engine/test-mocks-generator.js +4 -3
  458. package/dist/engine/test-plan-generator.js +30 -12
  459. package/dist/engine/test-scaffold-generator/advanced-scaffold.js +4 -5
  460. package/dist/engine/test-scaffold-generator/unit-scaffold.js +5 -6
  461. package/dist/engine/text-signal-boundaries.d.ts +2 -0
  462. package/dist/engine/text-signal-boundaries.js +25 -2
  463. package/dist/engine/time/relative-date.d.ts +3 -0
  464. package/dist/engine/time/relative-date.js +16 -0
  465. package/dist/engine/timing/budget.d.ts +17 -17
  466. package/dist/engine/timing/budget.js +98 -64
  467. package/dist/engine/token-optimizer/analytics.d.ts +1 -1
  468. package/dist/engine/token-optimizer/analytics.js +5 -6
  469. package/dist/engine/tool-groups/group-manager.js +3 -3
  470. package/dist/engine/universal-rules/installer.js +1 -1
  471. package/dist/engine/universal-rules/rules/planu-modes.js +2 -0
  472. package/dist/engine/universal-rules/rules/planu-release-policy.js +1 -0
  473. package/dist/engine/update-notifier.js +8 -5
  474. package/dist/engine/usage-tracker/core.d.ts +2 -2
  475. package/dist/engine/usage-tracker/core.js +1 -2
  476. package/dist/engine/usage-tracker/index.d.ts +0 -3
  477. package/dist/engine/usage-tracker/index.js +0 -3
  478. package/dist/engine/usage-tracker/stats.d.ts +2 -2
  479. package/dist/engine/usage-tracker/stats.js +1 -28
  480. package/dist/engine/validation/approved-spec-portability.d.ts +12 -0
  481. package/dist/engine/validation/approved-spec-portability.js +107 -0
  482. package/dist/engine/validation/durable-validation.d.ts +36 -0
  483. package/dist/engine/validation/durable-validation.js +256 -0
  484. package/dist/engine/validation/validation-freshness.d.ts +46 -0
  485. package/dist/engine/validation/validation-freshness.js +567 -0
  486. package/dist/engine/validation/validation-receipt-codec.d.ts +13 -0
  487. package/dist/engine/validation/validation-receipt-codec.js +182 -0
  488. package/dist/engine/validation/validation-receipt.d.ts +62 -0
  489. package/dist/engine/validation/validation-receipt.js +342 -0
  490. package/dist/engine/validation/validation-source-digest.d.ts +2 -0
  491. package/dist/engine/validation/validation-source-digest.js +86 -0
  492. package/dist/engine/validation/validation-source-policy.d.ts +4 -0
  493. package/dist/engine/validation/validation-source-policy.js +16 -0
  494. package/dist/engine/validation/validation-submission.d.ts +37 -0
  495. package/dist/engine/validation/validation-submission.js +142 -0
  496. package/dist/engine/validation/validation-worktree.d.ts +21 -0
  497. package/dist/engine/validation/validation-worktree.js +260 -0
  498. package/dist/engine/validation-evidence-ledger.js +41 -0
  499. package/dist/engine/validation-impact-planner.d.ts +14 -2
  500. package/dist/engine/validation-impact-planner.js +23 -10
  501. package/dist/engine/validator/dor-dod.d.ts +1 -0
  502. package/dist/engine/validator/dor-dod.js +5 -3
  503. package/dist/engine/validator/extractors.d.ts +1 -5
  504. package/dist/engine/validator/extractors.js +24 -69
  505. package/dist/engine/validator/spec-compliance-runner.d.ts +13 -25
  506. package/dist/engine/validator/spec-compliance-runner.js +442 -215
  507. package/dist/engine/validator/validation-report-writer.js +1 -1
  508. package/dist/engine/validator.js +37 -23
  509. package/dist/engine/verify-integrations/index.js +1 -1
  510. package/dist/engine/version-resolver.js +5 -6
  511. package/dist/engine/web-fetcher/stack-advisor.js +156 -92
  512. package/dist/engine/web-fetcher/stack-detector.js +114 -54
  513. package/dist/engine/workspace-manager.js +3 -2
  514. package/dist/errors/classified-degradation.d.ts +3 -0
  515. package/dist/errors/classified-degradation.js +10 -0
  516. package/dist/errors/degradation-sink.d.ts +3 -0
  517. package/dist/errors/degradation-sink.js +5 -0
  518. package/dist/errors/error-taxonomy.d.ts +12 -0
  519. package/dist/errors/error-taxonomy.js +62 -0
  520. package/dist/hosts/claude-code/ux/mcp-prompts.js +10 -4
  521. package/dist/hosts/claude-code/ux/mcp-resources.js +4 -2
  522. package/dist/hosts/codex/config-scaffold.js +4 -3
  523. package/dist/hosts/gemini/config-scaffold.js +2 -1
  524. package/dist/hosts/gemini/multimodal-spec-flow.js +7 -4
  525. package/dist/index.js +23 -20
  526. package/dist/resources/patterns.js +3 -1
  527. package/dist/resources/specs.js +3 -1
  528. package/dist/resources/templates.js +3 -1
  529. package/dist/resources/usage-stats-resource.js +2 -18
  530. package/dist/security/adapters/environment.d.ts +12 -0
  531. package/dist/security/adapters/environment.js +25 -0
  532. package/dist/security/adapters/linux-secret-service.d.ts +8 -0
  533. package/dist/security/adapters/linux-secret-service.js +64 -0
  534. package/dist/security/adapters/macos-keychain.d.ts +18 -0
  535. package/dist/security/adapters/macos-keychain.js +90 -0
  536. package/dist/security/adapters/windows-credential-manager.d.ts +8 -0
  537. package/dist/security/adapters/windows-credential-manager.js +60 -0
  538. package/dist/security/redactor.d.ts +5 -0
  539. package/dist/security/redactor.js +58 -0
  540. package/dist/security/secret-field.d.ts +5 -0
  541. package/dist/security/secret-field.js +17 -0
  542. package/dist/security/secret-migration.d.ts +3 -0
  543. package/dist/security/secret-migration.js +123 -0
  544. package/dist/security/secret-provider.d.ts +23 -0
  545. package/dist/security/secret-provider.js +145 -0
  546. package/dist/security/secure-json.d.ts +3 -0
  547. package/dist/security/secure-json.js +29 -0
  548. package/dist/server/routes/specs.js +10 -0
  549. package/dist/storage/api-surfaces-store.js +2 -2
  550. package/dist/storage/approval-operation-lock.d.ts +1 -1
  551. package/dist/storage/approval-operation-lock.js +5 -3
  552. package/dist/storage/audit-trail-store.d.ts +1 -1
  553. package/dist/storage/audit-trail-store.js +48 -62
  554. package/dist/storage/autopilot-log-store.js +12 -5
  555. package/dist/storage/base-store.d.ts +9 -9
  556. package/dist/storage/base-store.js +58 -21
  557. package/dist/storage/checkpoint-store.js +5 -2
  558. package/dist/storage/comments-store.js +2 -2
  559. package/dist/storage/compliance-audit-store.js +5 -2
  560. package/dist/storage/compliance-gate-config-store.js +7 -4
  561. package/dist/storage/compliance-store.js +2 -2
  562. package/dist/storage/context-profile-store.js +2 -2
  563. package/dist/storage/crash-shield-store.js +8 -4
  564. package/dist/storage/feedback-remote.d.ts +2 -3
  565. package/dist/storage/feedback-remote.js +45 -31
  566. package/dist/storage/feedback-store.js +10 -6
  567. package/dist/storage/figma-store.js +8 -4
  568. package/dist/storage/file-mutex.js +9 -1
  569. package/dist/storage/gaps-log.js +7 -4
  570. package/dist/storage/global-projects-store.js +4 -2
  571. package/dist/storage/global-store.d.ts +1 -17
  572. package/dist/storage/global-store.js +1 -42
  573. package/dist/storage/ideas-store.js +2 -2
  574. package/dist/storage/index.d.ts +5 -2
  575. package/dist/storage/index.js +5 -2
  576. package/dist/storage/knowledge-store/knowledge.js +27 -33
  577. package/dist/storage/lessons-store.js +2 -2
  578. package/dist/storage/migrations/canonical-storage.d.ts +15 -0
  579. package/dist/storage/migrations/canonical-storage.js +712 -0
  580. package/dist/storage/oauth-store.js +36 -8
  581. package/dist/storage/path-resolver.js +16 -3
  582. package/dist/storage/pr-store.js +2 -2
  583. package/dist/storage/project-drift-store.js +20 -8
  584. package/dist/storage/project-identity.d.ts +32 -0
  585. package/dist/storage/project-identity.js +194 -0
  586. package/dist/storage/project-resolver.js +14 -7
  587. package/dist/storage/release-notes-store.js +2 -6
  588. package/dist/storage/runtime-db.d.ts +195 -0
  589. package/dist/storage/runtime-db.js +1110 -0
  590. package/dist/storage/schema-registry.d.ts +5 -0
  591. package/dist/storage/schema-registry.js +74 -0
  592. package/dist/storage/sentry-store.js +20 -9
  593. package/dist/storage/session-state-store.js +12 -5
  594. package/dist/storage/skill-registry-storage.d.ts +1 -1
  595. package/dist/storage/skill-registry-storage.js +13 -11
  596. package/dist/storage/slack-store.js +10 -5
  597. package/dist/storage/spec-store.d.ts +14 -2
  598. package/dist/storage/spec-store.js +134 -37
  599. package/dist/storage/status-store/atomic-status-write.d.ts +5 -0
  600. package/dist/storage/status-store/atomic-status-write.js +57 -0
  601. package/dist/storage/status-store/file-lock.js +61 -20
  602. package/dist/storage/status-store/self-healing.js +13 -8
  603. package/dist/storage/status-store/version-sync.d.ts +2 -1
  604. package/dist/storage/status-store/version-sync.js +36 -39
  605. package/dist/storage/steering-store.js +2 -2
  606. package/dist/storage/storage-bundle.d.ts +5 -0
  607. package/dist/storage/storage-bundle.js +117 -0
  608. package/dist/storage/storage-catalog-validation.d.ts +3 -0
  609. package/dist/storage/storage-catalog-validation.js +20 -0
  610. package/dist/storage/storage-catalog.d.ts +25 -0
  611. package/dist/storage/storage-catalog.js +390 -0
  612. package/dist/storage/storage-layout.d.ts +24 -0
  613. package/dist/storage/storage-layout.js +101 -0
  614. package/dist/storage/storybook-store.js +2 -2
  615. package/dist/storage/supabase-store.js +24 -6
  616. package/dist/storage/tdd-policy-store.js +8 -6
  617. package/dist/storage/tech-debt-store.js +3 -3
  618. package/dist/storage/technology-selection-store.d.ts +1 -1
  619. package/dist/storage/technology-selection-store.js +6 -3
  620. package/dist/storage/token-cache-store.js +3 -3
  621. package/dist/storage/token-ledger-store.js +13 -8
  622. package/dist/storage/transition-log.js +7 -4
  623. package/dist/storage/trash-store.js +15 -6
  624. package/dist/storage/usage-store.d.ts +1 -5
  625. package/dist/storage/usage-store.js +0 -35
  626. package/dist/storage/vector-store/migrator.js +7 -2
  627. package/dist/storage/vector-store/sqlite-adapter.js +4 -1
  628. package/dist/storage/webhook-server-store.js +2 -2
  629. package/dist/tools/api-spec-generator-handler.js +3 -2
  630. package/dist/tools/auto-update-handler.d.ts +4 -4
  631. package/dist/tools/auto-update-handler.js +4 -4
  632. package/dist/tools/browser-validate-handler.js +2 -1
  633. package/dist/tools/challenge-spec/platform-challenge-scenarios-b.js +8 -5
  634. package/dist/tools/challenge-spec/resilience-challenge-scenarios.d.ts +2 -1
  635. package/dist/tools/challenge-spec/resilience-challenge-scenarios.js +10 -7
  636. package/dist/tools/challenge-spec/scenario-collector.js +1 -1
  637. package/dist/tools/challenge-spec/scenarios-data.js +1 -1
  638. package/dist/tools/challenge-spec/scenarios-desktop.js +8 -3
  639. package/dist/tools/challenge-spec/scenarios-failure.js +7 -2
  640. package/dist/tools/challenge-spec/scenarios-utils.d.ts +1 -1
  641. package/dist/tools/challenge-spec/scenarios-utils.js +35 -11
  642. package/dist/tools/challenge-spec/security-challenge-scenarios.js +3 -3
  643. package/dist/tools/challenge-spec.js +5 -5
  644. package/dist/tools/check-readiness.js +1 -1
  645. package/dist/tools/clarify-requirements/multiple-choice.js +53 -41
  646. package/dist/tools/comments-handler.js +2 -3
  647. package/dist/tools/compliance-test-handler.js +2 -2
  648. package/dist/tools/configure-telemetry.js +41 -13
  649. package/dist/tools/create-spec/auto-pipeline.js +13 -1
  650. package/dist/tools/create-spec/autopilot-analyzer.d.ts +1 -1
  651. package/dist/tools/create-spec/autopilot-analyzer.js +2 -4
  652. package/dist/tools/create-spec/mcp-tool-contract.d.ts +10 -4
  653. package/dist/tools/create-spec/mcp-tool-contract.js +7 -36
  654. package/dist/tools/create-spec/post-creation.d.ts +2 -1
  655. package/dist/tools/create-spec/post-creation.js +56 -54
  656. package/dist/tools/create-spec/relevance-scorer.d.ts +1 -1
  657. package/dist/tools/create-spec/relevance-scorer.js +17 -1
  658. package/dist/tools/create-spec/spec-builder.js +2 -23
  659. package/dist/tools/create-spec/spec-created-outbox-consumer.d.ts +14 -0
  660. package/dist/tools/create-spec/spec-created-outbox-consumer.js +176 -0
  661. package/dist/tools/create-spec.d.ts +1 -0
  662. package/dist/tools/create-spec.js +802 -732
  663. package/dist/tools/define-ui-contract/agent-interaction-contract.js +2 -4
  664. package/dist/tools/define-ui-contract-desktop/desktop-contract.js +12 -4
  665. package/dist/tools/define-ui-contract-desktop/native-contract.js +7 -3
  666. package/dist/tools/define-ui-contract-extensions.js +2 -3
  667. package/dist/tools/define-ui-contract-mobile.js +5 -9
  668. package/dist/tools/define-ui-contract-web/component-tree.js +4 -3
  669. package/dist/tools/define-ui-contract.js +7 -4
  670. package/dist/tools/deploy/deploy-spec.js +2 -4
  671. package/dist/tools/deploy/deploy-status.js +2 -4
  672. package/dist/tools/design-schema/nosql-category-schemas.js +2 -3
  673. package/dist/tools/design-schema-sql/migrations.js +3 -2
  674. package/dist/tools/design-schema-sql/tables.js +4 -1
  675. package/dist/tools/design-schema.js +4 -3
  676. package/dist/tools/feedback-handler.js +2 -4
  677. package/dist/tools/gc-data-projects.js +5 -5
  678. package/dist/tools/generate-execution-plan.js +3 -4
  679. package/dist/tools/generate-sub-agent.js +2 -1
  680. package/dist/tools/generate-tests/generators/a11y-tests-generator.js +5 -4
  681. package/dist/tools/generate-tests/generators/advanced-testing-generator.js +5 -4
  682. package/dist/tools/generate-tests/generators/concurrency-test-generator/js-templates.js +9 -4
  683. package/dist/tools/generate-tests/generators/concurrency-test-generator.js +8 -4
  684. package/dist/tools/generate-tests/generators/database/detectors.js +9 -3
  685. package/dist/tools/generate-tests/generators/database/index.js +2 -4
  686. package/dist/tools/generate-tests/generators/event-test-generator.js +5 -4
  687. package/dist/tools/generate-tests/generators/game-tests-generator.js +2 -1
  688. package/dist/tools/generate-tests/generators/graphql-test-generator.js +11 -5
  689. package/dist/tools/generate-tests/generators/grpc-test-generator.js +2 -3
  690. package/dist/tools/generate-tests/generators/llm-security-test-generator.js +4 -3
  691. package/dist/tools/generate-tests/generators/local-first-test-generator.js +4 -3
  692. package/dist/tools/generate-tests/generators/mcp-tests-generator.js +11 -9
  693. package/dist/tools/generate-tests/generators/microservices/index.js +2 -3
  694. package/dist/tools/generate-tests/generators/otel-test-generator.js +6 -3
  695. package/dist/tools/generate-tests/generators/security/detectors.js +2 -5
  696. package/dist/tools/generate-tests/generators/security/index.js +2 -4
  697. package/dist/tools/generate-tests/generators/supply-chain-test-generator.js +2 -3
  698. package/dist/tools/generate-tests/generators/visual-regression-generator.js +14 -17
  699. package/dist/tools/generate-tests/generators/websocket-test-generator.js +2 -3
  700. package/dist/tools/generate-tests/test-helpers.js +11 -12
  701. package/dist/tools/generate-tests-content.js +4 -3
  702. package/dist/tools/generate-tests.js +7 -4
  703. package/dist/tools/git/branch-ops.d.ts +1 -1
  704. package/dist/tools/git/branch-ops.js +3 -2
  705. package/dist/tools/git/git-helpers.d.ts +0 -2
  706. package/dist/tools/git/git-helpers.js +7 -7
  707. package/dist/tools/github-pr-handler.js +10 -3
  708. package/dist/tools/heal-spec-docs.js +6 -53
  709. package/dist/tools/hook-generator-handler.js +6 -6
  710. package/dist/tools/init-constitution/platform-principles.js +4 -2
  711. package/dist/tools/init-project/agents-md-writer.js +14 -5
  712. package/dist/tools/init-project/claude-md-generator.js +19 -12
  713. package/dist/tools/init-project/handler.js +165 -75
  714. package/dist/tools/init-project/host-assets-writer.d.ts +1 -1
  715. package/dist/tools/init-project/host-assets-writer.js +30 -3
  716. package/dist/tools/init-project/lifecycle-helpers.js +3 -5
  717. package/dist/tools/init-project/lint-scaffolder.d.ts +3 -3
  718. package/dist/tools/init-project/lint-scaffolder.js +6 -2
  719. package/dist/tools/init-project/migration-runner.d.ts +8 -1
  720. package/dist/tools/init-project/migration-runner.js +68 -2
  721. package/dist/tools/init-project/per-client-files-writer.js +14 -4
  722. package/dist/tools/init-project/portable-index-reconciler.d.ts +4 -0
  723. package/dist/tools/init-project/portable-index-reconciler.js +14 -0
  724. package/dist/tools/init-project/result-builder.js +1 -3
  725. package/dist/tools/init-project/rules-generator.js +10 -2
  726. package/dist/tools/init-project/scaffold-writer.d.ts +1 -1
  727. package/dist/tools/init-project/scaffold-writer.js +17 -15
  728. package/dist/tools/jobs/handlers.d.ts +15 -0
  729. package/dist/tools/jobs/handlers.js +158 -0
  730. package/dist/tools/list-specs.js +39 -59
  731. package/dist/tools/manage-plugins-handler.js +17 -9
  732. package/dist/tools/merge-risk-handler.js +2 -2
  733. package/dist/tools/migrate-tech/advanced-handlers.js +3 -2
  734. package/dist/tools/migrate-tech/build-tool-handlers.js +3 -2
  735. package/dist/tools/migrate-tech/core-handlers.js +5 -2
  736. package/dist/tools/migrate-tech/data-handlers.js +6 -3
  737. package/dist/tools/migrate-tech-advanced/rollback-handlers.js +3 -2
  738. package/dist/tools/migrate-tech-advanced/service-handlers.js +5 -2
  739. package/dist/tools/oauth-handler.js +7 -1
  740. package/dist/tools/package-handoff.js +2 -0
  741. package/dist/tools/reconcile-spec.js +0 -27
  742. package/dist/tools/register-agent-squad-tools.js +2 -2
  743. package/dist/tools/register-platform-tools/design-stack-tools.js +11 -11
  744. package/dist/tools/register-platform-tools/lifecycle-infra-tools.js +7 -7
  745. package/dist/tools/register-sdd-tools.d.ts +1 -1
  746. package/dist/tools/register-sdd-tools.js +2 -24
  747. package/dist/tools/register-spec-tools/analysis-tools.js +8 -8
  748. package/dist/tools/register-spec-tools/core-spec-tools.js +48 -8
  749. package/dist/tools/registry/auth.js +13 -5
  750. package/dist/tools/registry/publish.js +7 -4
  751. package/dist/tools/resolve-project-path.d.ts +2 -2
  752. package/dist/tools/resolve-project-path.js +7 -7
  753. package/dist/tools/reverse-engineer/analyzer.js +14 -14
  754. package/dist/tools/rollback-release.js +3 -2
  755. package/dist/tools/safe-handler.d.ts +5 -13
  756. package/dist/tools/safe-handler.js +302 -194
  757. package/dist/tools/schema-generator-handler.js +2 -1
  758. package/dist/tools/schemas/index.d.ts +1 -1
  759. package/dist/tools/schemas/index.js +1 -1
  760. package/dist/tools/schemas/output-schemas.d.ts +88 -105
  761. package/dist/tools/schemas/output-schemas.js +12 -122
  762. package/dist/tools/schemas/plugins-schemas.js +0 -2
  763. package/dist/tools/schemas/registry.js +0 -2
  764. package/dist/tools/schemas/skill-registry-schemas.js +0 -2
  765. package/dist/tools/schemas/spec.d.ts +4 -0
  766. package/dist/tools/schemas/spec.js +3 -0
  767. package/dist/tools/schemas/validate-output-schema.d.ts +267 -0
  768. package/dist/tools/schemas/validate-output-schema.js +219 -0
  769. package/dist/tools/sentry-handler.js +6 -1
  770. package/dist/tools/skill-bootstrap-handler.js +7 -4
  771. package/dist/tools/spec-prompt-handler.js +3 -3
  772. package/dist/tools/status-handler.js +4 -0
  773. package/dist/tools/storage-bundle-handler.d.ts +9 -0
  774. package/dist/tools/storage-bundle-handler.js +29 -0
  775. package/dist/tools/storage-paths-handler.d.ts +9 -0
  776. package/dist/tools/storage-paths-handler.js +17 -0
  777. package/dist/tools/suggest-mcp-server.js +11 -5
  778. package/dist/tools/suggest-mcps.js +29 -9
  779. package/dist/tools/suggest-tooling/advanced-testing-catalog.js +4 -5
  780. package/dist/tools/suggest-tooling/build-tool-catalog.js +2 -1
  781. package/dist/tools/suggest-tooling/css-framework-catalog.js +13 -7
  782. package/dist/tools/suggest-tooling/framework-catalog.js +3 -5
  783. package/dist/tools/suggest-tooling/frontend-perf-catalog.js +2 -6
  784. package/dist/tools/suggest-tooling/handler.js +10 -4
  785. package/dist/tools/suggest-tooling/hypermedia-catalog.js +11 -3
  786. package/dist/tools/suggest-tooling/linting-catalog.js +4 -7
  787. package/dist/tools/suggest-tooling/llm-security-catalog.js +2 -1
  788. package/dist/tools/suggest-tooling/local-first-catalog.js +7 -5
  789. package/dist/tools/suggest-tooling/observability-catalog.js +3 -4
  790. package/dist/tools/suggest-tooling/otel-catalog.js +4 -1
  791. package/dist/tools/suggest-tooling/resilience-catalog.js +16 -5
  792. package/dist/tools/suggest-tooling/skills-catalog.js +10 -9
  793. package/dist/tools/suggest-tooling/supply-chain-catalog.js +2 -3
  794. package/dist/tools/supabase-handler.js +2 -1
  795. package/dist/tools/sync-spec-state-handler.d.ts +1 -1
  796. package/dist/tools/sync-spec-state-handler.js +1 -1
  797. package/dist/tools/token-intelligence-handler.js +2 -2
  798. package/dist/tools/token-recording.js +2 -2
  799. package/dist/tools/token-savings-handler.js +2 -2
  800. package/dist/tools/tool-entry.d.ts +4 -4
  801. package/dist/tools/tool-entry.js +3 -3
  802. package/dist/tools/tool-registry/core-tools.js +162 -15
  803. package/dist/tools/tool-registry/group-infra.js +37 -122
  804. package/dist/tools/tool-registry/group-quality-compliance.js +31 -38
  805. package/dist/tools/tool-registry/inventory.d.ts +2 -0
  806. package/dist/tools/tool-registry/inventory.js +2 -0
  807. package/dist/tools/tool-registry-helpers.d.ts +3 -3
  808. package/dist/tools/tool-registry-helpers.js +3 -3
  809. package/dist/tools/tool-usage-report/registered-tools.d.ts +1 -1
  810. package/dist/tools/tool-usage-report/registered-tools.js +3 -15
  811. package/dist/tools/update-status/approval-gates.d.ts +13 -0
  812. package/dist/tools/update-status/approval-gates.js +84 -0
  813. package/dist/tools/update-status/batch.js +4 -2
  814. package/dist/tools/update-status/dod-gates.d.ts +6 -24
  815. package/dist/tools/update-status/dod-gates.js +60 -135
  816. package/dist/tools/update-status/done-receipt-verifier.d.ts +15 -0
  817. package/dist/tools/update-status/done-receipt-verifier.js +158 -0
  818. package/dist/tools/update-status/evidence-gate.js +190 -3
  819. package/dist/tools/update-status/file-sync.d.ts +2 -1
  820. package/dist/tools/update-status/file-sync.js +80 -18
  821. package/dist/tools/update-status/gate-harness.d.ts +7 -0
  822. package/dist/tools/update-status/gate-harness.js +8 -0
  823. package/dist/tools/update-status/index.d.ts +2 -0
  824. package/dist/tools/update-status/index.js +307 -367
  825. package/dist/tools/update-status/qa-gate.d.ts +1 -1
  826. package/dist/tools/update-status/qa-gate.js +2 -2
  827. package/dist/tools/update-status/response-builder.js +3 -3
  828. package/dist/tools/update-status/side-effects.d.ts +2 -0
  829. package/dist/tools/update-status/side-effects.js +32 -39
  830. package/dist/tools/update-status/transition-guard.d.ts +4 -2
  831. package/dist/tools/update-status/transition-guard.js +89 -25
  832. package/dist/tools/update-status-actions.d.ts +4 -2
  833. package/dist/tools/update-status-actions.js +16 -14
  834. package/dist/tools/update-status-convention-gate.js +24 -23
  835. package/dist/tools/update-status-reconcile.js +2 -2
  836. package/dist/tools/usage-report.js +1 -16
  837. package/dist/tools/usage-stats.js +1 -18
  838. package/dist/tools/usage-tracking.d.ts +4 -0
  839. package/dist/tools/usage-tracking.js +20 -0
  840. package/dist/tools/validate-api-contract-handler.js +3 -3
  841. package/dist/tools/validate-lint.d.ts +1 -0
  842. package/dist/tools/validate-lint.js +21 -14
  843. package/dist/tools/validate.d.ts +4 -1
  844. package/dist/tools/validate.js +319 -31
  845. package/dist/transports/http-transport.js +87 -66
  846. package/dist/transports/mcp-types.d.ts +0 -2
  847. package/dist/transports/middleware/with-telemetry.js +3 -2
  848. package/dist/transports/session-context.js +1 -1
  849. package/dist/types/abortable-process.d.ts +2 -0
  850. package/dist/types/advanced-framework.js +0 -2
  851. package/dist/types/atomic-upgrade.d.ts +71 -0
  852. package/dist/types/atomic-upgrade.js +2 -0
  853. package/dist/types/cascade-hooks.d.ts +1 -1
  854. package/dist/types/ci.d.ts +0 -4
  855. package/dist/types/ci.js +0 -2
  856. package/dist/types/clarification-token.d.ts +1 -1
  857. package/dist/types/claude-code-runtime.d.ts +0 -27
  858. package/dist/types/commercial-migration.d.ts +17 -0
  859. package/dist/types/commercial-migration.js +2 -0
  860. package/dist/types/common/primitives.d.ts +0 -2
  861. package/dist/types/core-bridge.d.ts +81 -10
  862. package/dist/types/crash-shield-framework-rules.d.ts +24 -0
  863. package/dist/types/crash-shield-framework-rules.js +2 -0
  864. package/dist/types/dashboard.d.ts +3 -7
  865. package/dist/types/data-gc.d.ts +16 -0
  866. package/dist/types/deploy.js +0 -2
  867. package/dist/types/docs.d.ts +0 -1
  868. package/dist/types/durable-job.d.ts +78 -0
  869. package/dist/types/durable-job.js +2 -0
  870. package/dist/types/durable-validation.d.ts +158 -0
  871. package/dist/types/durable-validation.js +166 -0
  872. package/dist/types/errors/structured-error.d.ts +3 -3
  873. package/dist/types/estimation.d.ts +4 -0
  874. package/dist/types/evidence-gates.d.ts +17 -1
  875. package/dist/types/execution.d.ts +45 -0
  876. package/dist/types/gemini-integration.d.ts +0 -11
  877. package/dist/types/handoff-artifacts.d.ts +43 -0
  878. package/dist/types/hooks-advanced.d.ts +0 -13
  879. package/dist/types/impact-detection.d.ts +2 -2
  880. package/dist/types/index.d.ts +4 -6
  881. package/dist/types/index.js +3 -5
  882. package/dist/types/infrastructure.js +0 -2
  883. package/dist/types/kiro-integration.d.ts +0 -6
  884. package/dist/types/lifecycle.js +0 -2
  885. package/dist/types/migration/canonical-storage.d.ts +37 -0
  886. package/dist/types/migration/canonical-storage.js +2 -0
  887. package/dist/types/migration/index.d.ts +1 -1
  888. package/dist/types/native-worker.d.ts +48 -0
  889. package/dist/types/native-worker.js +2 -0
  890. package/dist/types/network-policy.d.ts +12 -0
  891. package/dist/types/network-policy.js +2 -0
  892. package/dist/types/oauth.js +0 -2
  893. package/dist/types/observability.d.ts +32 -0
  894. package/dist/types/outbox-worker.d.ts +35 -0
  895. package/dist/types/outbox-worker.js +11 -0
  896. package/dist/types/permissions-config.d.ts +0 -27
  897. package/dist/types/permissions-config.js +0 -2
  898. package/dist/types/plugin-install.d.ts +0 -11
  899. package/dist/types/plugin-install.js +0 -2
  900. package/dist/types/portal.d.ts +1 -0
  901. package/dist/types/product-public.d.ts +75 -0
  902. package/dist/types/product-public.js +2 -0
  903. package/dist/types/project/inputs.d.ts +2 -0
  904. package/dist/types/project/lint-scaffolder.d.ts +1 -1
  905. package/dist/types/project/mfe-detection.js +0 -2
  906. package/dist/types/project/platform-mobile.js +0 -2
  907. package/dist/types/project/platform-specialty.js +0 -2
  908. package/dist/types/project-knowledge-graph.d.ts +7 -0
  909. package/dist/types/runtime-database.d.ts +10 -0
  910. package/dist/types/runtime-database.js +2 -0
  911. package/dist/types/runtime-policy.d.ts +51 -0
  912. package/dist/types/runtime-policy.js +2 -0
  913. package/dist/types/safety.d.ts +4 -5
  914. package/dist/types/schema-registry.d.ts +12 -0
  915. package/dist/types/schema-registry.js +2 -0
  916. package/dist/types/security.d.ts +52 -0
  917. package/dist/types/session-safeguard.d.ts +0 -31
  918. package/dist/types/skill-registry.js +0 -2
  919. package/dist/types/spec/canonical-repair.d.ts +81 -0
  920. package/dist/types/spec/canonical-repair.js +2 -0
  921. package/dist/types/spec/core.d.ts +14 -0
  922. package/dist/types/spec/index.d.ts +1 -0
  923. package/dist/types/spec/index.js +1 -0
  924. package/dist/types/spec/inputs.d.ts +31 -0
  925. package/dist/types/spec-format.d.ts +24 -0
  926. package/dist/types/spec-lock-v2.d.ts +13 -7
  927. package/dist/types/spec-lock-v2.js +1 -1
  928. package/dist/types/spec-registry.js +0 -2
  929. package/dist/types/storage-bundle.d.ts +13 -0
  930. package/dist/types/storage-bundle.js +2 -0
  931. package/dist/types/storage-catalog.d.ts +18 -0
  932. package/dist/types/storage-catalog.js +2 -0
  933. package/dist/types/team-planner.js +0 -2
  934. package/dist/types/technology-registry.d.ts +35 -0
  935. package/dist/types/technology-registry.js +2 -0
  936. package/dist/types/technology-symbols.generated.d.ts +117 -0
  937. package/dist/types/technology-symbols.generated.js +2 -0
  938. package/dist/types/telemetry.d.ts +7 -4
  939. package/dist/types/transport.d.ts +2 -2
  940. package/dist/types/usage.d.ts +1 -36
  941. package/dist/types/usage.js +1 -1
  942. package/dist/types/validate-worker.d.ts +50 -0
  943. package/dist/types/validate-worker.js +2 -0
  944. package/dist/types/validation-evidence.d.ts +1 -1
  945. package/dist/types/validation-receipt.d.ts +104 -0
  946. package/dist/types/validation-receipt.js +2 -0
  947. package/dist/types/validation.d.ts +2 -2
  948. package/package.json +36 -21
  949. package/planu-native.json +1 -1
  950. package/planu-plugin.json +23 -40
  951. package/scripts/lib/pending-release-file.mjs +93 -0
  952. package/src/i18n/messages/en.json +0 -41
  953. package/src/i18n/messages/es.json +0 -41
  954. package/src/i18n/messages/pt.json +0 -41
  955. package/dist/cli/commands/activate.d.ts +0 -14
  956. package/dist/cli/commands/activate.js +0 -174
  957. package/dist/config/license-plans.json +0 -244
  958. package/dist/config/server-instructions.ts +0 -121
  959. package/dist/config/version-defaults.ts +0 -76
  960. package/dist/config/version.ts +0 -18
  961. package/dist/engine/ai-integration/gemini/settings-generator.d.ts +0 -4
  962. package/dist/engine/ai-integration/gemini/settings-generator.js +0 -195
  963. package/dist/engine/ai-integration/kiro/hooks-generator.d.ts +0 -6
  964. package/dist/engine/ai-integration/kiro/hooks-generator.js +0 -75
  965. package/dist/engine/hooks/full-spectrum-generator.d.ts +0 -32
  966. package/dist/engine/hooks/full-spectrum-generator.js +0 -117
  967. package/dist/engine/license-validator/config-loader.d.ts +0 -5
  968. package/dist/engine/license-validator/config-loader.js +0 -16
  969. package/dist/engine/license-validator/core.d.ts +0 -15
  970. package/dist/engine/license-validator/core.js +0 -151
  971. package/dist/engine/license-validator/fingerprint.d.ts +0 -3
  972. package/dist/engine/license-validator/fingerprint.js +0 -17
  973. package/dist/engine/license-validator/lemon-squeezy.d.ts +0 -5
  974. package/dist/engine/license-validator/lemon-squeezy.js +0 -55
  975. package/dist/engine/license-validator.d.ts +0 -5
  976. package/dist/engine/license-validator.js +0 -6
  977. package/dist/engine/product-intelligence/index.d.ts +0 -7
  978. package/dist/engine/product-intelligence/index.js +0 -211
  979. package/dist/engine/session/auto-save.d.ts +0 -18
  980. package/dist/engine/session/auto-save.js +0 -98
  981. package/dist/engine/session/context-snapshot.d.ts +0 -8
  982. package/dist/engine/session/context-snapshot.js +0 -49
  983. package/dist/engine/session/memory-sync.d.ts +0 -12
  984. package/dist/engine/session/memory-sync.js +0 -34
  985. package/dist/engine/session/session-diff.d.ts +0 -11
  986. package/dist/engine/session/session-diff.js +0 -42
  987. package/dist/engine/session/session-merge.d.ts +0 -12
  988. package/dist/engine/session/session-merge.js +0 -55
  989. package/dist/engine/session-safeguard/checkpoint-runner.d.ts +0 -4
  990. package/dist/engine/session-safeguard/checkpoint-runner.js +0 -70
  991. package/dist/engine/session-safeguard/learnings-buffer.d.ts +0 -16
  992. package/dist/engine/session-safeguard/learnings-buffer.js +0 -114
  993. package/dist/engine/session-safeguard/precompaction-drain.d.ts +0 -10
  994. package/dist/engine/session-safeguard/precompaction-drain.js +0 -82
  995. package/dist/engine/session-safeguard/unpushed-detector.d.ts +0 -7
  996. package/dist/engine/session-safeguard/unpushed-detector.js +0 -59
  997. package/dist/engine/spec-changelog/core.d.ts +0 -16
  998. package/dist/engine/spec-changelog/core.js +0 -176
  999. package/dist/engine/spec-changelog/diff.d.ts +0 -18
  1000. package/dist/engine/spec-changelog/diff.js +0 -121
  1001. package/dist/engine/spec-changelog/index.d.ts +0 -3
  1002. package/dist/engine/spec-changelog/index.js +0 -4
  1003. package/dist/engine/telemetry/geo-resolver.d.ts +0 -9
  1004. package/dist/engine/telemetry/geo-resolver.js +0 -43
  1005. package/dist/engine/trial-engine.d.ts +0 -5
  1006. package/dist/engine/trial-engine.js +0 -14
  1007. package/dist/engine/usage-tracker/rate-check.d.ts +0 -7
  1008. package/dist/engine/usage-tracker/rate-check.js +0 -18
  1009. package/dist/engine/usage-tracker/rate-limiter.d.ts +0 -14
  1010. package/dist/engine/usage-tracker/rate-limiter.js +0 -73
  1011. package/dist/engine/usage-tracker/trial.d.ts +0 -27
  1012. package/dist/engine/usage-tracker/trial.js +0 -49
  1013. package/dist/engine/webhook/event-handlers.d.ts +0 -25
  1014. package/dist/engine/webhook/event-handlers.js +0 -89
  1015. package/dist/engine/webhook/index.d.ts +0 -4
  1016. package/dist/engine/webhook/index.js +0 -5
  1017. package/dist/engine/webhook/server.d.ts +0 -12
  1018. package/dist/engine/webhook/server.js +0 -249
  1019. package/dist/engine/webhook/signature.d.ts +0 -16
  1020. package/dist/engine/webhook/signature.js +0 -49
  1021. package/dist/storage/data-dir-discovery.d.ts +0 -31
  1022. package/dist/storage/data-dir-discovery.js +0 -140
  1023. package/dist/storage/license-store.d.ts +0 -6
  1024. package/dist/storage/license-store.js +0 -91
  1025. package/dist/storage/migrations/cwd-to-absolute.d.ts +0 -25
  1026. package/dist/storage/migrations/cwd-to-absolute.js +0 -281
  1027. package/dist/storage/session-store.d.ts +0 -20
  1028. package/dist/storage/session-store.js +0 -128
  1029. package/dist/tools/activate-license.d.ts +0 -6
  1030. package/dist/tools/activate-license.js +0 -132
  1031. package/dist/tools/checkpoint-handler.d.ts +0 -3
  1032. package/dist/tools/checkpoint-handler.js +0 -130
  1033. package/dist/tools/create-spec/adapters/prior-decisions-hint.d.ts +0 -14
  1034. package/dist/tools/create-spec/adapters/prior-decisions-hint.js +0 -30
  1035. package/dist/tools/export-session.d.ts +0 -3
  1036. package/dist/tools/export-session.js +0 -90
  1037. package/dist/tools/init-project/ancestor-data-detector.d.ts +0 -22
  1038. package/dist/tools/init-project/ancestor-data-detector.js +0 -81
  1039. package/dist/tools/license-gate.d.ts +0 -18
  1040. package/dist/tools/license-gate.js +0 -222
  1041. package/dist/tools/license-status.d.ts +0 -3
  1042. package/dist/tools/license-status.js +0 -93
  1043. package/dist/tools/list-sessions.d.ts +0 -3
  1044. package/dist/tools/list-sessions.js +0 -46
  1045. package/dist/tools/planu-session-checkpoint.d.ts +0 -6
  1046. package/dist/tools/planu-session-checkpoint.js +0 -42
  1047. package/dist/tools/restore-session.d.ts +0 -3
  1048. package/dist/tools/restore-session.js +0 -71
  1049. package/dist/tools/spec-history.d.ts +0 -3
  1050. package/dist/tools/spec-history.js +0 -59
  1051. package/dist/tools/update-status/force-done-audit.d.ts +0 -2
  1052. package/dist/tools/update-status/force-done-audit.js +0 -23
  1053. package/dist/tools/webhook.d.ts +0 -6
  1054. package/dist/tools/webhook.js +0 -150
  1055. package/dist/types/changelog.d.ts +0 -49
  1056. package/dist/types/changelog.js +0 -3
  1057. package/dist/types/licensing.d.ts +0 -109
  1058. package/dist/types/licensing.js +0 -4
  1059. package/dist/types/migration/cwd-to-absolute.d.ts +0 -8
  1060. package/dist/types/migration/cwd-to-absolute.js +0 -3
  1061. package/dist/types/product-intelligence.d.ts +0 -60
  1062. package/dist/types/product-intelligence.js +0 -3
  1063. package/dist/types/session.d.ts +0 -84
  1064. package/dist/types/session.js +0 -3
  1065. package/dist/types/webhook.d.ts +0 -62
  1066. package/dist/types/webhook.js +0 -4
@@ -0,0 +1,1110 @@
1
+ /* eslint-disable max-lines -- runtime schema, migrations and transactional operations remain co-located for auditability */
2
+ import { mkdirSync } from 'node:fs';
3
+ import { dirname, isAbsolute, resolve } from 'node:path';
4
+ import { DatabaseSync } from 'node:sqlite';
5
+ import { parseValidationReceiptPendingCheckpoint, } from '../types/durable-validation.js';
6
+ const CURRENT_SCHEMA_VERSION = 4;
7
+ const DEFAULT_BUSY_TIMEOUT_MS = 5_000;
8
+ const DEFAULT_MAX_CONNECTIONS = 4;
9
+ const openConnections = new Map();
10
+ let integrityCheckedOpens = 0;
11
+ let integrityBypassedOpens = 0;
12
+ /** Count-only process diagnostic for deterministic resource lifecycle tests. */
13
+ export function getRuntimeDatabaseDiagnosticsForTests() {
14
+ let count = 0;
15
+ for (const connections of openConnections.values()) {
16
+ count += connections;
17
+ }
18
+ return { openConnections: count, integrityCheckedOpens, integrityBypassedOpens };
19
+ }
20
+ export const DURABLE_JOB_STATES = [
21
+ 'accepted',
22
+ 'running',
23
+ 'checkpointed',
24
+ 'cancelled',
25
+ 'failed',
26
+ 'dead-letter',
27
+ 'completed',
28
+ ];
29
+ export class RuntimeDatabaseCorruptionError extends Error {
30
+ databasePath;
31
+ detail;
32
+ constructor(databasePath, detail) {
33
+ super(`[Planu] Runtime database failed integrity check: ${detail}`);
34
+ this.databasePath = databasePath;
35
+ this.detail = detail;
36
+ this.name = 'RuntimeDatabaseCorruptionError';
37
+ }
38
+ }
39
+ export class RuntimeDatabaseResourceExhaustedError extends Error {
40
+ databasePath;
41
+ maxConnections;
42
+ constructor(databasePath, maxConnections) {
43
+ super(`[Planu] Runtime database connection limit reached (${String(maxConnections)})`);
44
+ this.databasePath = databasePath;
45
+ this.maxConnections = maxConnections;
46
+ this.name = 'RuntimeDatabaseResourceExhaustedError';
47
+ }
48
+ }
49
+ function requireIdentifier(value, label) {
50
+ if (!value || value.length > 128 || !/^[A-Za-z0-9][A-Za-z0-9._:-]*$/.test(value)) {
51
+ throw new Error(`[Planu] Invalid ${label}`);
52
+ }
53
+ }
54
+ function parseJson(raw) {
55
+ if (typeof raw !== 'string') {
56
+ throw new Error('[Planu] Runtime database contains invalid JSON');
57
+ }
58
+ return JSON.parse(raw);
59
+ }
60
+ function stringifyJson(value) {
61
+ const serialized = JSON.stringify(value);
62
+ if (serialized === undefined) {
63
+ throw new Error('[Planu] Runtime value is not JSON serializable');
64
+ }
65
+ return serialized;
66
+ }
67
+ /** A bounded (one connection), transactional SQLite runtime store. */
68
+ export class RuntimeDatabase {
69
+ path;
70
+ schemaVersion = CURRENT_SCHEMA_VERSION;
71
+ database;
72
+ connectionKey;
73
+ closed = false;
74
+ inTransaction = false;
75
+ // eslint-disable-next-line complexity -- constructor owns fail-safe acquisition and rollback
76
+ constructor(options) {
77
+ if (!options.path.trim()) {
78
+ throw new Error('[Planu] Runtime database path is required');
79
+ }
80
+ const busyTimeoutMs = options.busyTimeoutMs ?? DEFAULT_BUSY_TIMEOUT_MS;
81
+ if (!Number.isSafeInteger(busyTimeoutMs) || busyTimeoutMs < 0 || busyTimeoutMs > 60_000) {
82
+ throw new Error('[Planu] busyTimeoutMs must be an integer between 0 and 60000');
83
+ }
84
+ if (options.path !== ':memory:' && !isAbsolute(options.path)) {
85
+ throw new Error('[Planu] Runtime database path must be absolute');
86
+ }
87
+ const maxConnections = options.maxConnections ?? DEFAULT_MAX_CONNECTIONS;
88
+ if (!Number.isSafeInteger(maxConnections) || maxConnections < 1 || maxConnections > 32) {
89
+ throw new Error('[Planu] maxConnections must be an integer between 1 and 32');
90
+ }
91
+ this.path = options.path === ':memory:' ? options.path : resolve(options.path);
92
+ this.connectionKey =
93
+ this.path === ':memory:' ? `${this.path}:${randomConnectionKey()}` : this.path;
94
+ const currentConnections = openConnections.get(this.connectionKey) ?? 0;
95
+ if (currentConnections >= maxConnections) {
96
+ throw new RuntimeDatabaseResourceExhaustedError(this.path, maxConnections);
97
+ }
98
+ openConnections.set(this.connectionKey, currentConnections + 1);
99
+ let database;
100
+ try {
101
+ if (this.path !== ':memory:') {
102
+ mkdirSync(dirname(this.path), { recursive: true, mode: 0o700 });
103
+ }
104
+ database = new DatabaseSync(this.path, {
105
+ timeout: busyTimeoutMs,
106
+ enableForeignKeyConstraints: true,
107
+ enableDoubleQuotedStringLiterals: false,
108
+ allowExtension: false,
109
+ });
110
+ this.database = database;
111
+ this.database.exec('PRAGMA journal_mode = WAL; PRAGMA synchronous = FULL;');
112
+ this.migrate();
113
+ if (options.checkIntegrity !== false) {
114
+ this.assertIntegrity();
115
+ integrityCheckedOpens += 1;
116
+ }
117
+ else {
118
+ integrityBypassedOpens += 1;
119
+ }
120
+ }
121
+ catch (error) {
122
+ database?.close();
123
+ this.releaseConnection();
124
+ if (error instanceof Error && /malformed|not a database|disk image/i.test(error.message)) {
125
+ throw new RuntimeDatabaseCorruptionError(this.path, error.message);
126
+ }
127
+ throw error;
128
+ }
129
+ }
130
+ releaseConnection() {
131
+ const count = openConnections.get(this.connectionKey) ?? 0;
132
+ if (count <= 1) {
133
+ openConnections.delete(this.connectionKey);
134
+ }
135
+ else {
136
+ openConnections.set(this.connectionKey, count - 1);
137
+ }
138
+ }
139
+ assertOpen() {
140
+ if (this.closed) {
141
+ throw new Error('[Planu] Runtime database is closed');
142
+ }
143
+ }
144
+ // eslint-disable-next-line max-lines-per-function -- versioned DDL is intentionally auditable in one transaction
145
+ migrate() {
146
+ const row = this.database.prepare('PRAGMA user_version').get();
147
+ if (row.user_version > CURRENT_SCHEMA_VERSION) {
148
+ throw new Error(`[Planu] Runtime schema ${String(row.user_version)} is newer than supported`);
149
+ }
150
+ if (row.user_version === 0) {
151
+ this.database.exec(`
152
+ BEGIN IMMEDIATE;
153
+ CREATE TABLE runtime_records (
154
+ project_id TEXT NOT NULL,
155
+ workspace_id TEXT NOT NULL,
156
+ kind TEXT NOT NULL CHECK (kind IN ('mutation', 'index', 'audit-state')),
157
+ record_key TEXT NOT NULL,
158
+ value_json TEXT NOT NULL,
159
+ source_digest TEXT,
160
+ updated_at TEXT NOT NULL,
161
+ PRIMARY KEY (project_id, workspace_id, kind, record_key)
162
+ ) STRICT;
163
+ CREATE TABLE jobs (
164
+ id TEXT NOT NULL,
165
+ project_id TEXT NOT NULL,
166
+ workspace_id TEXT NOT NULL,
167
+ state TEXT NOT NULL CHECK (state IN ('accepted', 'running', 'checkpointed', 'cancelled', 'failed', 'dead-letter', 'completed')),
168
+ payload_json TEXT NOT NULL,
169
+ checkpoint_json TEXT,
170
+ result_json TEXT,
171
+ error_message TEXT,
172
+ attempts INTEGER NOT NULL DEFAULT 0 CHECK (attempts >= 0),
173
+ max_attempts INTEGER NOT NULL DEFAULT 3 CHECK (max_attempts >= 1),
174
+ cancel_requested INTEGER NOT NULL DEFAULT 0 CHECK (cancel_requested IN (0, 1)),
175
+ lease_owner TEXT,
176
+ lease_expires_at TEXT,
177
+ fencing_token INTEGER NOT NULL DEFAULT 0 CHECK (fencing_token >= 0),
178
+ created_at TEXT NOT NULL,
179
+ updated_at TEXT NOT NULL,
180
+ PRIMARY KEY (project_id, workspace_id, id)
181
+ ) STRICT;
182
+ CREATE TABLE outbox (
183
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
184
+ project_id TEXT NOT NULL,
185
+ workspace_id TEXT NOT NULL,
186
+ topic TEXT NOT NULL,
187
+ payload_json TEXT NOT NULL,
188
+ created_at TEXT NOT NULL,
189
+ delivered_at TEXT
190
+ ) STRICT;
191
+ CREATE TABLE audit_log (
192
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
193
+ project_id TEXT NOT NULL,
194
+ workspace_id TEXT NOT NULL,
195
+ event_type TEXT NOT NULL,
196
+ payload_json TEXT NOT NULL,
197
+ created_at TEXT NOT NULL
198
+ ) STRICT;
199
+ CREATE INDEX jobs_project_state ON jobs(project_id, workspace_id, state);
200
+ CREATE INDEX jobs_lease_expiry ON jobs(state, lease_expires_at);
201
+ CREATE INDEX outbox_pending ON outbox(project_id, workspace_id, delivered_at, id);
202
+ CREATE INDEX audit_project_time ON audit_log(project_id, workspace_id, created_at);
203
+ PRAGMA user_version = 4;
204
+ COMMIT;
205
+ `);
206
+ }
207
+ if (row.user_version === 1) {
208
+ this.database.exec(`
209
+ BEGIN IMMEDIATE;
210
+ CREATE TABLE jobs_v2 (
211
+ id TEXT NOT NULL,
212
+ project_id TEXT NOT NULL,
213
+ workspace_id TEXT NOT NULL,
214
+ state TEXT NOT NULL CHECK (state IN ('pending', 'running', 'completed', 'failed', 'cancelled')),
215
+ payload_json TEXT NOT NULL,
216
+ created_at TEXT NOT NULL,
217
+ updated_at TEXT NOT NULL,
218
+ PRIMARY KEY (project_id, workspace_id, id)
219
+ ) STRICT;
220
+ INSERT INTO jobs_v2 SELECT id, project_id, workspace_id, state, payload_json, created_at, updated_at FROM jobs;
221
+ DROP TABLE jobs;
222
+ ALTER TABLE jobs_v2 RENAME TO jobs;
223
+ CREATE TABLE outbox_v2 (
224
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
225
+ project_id TEXT NOT NULL,
226
+ workspace_id TEXT NOT NULL,
227
+ topic TEXT NOT NULL,
228
+ payload_json TEXT NOT NULL,
229
+ created_at TEXT NOT NULL,
230
+ delivered_at TEXT
231
+ ) STRICT;
232
+ INSERT INTO outbox_v2 (id, project_id, workspace_id, topic, payload_json, created_at, delivered_at)
233
+ SELECT id, '__legacy__', 'global', topic, payload_json, created_at, delivered_at FROM outbox;
234
+ DROP TABLE outbox;
235
+ ALTER TABLE outbox_v2 RENAME TO outbox;
236
+ CREATE INDEX jobs_project_state ON jobs(project_id, workspace_id, state);
237
+ CREATE INDEX outbox_pending ON outbox(project_id, workspace_id, delivered_at, id);
238
+ PRAGMA user_version = 2;
239
+ COMMIT;
240
+ `);
241
+ }
242
+ const migrated = this.database.prepare('PRAGMA user_version').get();
243
+ if (migrated.user_version === 2) {
244
+ this.database.exec(`
245
+ BEGIN IMMEDIATE;
246
+ CREATE TABLE jobs_v3 (
247
+ id TEXT NOT NULL,
248
+ project_id TEXT NOT NULL,
249
+ workspace_id TEXT NOT NULL,
250
+ state TEXT NOT NULL CHECK (state IN ('accepted', 'running', 'checkpointed', 'cancelled', 'failed', 'dead-letter', 'completed')),
251
+ payload_json TEXT NOT NULL,
252
+ checkpoint_json TEXT,
253
+ result_json TEXT,
254
+ error_message TEXT,
255
+ attempts INTEGER NOT NULL DEFAULT 0 CHECK (attempts >= 0),
256
+ max_attempts INTEGER NOT NULL DEFAULT 3 CHECK (max_attempts >= 1),
257
+ cancel_requested INTEGER NOT NULL DEFAULT 0 CHECK (cancel_requested IN (0, 1)),
258
+ lease_owner TEXT,
259
+ lease_expires_at TEXT,
260
+ created_at TEXT NOT NULL,
261
+ updated_at TEXT NOT NULL,
262
+ PRIMARY KEY (project_id, workspace_id, id)
263
+ ) STRICT;
264
+ INSERT INTO jobs_v3
265
+ (id, project_id, workspace_id, state, payload_json, created_at, updated_at)
266
+ SELECT id, project_id, workspace_id,
267
+ CASE state
268
+ WHEN 'pending' THEN 'accepted'
269
+ WHEN 'running' THEN 'checkpointed'
270
+ ELSE state
271
+ END,
272
+ payload_json, created_at, updated_at
273
+ FROM jobs;
274
+ DROP TABLE jobs;
275
+ ALTER TABLE jobs_v3 RENAME TO jobs;
276
+ CREATE INDEX jobs_project_state ON jobs(project_id, workspace_id, state);
277
+ CREATE INDEX jobs_lease_expiry ON jobs(state, lease_expires_at);
278
+ PRAGMA user_version = 3;
279
+ COMMIT;
280
+ `);
281
+ }
282
+ const current = this.database.prepare('PRAGMA user_version').get();
283
+ if (current.user_version === 3) {
284
+ this.database.exec(`
285
+ BEGIN IMMEDIATE;
286
+ ALTER TABLE jobs ADD COLUMN fencing_token INTEGER NOT NULL DEFAULT 0 CHECK (fencing_token >= 0);
287
+ UPDATE jobs SET
288
+ state = CASE
289
+ WHEN cancel_requested = 1 THEN 'cancelled'
290
+ WHEN attempts >= max_attempts THEN 'dead-letter'
291
+ ELSE 'checkpointed'
292
+ END,
293
+ error_message = CASE
294
+ WHEN attempts >= max_attempts THEN 'Lease expired after maximum attempts'
295
+ ELSE error_message
296
+ END,
297
+ lease_owner = NULL,
298
+ lease_expires_at = NULL
299
+ WHERE state = 'running';
300
+ PRAGMA user_version = 4;
301
+ COMMIT;
302
+ `);
303
+ }
304
+ }
305
+ assertIntegrity() {
306
+ this.assertOpen();
307
+ const rows = this.database.prepare('PRAGMA quick_check').all();
308
+ const failures = rows.map((row) => row.quick_check).filter((value) => value !== 'ok');
309
+ if (failures.length > 0) {
310
+ throw new RuntimeDatabaseCorruptionError(this.path, failures.join('; '));
311
+ }
312
+ }
313
+ journalMode() {
314
+ this.assertOpen();
315
+ const row = this.database.prepare('PRAGMA journal_mode').get();
316
+ return row.journal_mode;
317
+ }
318
+ transaction(operation) {
319
+ this.assertOpen();
320
+ if (this.inTransaction) {
321
+ throw new Error('[Planu] Nested runtime transactions are not supported');
322
+ }
323
+ this.database.exec('BEGIN IMMEDIATE');
324
+ this.inTransaction = true;
325
+ try {
326
+ const result = operation();
327
+ this.database.exec('COMMIT');
328
+ return result;
329
+ }
330
+ catch (error) {
331
+ this.database.exec('ROLLBACK');
332
+ throw error;
333
+ }
334
+ finally {
335
+ this.inTransaction = false;
336
+ }
337
+ }
338
+ /** Run a consistent read-only snapshot without acquiring an immediate writer lock. */
339
+ snapshot(operation) {
340
+ this.assertOpen();
341
+ if (this.inTransaction) {
342
+ throw new Error('[Planu] Nested runtime transactions are not supported');
343
+ }
344
+ this.database.exec('BEGIN');
345
+ this.inTransaction = true;
346
+ try {
347
+ const result = operation();
348
+ this.database.exec('COMMIT');
349
+ return result;
350
+ }
351
+ catch (error) {
352
+ this.database.exec('ROLLBACK');
353
+ throw error;
354
+ }
355
+ finally {
356
+ this.inTransaction = false;
357
+ }
358
+ }
359
+ putRecord(record) {
360
+ this.assertOpen();
361
+ requireIdentifier(record.projectId, 'projectId');
362
+ requireIdentifier(record.workspaceId, 'workspaceId');
363
+ requireIdentifier(record.key, 'record key');
364
+ const valueJson = stringifyJson(record.value);
365
+ this.database
366
+ .prepare(`
367
+ INSERT INTO runtime_records
368
+ (project_id, workspace_id, kind, record_key, value_json, source_digest, updated_at)
369
+ VALUES (?, ?, ?, ?, ?, ?, ?)
370
+ ON CONFLICT(project_id, workspace_id, kind, record_key) DO UPDATE SET
371
+ value_json = excluded.value_json,
372
+ source_digest = excluded.source_digest,
373
+ updated_at = excluded.updated_at
374
+ WHERE excluded.updated_at >= runtime_records.updated_at
375
+ `)
376
+ .run(record.projectId, record.workspaceId, record.kind, record.key, valueJson, record.sourceDigest ?? null, record.updatedAt ?? new Date().toISOString());
377
+ }
378
+ getRecord(projectId, workspaceId, kind, key) {
379
+ this.assertOpen();
380
+ requireIdentifier(projectId, 'projectId');
381
+ requireIdentifier(workspaceId, 'workspaceId');
382
+ requireIdentifier(key, 'record key');
383
+ const row = this.database
384
+ .prepare(`
385
+ SELECT project_id, workspace_id, kind, record_key, value_json, source_digest, updated_at
386
+ FROM runtime_records
387
+ WHERE project_id = ? AND workspace_id = ? AND kind = ? AND record_key = ?
388
+ `)
389
+ .get(projectId, workspaceId, kind, key);
390
+ return row ? mapRuntimeRecordRow(row) : undefined;
391
+ }
392
+ listRecords(projectId, workspaceId, kind) {
393
+ this.assertOpen();
394
+ requireIdentifier(projectId, 'projectId');
395
+ requireIdentifier(workspaceId, 'workspaceId');
396
+ const rows = (kind
397
+ ? this.database
398
+ .prepare(`SELECT project_id, workspace_id, kind, record_key, value_json, source_digest, updated_at
399
+ FROM runtime_records
400
+ WHERE project_id = ? AND workspace_id = ? AND kind = ?
401
+ ORDER BY record_key`)
402
+ .all(projectId, workspaceId, kind)
403
+ : this.database
404
+ .prepare(`SELECT project_id, workspace_id, kind, record_key, value_json, source_digest, updated_at
405
+ FROM runtime_records
406
+ WHERE project_id = ? AND workspace_id = ?
407
+ ORDER BY kind, record_key`)
408
+ .all(projectId, workspaceId));
409
+ return rows.map(mapRuntimeRecordRow);
410
+ }
411
+ enqueueJob(input) {
412
+ this.assertOpen();
413
+ requireIdentifier(input.id, 'job id');
414
+ requireIdentifier(input.projectId, 'projectId');
415
+ requireIdentifier(input.workspaceId, 'workspaceId');
416
+ const maxAttempts = input.maxAttempts ?? 3;
417
+ if (!Number.isSafeInteger(maxAttempts) || maxAttempts < 1 || maxAttempts > 100) {
418
+ throw new Error('[Planu] maxAttempts must be an integer between 1 and 100');
419
+ }
420
+ const now = new Date().toISOString();
421
+ this.database
422
+ .prepare(`
423
+ INSERT INTO jobs
424
+ (id, project_id, workspace_id, state, payload_json, max_attempts, created_at, updated_at)
425
+ VALUES (?, ?, ?, 'accepted', ?, ?, ?, ?)
426
+ `)
427
+ .run(input.id, input.projectId, input.workspaceId, stringifyJson(input.payload), maxAttempts, now, now);
428
+ }
429
+ getJob(projectId, workspaceId, id) {
430
+ this.assertOpen();
431
+ requireIdentifier(projectId, 'projectId');
432
+ requireIdentifier(workspaceId, 'workspaceId');
433
+ requireIdentifier(id, 'job id');
434
+ const row = this.database
435
+ .prepare(`SELECT * FROM jobs WHERE project_id = ? AND workspace_id = ? AND id = ?`)
436
+ .get(projectId, workspaceId, id);
437
+ return row ? mapJobRow(row) : undefined;
438
+ }
439
+ listJobs(projectId, workspaceId) {
440
+ this.assertOpen();
441
+ requireIdentifier(projectId, 'projectId');
442
+ requireIdentifier(workspaceId, 'workspaceId');
443
+ const rows = this.database
444
+ .prepare(`SELECT * FROM jobs WHERE project_id = ? AND workspace_id = ? ORDER BY created_at, id`)
445
+ .all(projectId, workspaceId);
446
+ return rows.map(mapJobRow);
447
+ }
448
+ listRunnableJobScopes() {
449
+ this.assertOpen();
450
+ return this.database
451
+ .prepare(`SELECT DISTINCT project_id AS projectId, workspace_id AS workspaceId
452
+ FROM jobs WHERE state IN ('accepted', 'checkpointed', 'running')
453
+ ORDER BY project_id, workspace_id`)
454
+ .all();
455
+ }
456
+ claimJob(input) {
457
+ this.assertOpen();
458
+ validateLeaseInput(input);
459
+ const now = input.now ?? new Date().toISOString();
460
+ const expiresAt = new Date(Date.parse(now) + input.leaseMs).toISOString();
461
+ return this.transaction(() => {
462
+ this.recoverExpiredJobs(now, input.projectId, input.workspaceId);
463
+ const result = this.database
464
+ .prepare(`UPDATE jobs
465
+ SET state = 'running', attempts = attempts + 1, fencing_token = fencing_token + 1, lease_owner = ?,
466
+ lease_expires_at = ?, updated_at = ?
467
+ WHERE project_id = ? AND workspace_id = ? AND id = ?
468
+ AND state IN ('accepted', 'checkpointed') AND cancel_requested = 0
469
+ AND attempts < max_attempts`)
470
+ .run(input.workerId, expiresAt, now, input.projectId, input.workspaceId, input.id);
471
+ return result.changes === 1
472
+ ? this.getJob(input.projectId, input.workspaceId, input.id)
473
+ : undefined;
474
+ });
475
+ }
476
+ renewJobLease(input) {
477
+ this.assertOpen();
478
+ validateLeaseInput(input);
479
+ const now = input.now ?? new Date().toISOString();
480
+ const expiresAt = new Date(Date.parse(now) + input.leaseMs).toISOString();
481
+ const result = this.database
482
+ .prepare(`UPDATE jobs
483
+ SET lease_expires_at = CASE WHEN lease_expires_at > ? THEN lease_expires_at ELSE ? END,
484
+ updated_at = ?
485
+ WHERE project_id = ? AND workspace_id = ? AND id = ?
486
+ AND state = 'running' AND lease_owner = ? AND fencing_token = ? AND cancel_requested = 0
487
+ AND lease_expires_at > ?`)
488
+ .run(expiresAt, expiresAt, now, input.projectId, input.workspaceId, input.id, input.workerId, requireFencingToken(input), now);
489
+ return result.changes === 1;
490
+ }
491
+ recordJobProgress(input) {
492
+ this.assertOpen();
493
+ validateLeaseInput(input);
494
+ const now = input.now ?? new Date().toISOString();
495
+ const expiresAt = new Date(Date.parse(now) + input.leaseMs).toISOString();
496
+ const result = this.database
497
+ .prepare(`UPDATE jobs
498
+ SET checkpoint_json = ?,
499
+ lease_expires_at = CASE WHEN lease_expires_at > ? THEN lease_expires_at ELSE ? END,
500
+ updated_at = ?
501
+ WHERE project_id = ? AND workspace_id = ? AND id = ?
502
+ AND state = 'running' AND lease_owner = ? AND fencing_token = ? AND cancel_requested = 0
503
+ AND lease_expires_at > ?`)
504
+ .run(stringifyJson(input.checkpoint), expiresAt, expiresAt, now, input.projectId, input.workspaceId, input.id, input.workerId, requireFencingToken(input), now);
505
+ if (result.changes !== 1) {
506
+ this.requireLeasedJob(input);
507
+ throw new Error('[Planu] Job lease was lost before checkpoint');
508
+ }
509
+ return requireJobRecord(this.getJob(input.projectId, input.workspaceId, input.id), input.id);
510
+ }
511
+ assertActiveJobLease(input) {
512
+ this.assertOpen();
513
+ this.requireLeasedJob(input);
514
+ }
515
+ checkpointJob(input) {
516
+ return this.finishLeasedUpdate(input, 'checkpointed', {
517
+ checkpointJson: stringifyJson(input.checkpoint),
518
+ });
519
+ }
520
+ completeJob(input) {
521
+ return this.finishLeasedUpdate(input, 'completed', {
522
+ clearCheckpoint: true,
523
+ resultJson: stringifyJson(input.result),
524
+ });
525
+ }
526
+ failJob(input) {
527
+ if (!input.error.trim() || input.error.length > 4_096) {
528
+ throw new Error('[Planu] job error must contain between 1 and 4096 characters');
529
+ }
530
+ const current = this.requireLeasedJob(input);
531
+ const state = current.attempts >= current.maxAttempts ? 'dead-letter' : 'failed';
532
+ return this.finishLeasedUpdate(input, state, { errorMessage: input.error });
533
+ }
534
+ retryJob(projectId, workspaceId, id) {
535
+ this.assertOpen();
536
+ requireIdentifier(projectId, 'projectId');
537
+ requireIdentifier(workspaceId, 'workspaceId');
538
+ requireIdentifier(id, 'job id');
539
+ const now = new Date().toISOString();
540
+ const result = this.database
541
+ .prepare(`UPDATE jobs SET state = 'accepted', error_message = NULL, updated_at = ?
542
+ WHERE project_id = ? AND workspace_id = ? AND id = ?
543
+ AND state = 'failed' AND cancel_requested = 0 AND attempts < max_attempts`)
544
+ .run(now, projectId, workspaceId, id);
545
+ if (result.changes !== 1) {
546
+ throw new Error('[Planu] Job is not retryable');
547
+ }
548
+ return requireJobRecord(this.getJob(projectId, workspaceId, id), id);
549
+ }
550
+ restartJob(projectId, workspaceId, id) {
551
+ this.assertOpen();
552
+ requireIdentifier(projectId, 'projectId');
553
+ requireIdentifier(workspaceId, 'workspaceId');
554
+ requireIdentifier(id, 'job id');
555
+ const now = new Date().toISOString();
556
+ this.transaction(() => {
557
+ const current = this.getJob(projectId, workspaceId, id);
558
+ if (!current ||
559
+ !['accepted', 'checkpointed', 'failed', 'dead-letter', 'cancelled', 'completed'].includes(current.state)) {
560
+ throw new Error('[Planu] Job is not restartable');
561
+ }
562
+ this.archiveCheckpointBeforeRestart(projectId, workspaceId, id, now);
563
+ const result = this.database
564
+ .prepare(`UPDATE jobs SET state = 'accepted', attempts = 0, cancel_requested = 0,
565
+ checkpoint_json = NULL, result_json = NULL, error_message = NULL,
566
+ lease_owner = NULL, lease_expires_at = NULL, updated_at = ?
567
+ WHERE project_id = ? AND workspace_id = ? AND id = ?
568
+ AND state IN ('accepted', 'checkpointed', 'failed', 'dead-letter', 'cancelled', 'completed')`)
569
+ .run(now, projectId, workspaceId, id);
570
+ if (result.changes !== 1) {
571
+ throw new Error('[Planu] Job is not restartable');
572
+ }
573
+ });
574
+ return requireJobRecord(this.getJob(projectId, workspaceId, id), id);
575
+ }
576
+ restartReceiptPublication(projectId, workspaceId, id, limits) {
577
+ this.assertOpen();
578
+ requireIdentifier(projectId, 'projectId');
579
+ requireIdentifier(workspaceId, 'workspaceId');
580
+ requireIdentifier(id, 'job id');
581
+ const now = new Date().toISOString();
582
+ this.transaction(() => {
583
+ const current = this.getJob(projectId, workspaceId, id);
584
+ if (!current ||
585
+ !['failed', 'dead-letter'].includes(current.state) ||
586
+ current.cancelRequested ||
587
+ !parseValidationReceiptPendingCheckpoint(current.checkpoint, limits)) {
588
+ throw new Error('[Planu] Job receipt publication is not restartable');
589
+ }
590
+ const changed = this.database
591
+ .prepare(`UPDATE jobs SET state = 'accepted', attempts = 0, cancel_requested = 0,
592
+ result_json = NULL, error_message = NULL, lease_owner = NULL,
593
+ lease_expires_at = NULL, updated_at = ?
594
+ WHERE project_id = ? AND workspace_id = ? AND id = ?
595
+ AND state IN ('failed', 'dead-letter') AND cancel_requested = 0`)
596
+ .run(now, projectId, workspaceId, id);
597
+ if (changed.changes !== 1) {
598
+ throw new Error('[Planu] Job receipt publication is not restartable');
599
+ }
600
+ });
601
+ return requireJobRecord(this.getJob(projectId, workspaceId, id), id);
602
+ }
603
+ restartJobWithPayload(projectId, workspaceId, id, payload) {
604
+ this.assertOpen();
605
+ requireIdentifier(projectId, 'projectId');
606
+ requireIdentifier(workspaceId, 'workspaceId');
607
+ requireIdentifier(id, 'job id');
608
+ const now = new Date().toISOString();
609
+ this.transaction(() => {
610
+ const current = this.getJob(projectId, workspaceId, id);
611
+ if (!current ||
612
+ !['failed', 'dead-letter', 'cancelled', 'completed'].includes(current.state)) {
613
+ throw new Error('[Planu] Job payload is not replaceable while work is active');
614
+ }
615
+ this.archiveCheckpointBeforeRestart(projectId, workspaceId, id, now);
616
+ const result = this.database
617
+ .prepare(`UPDATE jobs SET state = 'accepted', attempts = 0, cancel_requested = 0,
618
+ payload_json = ?, checkpoint_json = NULL, result_json = NULL, error_message = NULL,
619
+ lease_owner = NULL, lease_expires_at = NULL, updated_at = ?
620
+ WHERE project_id = ? AND workspace_id = ? AND id = ?
621
+ AND state IN ('failed', 'dead-letter', 'cancelled', 'completed')`)
622
+ .run(stringifyJson(payload), now, projectId, workspaceId, id);
623
+ if (result.changes !== 1) {
624
+ throw new Error('[Planu] Job payload is not replaceable while work is active');
625
+ }
626
+ });
627
+ return requireJobRecord(this.getJob(projectId, workspaceId, id), id);
628
+ }
629
+ cancelJob(projectId, workspaceId, id) {
630
+ this.assertOpen();
631
+ requireIdentifier(projectId, 'projectId');
632
+ requireIdentifier(workspaceId, 'workspaceId');
633
+ requireIdentifier(id, 'job id');
634
+ const current = this.getJob(projectId, workspaceId, id);
635
+ if (!current) {
636
+ throw new Error(`[Planu] Job ${id} was not found`);
637
+ }
638
+ if (current.state === 'completed' ||
639
+ current.state === 'cancelled' ||
640
+ current.state === 'dead-letter') {
641
+ return current;
642
+ }
643
+ const now = new Date().toISOString();
644
+ this.database
645
+ .prepare(`UPDATE jobs SET state = 'cancelled', cancel_requested = 1,
646
+ lease_owner = NULL, lease_expires_at = NULL, updated_at = ?
647
+ WHERE project_id = ? AND workspace_id = ? AND id = ?`)
648
+ .run(now, projectId, workspaceId, id);
649
+ return requireJobRecord(this.getJob(projectId, workspaceId, id), id);
650
+ }
651
+ archiveCheckpointBeforeRestart(projectId, workspaceId, id, restartedAt) {
652
+ const current = this.getJob(projectId, workspaceId, id);
653
+ if (current?.checkpoint === undefined) {
654
+ return;
655
+ }
656
+ this.putRecord({
657
+ projectId,
658
+ workspaceId,
659
+ kind: 'audit-state',
660
+ key: `job-attempt:${id.slice(0, 64)}:${process.hrtime.bigint().toString()}`,
661
+ value: {
662
+ operationId: id,
663
+ attempts: current.attempts,
664
+ previousState: current.state,
665
+ checkpoint: current.checkpoint,
666
+ restartedAt,
667
+ },
668
+ });
669
+ }
670
+ recoverExpiredJobs(now = new Date().toISOString(), projectId, workspaceId) {
671
+ this.assertOpen();
672
+ const scope = projectId && workspaceId ? ' AND project_id = ? AND workspace_id = ?' : '';
673
+ if ((projectId && !workspaceId) || (!projectId && workspaceId)) {
674
+ throw new Error('[Planu] projectId and workspaceId must be provided together');
675
+ }
676
+ if (projectId && workspaceId) {
677
+ requireIdentifier(projectId, 'projectId');
678
+ requireIdentifier(workspaceId, 'workspaceId');
679
+ }
680
+ const statement = this.database.prepare(`UPDATE jobs
681
+ SET state = CASE
682
+ WHEN cancel_requested = 1 THEN 'cancelled'
683
+ WHEN attempts >= max_attempts THEN 'dead-letter'
684
+ ELSE 'checkpointed'
685
+ END,
686
+ error_message = CASE WHEN attempts >= max_attempts THEN 'Lease expired after maximum attempts' ELSE error_message END,
687
+ lease_owner = NULL, lease_expires_at = NULL, updated_at = ?
688
+ WHERE state = 'running' AND lease_expires_at <= ?${scope}`);
689
+ const result = projectId && workspaceId
690
+ ? statement.run(now, now, projectId, workspaceId)
691
+ : statement.run(now, now);
692
+ return Number(result.changes);
693
+ }
694
+ requireLeasedJob(input) {
695
+ validateLeaseInput(input);
696
+ const current = this.getJob(input.projectId, input.workspaceId, input.id);
697
+ if (current?.state !== 'running' ||
698
+ current.leaseOwner !== input.workerId ||
699
+ current.fencingToken !== requireFencingToken(input) ||
700
+ current.cancelRequested) {
701
+ throw new Error('[Planu] Job lease is stale or not owned by this worker');
702
+ }
703
+ const now = input.now ?? new Date().toISOString();
704
+ if (!current.leaseExpiresAt || current.leaseExpiresAt <= now) {
705
+ throw new Error('[Planu] Job lease has expired');
706
+ }
707
+ return current;
708
+ }
709
+ finishLeasedUpdate(input, state, values) {
710
+ this.requireLeasedJob(input);
711
+ const now = input.now ?? new Date().toISOString();
712
+ const result = this.database
713
+ .prepare(`UPDATE jobs SET state = ?, checkpoint_json = CASE WHEN ? = 1 THEN NULL ELSE COALESCE(?, checkpoint_json) END,
714
+ result_json = COALESCE(?, result_json), error_message = ?,
715
+ lease_owner = NULL, lease_expires_at = NULL, updated_at = ?
716
+ WHERE project_id = ? AND workspace_id = ? AND id = ?
717
+ AND state = 'running' AND lease_owner = ? AND fencing_token = ?
718
+ AND lease_expires_at > ? AND cancel_requested = 0`)
719
+ .run(state, values.clearCheckpoint === true ? 1 : 0, values.checkpointJson ?? null, values.resultJson ?? null, values.errorMessage ?? null, now, input.projectId, input.workspaceId, input.id, input.workerId, requireFencingToken(input), now);
720
+ if (result.changes !== 1) {
721
+ throw new Error('[Planu] Job lease was lost before commit');
722
+ }
723
+ return requireJobRecord(this.getJob(input.projectId, input.workspaceId, input.id), input.id);
724
+ }
725
+ enqueueOutbox(input) {
726
+ this.assertOpen();
727
+ requireIdentifier(input.projectId, 'projectId');
728
+ requireIdentifier(input.workspaceId, 'workspaceId');
729
+ requireIdentifier(input.topic, 'outbox topic');
730
+ const result = this.database
731
+ .prepare('INSERT INTO outbox (project_id, workspace_id, topic, payload_json, created_at) VALUES (?, ?, ?, ?, ?)')
732
+ .run(input.projectId, input.workspaceId, input.topic, stringifyJson(input.payload), new Date().toISOString());
733
+ return Number(result.lastInsertRowid);
734
+ }
735
+ listOutbox(projectId, workspaceId, options = {}) {
736
+ this.assertOpen();
737
+ requireIdentifier(projectId, 'projectId');
738
+ requireIdentifier(workspaceId, 'workspaceId');
739
+ const limit = options.limit ?? 100;
740
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > 1_000) {
741
+ throw new Error('[Planu] outbox limit must be an integer between 1 and 1000');
742
+ }
743
+ const pendingClause = options.pendingOnly === false ? '' : ' AND delivered_at IS NULL';
744
+ const topics = options.topics ?? [];
745
+ for (const topic of topics) {
746
+ requireIdentifier(topic, 'outbox topic');
747
+ }
748
+ const topicsClause = topics.length > 0 ? ` AND topic IN (${topics.map(() => '?').join(', ')})` : '';
749
+ const rows = this.database
750
+ .prepare(`SELECT id, project_id, workspace_id, topic, payload_json, created_at, delivered_at
751
+ FROM outbox
752
+ WHERE project_id = ? AND workspace_id = ?${pendingClause}${topicsClause}
753
+ ORDER BY id LIMIT ?`)
754
+ .all(projectId, workspaceId, ...topics, limit);
755
+ return rows.map(mapOutboxRow);
756
+ }
757
+ listPendingOutboxScopes() {
758
+ this.assertOpen();
759
+ return this.database
760
+ .prepare(`SELECT DISTINCT project_id AS projectId, workspace_id AS workspaceId
761
+ FROM outbox WHERE delivered_at IS NULL ORDER BY project_id, workspace_id`)
762
+ .all();
763
+ }
764
+ markOutboxDelivered(projectId, workspaceId, id, deliveredAt = new Date().toISOString()) {
765
+ this.assertOpen();
766
+ requireIdentifier(projectId, 'projectId');
767
+ requireIdentifier(workspaceId, 'workspaceId');
768
+ if (!Number.isSafeInteger(id) || id < 1) {
769
+ throw new Error('[Planu] outbox id must be a positive integer');
770
+ }
771
+ if (!Number.isFinite(Date.parse(deliveredAt))) {
772
+ throw new Error('[Planu] deliveredAt must be a valid ISO date');
773
+ }
774
+ const result = this.database
775
+ .prepare(`UPDATE outbox SET delivered_at = ?
776
+ WHERE id = ? AND project_id = ? AND workspace_id = ? AND delivered_at IS NULL`)
777
+ .run(deliveredAt, id, projectId, workspaceId);
778
+ return result.changes === 1;
779
+ }
780
+ appendAudit(input) {
781
+ this.assertOpen();
782
+ requireIdentifier(input.projectId, 'projectId');
783
+ requireIdentifier(input.workspaceId, 'workspaceId');
784
+ requireIdentifier(input.eventType, 'event type');
785
+ const result = this.database
786
+ .prepare(`
787
+ INSERT INTO audit_log (project_id, workspace_id, event_type, payload_json, created_at)
788
+ VALUES (?, ?, ?, ?, ?)
789
+ `)
790
+ .run(input.projectId, input.workspaceId, input.eventType, stringifyJson(input.payload), new Date().toISOString());
791
+ return Number(result.lastInsertRowid);
792
+ }
793
+ listAudit(projectId, workspaceId, options = {}) {
794
+ this.assertOpen();
795
+ requireIdentifier(projectId, 'projectId');
796
+ requireIdentifier(workspaceId, 'workspaceId');
797
+ const afterId = options.afterId ?? 0;
798
+ const limit = options.limit ?? 100;
799
+ if (!Number.isSafeInteger(afterId) || afterId < 0) {
800
+ throw new Error('[Planu] audit afterId must be a non-negative integer');
801
+ }
802
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > 1_000) {
803
+ throw new Error('[Planu] audit limit must be an integer between 1 and 1000');
804
+ }
805
+ const rows = this.database
806
+ .prepare(`SELECT id, project_id, workspace_id, event_type, payload_json, created_at
807
+ FROM audit_log
808
+ WHERE project_id = ? AND workspace_id = ? AND id > ?
809
+ ORDER BY id LIMIT ?`)
810
+ .all(projectId, workspaceId, afterId, limit);
811
+ return rows.map(mapAuditRow);
812
+ }
813
+ /** Recover every authoritative mutable family for one isolated workspace. */
814
+ recoverWorkspace(projectId, workspaceId) {
815
+ this.assertOpen();
816
+ requireIdentifier(projectId, 'projectId');
817
+ requireIdentifier(workspaceId, 'workspaceId');
818
+ this.recoverExpiredJobs(new Date().toISOString(), projectId, workspaceId);
819
+ return this.snapshot(() => {
820
+ const outbox = this.database
821
+ .prepare(`SELECT id, project_id, workspace_id, topic, payload_json, created_at, delivered_at
822
+ FROM outbox WHERE project_id = ? AND workspace_id = ? ORDER BY id`)
823
+ .all(projectId, workspaceId);
824
+ const audit = this.database
825
+ .prepare(`SELECT id, project_id, workspace_id, event_type, payload_json, created_at
826
+ FROM audit_log WHERE project_id = ? AND workspace_id = ? ORDER BY id`)
827
+ .all(projectId, workspaceId);
828
+ return {
829
+ schemaVersion: CURRENT_SCHEMA_VERSION,
830
+ projectId,
831
+ workspaceId,
832
+ records: this.listRecords(projectId, workspaceId),
833
+ jobs: this.listJobs(projectId, workspaceId),
834
+ outbox: outbox.map(mapOutboxRow),
835
+ audit: audit.map(mapAuditRow),
836
+ };
837
+ });
838
+ }
839
+ exportProject(projectId) {
840
+ this.assertOpen();
841
+ requireIdentifier(projectId, 'projectId');
842
+ return this.snapshot(() => this.exportProjectSnapshot(projectId));
843
+ }
844
+ exportProjectSnapshot(projectId) {
845
+ const records = this.database
846
+ .prepare('SELECT project_id, workspace_id, kind, record_key, value_json, source_digest, updated_at FROM runtime_records WHERE project_id = ? ORDER BY workspace_id, kind, record_key')
847
+ .all(projectId);
848
+ const mapRows = (rows) => rows.map((row) => Object.fromEntries(Object.entries(row).map(([key, value]) => [
849
+ key,
850
+ key.endsWith('_json') && value !== null ? parseJson(value) : value,
851
+ ])));
852
+ const mappedRecords = records.map((row) => ({
853
+ projectId: String(row.project_id),
854
+ workspaceId: String(row.workspace_id),
855
+ kind: row.kind,
856
+ key: String(row.record_key),
857
+ value: parseJson(row.value_json),
858
+ sourceDigest: typeof row.source_digest === 'string' ? row.source_digest : undefined,
859
+ updatedAt: String(row.updated_at),
860
+ }));
861
+ const jobs = this.database
862
+ .prepare('SELECT * FROM jobs WHERE project_id = ? ORDER BY workspace_id, id')
863
+ .all(projectId);
864
+ const outbox = this.database
865
+ .prepare('SELECT * FROM outbox WHERE project_id = ? ORDER BY workspace_id, id')
866
+ .all(projectId);
867
+ const audit = this.database
868
+ .prepare('SELECT * FROM audit_log WHERE project_id = ? ORDER BY workspace_id, id')
869
+ .all(projectId);
870
+ return {
871
+ schemaVersion: 1,
872
+ projectId,
873
+ records: mappedRecords,
874
+ jobs: mapRows(jobs),
875
+ outbox: mapRows(outbox),
876
+ audit: mapRows(audit),
877
+ };
878
+ }
879
+ // eslint-disable-next-line complexity -- portable job validation is intentionally explicit
880
+ importJob(job) {
881
+ requireIdentifier(String(job.id), 'job id');
882
+ requireIdentifier(String(job.workspace_id), 'workspaceId');
883
+ const importedState = String(job.state);
884
+ const attempts = job.attempts === undefined ? 0 : Number(job.attempts);
885
+ const maxAttempts = job.max_attempts === undefined ? 3 : Number(job.max_attempts);
886
+ const fencingToken = job.fencing_token === undefined ? 0 : Number(job.fencing_token);
887
+ if (!Number.isSafeInteger(attempts) ||
888
+ attempts < 0 ||
889
+ !Number.isSafeInteger(maxAttempts) ||
890
+ maxAttempts < 1 ||
891
+ maxAttempts > 100 ||
892
+ !Number.isSafeInteger(fencingToken) ||
893
+ fencingToken < 0) {
894
+ throw new Error('[Planu] Runtime bundle contains invalid job attempts');
895
+ }
896
+ const importedRunning = importedState === 'running';
897
+ const state = importedState === 'pending'
898
+ ? 'accepted'
899
+ : importedRunning
900
+ ? job.cancel_requested === 1
901
+ ? 'cancelled'
902
+ : attempts >= maxAttempts
903
+ ? 'dead-letter'
904
+ : 'checkpointed'
905
+ : importedState;
906
+ if (!DURABLE_JOB_STATES.includes(state)) {
907
+ throw new Error('[Planu] Runtime bundle contains invalid job state');
908
+ }
909
+ this.database
910
+ .prepare(`INSERT INTO jobs
911
+ (id, project_id, workspace_id, state, payload_json, checkpoint_json, result_json,
912
+ error_message, attempts, max_attempts, cancel_requested, lease_owner,
913
+ lease_expires_at, fencing_token, created_at, updated_at)
914
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
915
+ ON CONFLICT(project_id, workspace_id, id) DO UPDATE SET
916
+ state = excluded.state, payload_json = excluded.payload_json,
917
+ checkpoint_json = excluded.checkpoint_json, result_json = excluded.result_json,
918
+ error_message = excluded.error_message, attempts = excluded.attempts,
919
+ max_attempts = excluded.max_attempts, cancel_requested = excluded.cancel_requested,
920
+ lease_owner = excluded.lease_owner, lease_expires_at = excluded.lease_expires_at,
921
+ fencing_token = MAX(jobs.fencing_token, excluded.fencing_token),
922
+ updated_at = excluded.updated_at
923
+ WHERE jobs.state != 'running' AND excluded.updated_at >= jobs.updated_at
924
+ AND NOT (
925
+ jobs.state IN ('cancelled', 'failed', 'dead-letter', 'completed')
926
+ AND excluded.state IN ('accepted', 'running', 'checkpointed')
927
+ )`)
928
+ .run(String(job.id), String(job.project_id), String(job.workspace_id), state, stringifyJson(job.payload_json), job.checkpoint_json === null || job.checkpoint_json === undefined
929
+ ? null
930
+ : stringifyJson(job.checkpoint_json), job.result_json === null || job.result_json === undefined
931
+ ? null
932
+ : stringifyJson(job.result_json), typeof job.error_message === 'string' ? job.error_message : null, attempts, maxAttempts, job.cancel_requested === 1 ? 1 : 0, !importedRunning && typeof job.lease_owner === 'string' ? job.lease_owner : null, !importedRunning && typeof job.lease_expires_at === 'string' ? job.lease_expires_at : null, fencingToken, String(job.created_at), String(job.updated_at));
933
+ }
934
+ assertLedgerIdAvailable(table, id, projectId, workspaceId) {
935
+ const existing = this.database
936
+ .prepare(`SELECT project_id, workspace_id FROM ${table} WHERE id = ?`)
937
+ .get(id);
938
+ if (existing && (existing.project_id !== projectId || existing.workspace_id !== workspaceId)) {
939
+ throw new Error(`[Planu] Runtime bundle ${table} id collides with another project`);
940
+ }
941
+ }
942
+ importOutbox(item, projectId) {
943
+ const id = Number(item.id);
944
+ if (!Number.isSafeInteger(id) || id < 1) {
945
+ throw new Error('[Planu] Runtime bundle contains invalid outbox id');
946
+ }
947
+ const workspaceId = String(item.workspace_id);
948
+ requireIdentifier(workspaceId, 'workspaceId');
949
+ requireIdentifier(String(item.topic), 'outbox topic');
950
+ this.assertLedgerIdAvailable('outbox', id, projectId, workspaceId);
951
+ this.database
952
+ .prepare(`INSERT INTO outbox
953
+ (id, project_id, workspace_id, topic, payload_json, created_at, delivered_at)
954
+ VALUES (?, ?, ?, ?, ?, ?, ?)
955
+ ON CONFLICT(id) DO UPDATE SET
956
+ topic = excluded.topic,
957
+ payload_json = excluded.payload_json,
958
+ delivered_at = excluded.delivered_at
959
+ WHERE outbox.project_id = excluded.project_id
960
+ AND outbox.workspace_id = excluded.workspace_id`)
961
+ .run(id, projectId, workspaceId, String(item.topic), stringifyJson(item.payload_json), String(item.created_at), typeof item.delivered_at === 'string' ? item.delivered_at : null);
962
+ }
963
+ importAudit(event, projectId) {
964
+ const id = Number(event.id);
965
+ if (!Number.isSafeInteger(id) || id < 1) {
966
+ throw new Error('[Planu] Runtime bundle contains invalid audit id');
967
+ }
968
+ const workspaceId = String(event.workspace_id);
969
+ requireIdentifier(workspaceId, 'workspaceId');
970
+ requireIdentifier(String(event.event_type), 'event type');
971
+ this.assertLedgerIdAvailable('audit_log', id, projectId, workspaceId);
972
+ this.database
973
+ .prepare(`INSERT INTO audit_log
974
+ (id, project_id, workspace_id, event_type, payload_json, created_at)
975
+ VALUES (?, ?, ?, ?, ?, ?)
976
+ ON CONFLICT(id) DO UPDATE SET
977
+ event_type = excluded.event_type,
978
+ payload_json = excluded.payload_json
979
+ WHERE audit_log.project_id = excluded.project_id
980
+ AND audit_log.workspace_id = excluded.workspace_id`)
981
+ .run(id, projectId, workspaceId, String(event.event_type), stringifyJson(event.payload_json), String(event.created_at));
982
+ }
983
+ importProject(bundle) {
984
+ requireIdentifier(bundle.projectId, 'projectId');
985
+ const foreignProject = [
986
+ ...bundle.records.map((item) => item.projectId),
987
+ ...bundle.jobs.map((item) => String(item.project_id)),
988
+ ...bundle.outbox.map((item) => String(item.project_id)),
989
+ ...bundle.audit.map((item) => String(item.project_id)),
990
+ ].find((projectId) => projectId !== bundle.projectId);
991
+ if (foreignProject) {
992
+ throw new Error('[Planu] Runtime bundle contains cross-project data');
993
+ }
994
+ this.transaction(() => {
995
+ for (const record of bundle.records) {
996
+ this.putRecord(record);
997
+ }
998
+ for (const job of bundle.jobs) {
999
+ this.importJob(job);
1000
+ }
1001
+ for (const item of bundle.outbox) {
1002
+ this.importOutbox(item, bundle.projectId);
1003
+ }
1004
+ for (const event of bundle.audit) {
1005
+ this.importAudit(event, bundle.projectId);
1006
+ }
1007
+ });
1008
+ }
1009
+ close() {
1010
+ if (this.closed) {
1011
+ return;
1012
+ }
1013
+ try {
1014
+ this.database.close();
1015
+ }
1016
+ finally {
1017
+ this.releaseConnection();
1018
+ this.closed = true;
1019
+ }
1020
+ }
1021
+ [Symbol.dispose]() {
1022
+ this.close();
1023
+ }
1024
+ }
1025
+ let inMemoryConnectionSequence = 0;
1026
+ function randomConnectionKey() {
1027
+ inMemoryConnectionSequence += 1;
1028
+ return String(inMemoryConnectionSequence);
1029
+ }
1030
+ function validateLeaseInput(input) {
1031
+ requireIdentifier(input.id, 'job id');
1032
+ requireIdentifier(input.projectId, 'projectId');
1033
+ requireIdentifier(input.workspaceId, 'workspaceId');
1034
+ requireIdentifier(input.workerId, 'worker id');
1035
+ if (!Number.isSafeInteger(input.leaseMs) || input.leaseMs < 100 || input.leaseMs > 300_000) {
1036
+ throw new Error('[Planu] leaseMs must be an integer between 100 and 300000');
1037
+ }
1038
+ if (input.now !== undefined && !Number.isFinite(Date.parse(input.now))) {
1039
+ throw new Error('[Planu] lease timestamp must be a valid ISO date');
1040
+ }
1041
+ }
1042
+ function requireFencingToken(input) {
1043
+ const token = input.fencingToken;
1044
+ if (token === undefined || !Number.isSafeInteger(token) || token < 1) {
1045
+ throw new Error('[Planu] Job lease requires a positive fencing token');
1046
+ }
1047
+ return token;
1048
+ }
1049
+ function optionalJson(value) {
1050
+ return typeof value === 'string' ? parseJson(value) : undefined;
1051
+ }
1052
+ function mapRuntimeRecordRow(row) {
1053
+ return {
1054
+ projectId: row.project_id,
1055
+ workspaceId: row.workspace_id,
1056
+ kind: row.kind,
1057
+ key: row.record_key,
1058
+ value: parseJson(row.value_json),
1059
+ sourceDigest: row.source_digest ?? undefined,
1060
+ updatedAt: row.updated_at,
1061
+ };
1062
+ }
1063
+ function mapOutboxRow(row) {
1064
+ return {
1065
+ id: Number(row.id),
1066
+ projectId: String(row.project_id),
1067
+ workspaceId: String(row.workspace_id),
1068
+ topic: String(row.topic),
1069
+ payload: parseJson(row.payload_json),
1070
+ createdAt: String(row.created_at),
1071
+ deliveredAt: typeof row.delivered_at === 'string' ? row.delivered_at : undefined,
1072
+ };
1073
+ }
1074
+ function mapAuditRow(row) {
1075
+ return {
1076
+ id: Number(row.id),
1077
+ projectId: String(row.project_id),
1078
+ workspaceId: String(row.workspace_id),
1079
+ eventType: String(row.event_type),
1080
+ payload: parseJson(row.payload_json),
1081
+ createdAt: String(row.created_at),
1082
+ };
1083
+ }
1084
+ function requireJobRecord(job, id) {
1085
+ if (!job) {
1086
+ throw new Error(`[Planu] Job ${id} disappeared after a committed update`);
1087
+ }
1088
+ return job;
1089
+ }
1090
+ function mapJobRow(row) {
1091
+ return {
1092
+ id: String(row.id),
1093
+ projectId: String(row.project_id),
1094
+ workspaceId: String(row.workspace_id),
1095
+ state: row.state,
1096
+ payload: parseJson(row.payload_json),
1097
+ checkpoint: optionalJson(row.checkpoint_json),
1098
+ result: optionalJson(row.result_json),
1099
+ error: typeof row.error_message === 'string' ? row.error_message : undefined,
1100
+ attempts: Number(row.attempts),
1101
+ maxAttempts: Number(row.max_attempts),
1102
+ cancelRequested: row.cancel_requested === 1,
1103
+ leaseOwner: typeof row.lease_owner === 'string' ? row.lease_owner : undefined,
1104
+ fencingToken: Number(row.fencing_token),
1105
+ leaseExpiresAt: typeof row.lease_expires_at === 'string' ? row.lease_expires_at : undefined,
1106
+ createdAt: String(row.created_at),
1107
+ updatedAt: String(row.updated_at),
1108
+ };
1109
+ }
1110
+ //# sourceMappingURL=runtime-db.js.map