@cassiomc1/forgeloop 1.13.0 → 2.0.0-rc.2

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 (395) hide show
  1. package/AGENT_COMPATIBILITY.md +8 -0
  2. package/CONTRIBUTING.md +11 -7
  3. package/DOCS_INDEX.md +37 -4
  4. package/ENG/c-development-eng.md +2 -2
  5. package/ENG/cpp-development-eng.md +2 -2
  6. package/ENG/dotnet-aspnetcore-development-eng.md +7 -1
  7. package/ENG/flutter-development-eng.md +4 -2
  8. package/ENG/go-development-eng.md +2 -2
  9. package/ENG/java-development-eng.md +3 -3
  10. package/ENG/nodejs-backend-development-eng.md +10 -6
  11. package/ENG/php-development-eng.md +3 -3
  12. package/ENG/python-development-eng.md +205 -0
  13. package/ENG/rust-development-eng.md +42 -1
  14. package/ENG/sec-code-eng.md +7 -7
  15. package/ENG/sql-development-eng.md +4 -4
  16. package/ENG/swift-development-eng.md +5 -4
  17. package/ENG/test-code-eng.md +1 -1
  18. package/ENG/typescript-development-eng.md +4 -4
  19. package/EXECUTION_STATE.md +12 -0
  20. package/GUIDE_ROUTER.md +6 -0
  21. package/LICENSE +133 -21
  22. package/LOOP_ENGINEERING.md +28 -2
  23. package/LOOP_SYSTEM_DESIGN.md +10 -10
  24. package/ORCHESTRATOR_INTEGRATION.md +9 -5
  25. package/PROTOCOL_INTEGRATION.md +55 -2
  26. package/README.md +63 -59
  27. package/TERMINOLOGY.md +2 -0
  28. package/THIRD_PARTY_NOTICES.md +3 -4
  29. package/THREAT_MODEL.md +140 -1
  30. package/completions/_forgeloop +29 -3
  31. package/completions/forgeloop.bash +55 -3
  32. package/completions/forgeloop.fish +183 -1
  33. package/docs/ADVISORY_CONTEXT.md +25 -0
  34. package/docs/AGENT_BROWSER_ADAPTER.md +81 -0
  35. package/docs/AGENT_BROWSER_VERIFICATION.md +6 -0
  36. package/docs/AGENT_PROTOCOL_SUMMARY.md +74 -39
  37. package/docs/AGENT_SKILL.md +66 -0
  38. package/docs/ARTIFACT_REFERENCE.md +171 -35
  39. package/docs/AUDIT_UX.md +46 -0
  40. package/docs/BROWSER_VERIFICATION.md +136 -0
  41. package/docs/CLI_REFERENCE.md +512 -8
  42. package/docs/CODE_ATTESTATION.md +2 -2
  43. package/docs/DOCUMENTATION_GUIDE.md +34 -11
  44. package/docs/GETTING_STARTED.md +3 -3
  45. package/docs/JEV_BENCHMARKS.md +31 -0
  46. package/docs/MODEL_ROUTING.md +37 -0
  47. package/docs/OPENSRC_ADAPTER.md +241 -0
  48. package/docs/PACKAGE_CONTENTS.md +46 -18
  49. package/docs/PROVIDERS.md +126 -0
  50. package/docs/PROVIDER_ARCHITECTURE.md +199 -0
  51. package/docs/RECIPES.md +9 -0
  52. package/docs/RELEASE_CHECKLIST.md +116 -12
  53. package/docs/SECURITY_REVIEW.md +71 -0
  54. package/docs/SELF_HOSTED_TESTS.md +121 -0
  55. package/docs/SEMANTIC_DECISION_PLANE.md +71 -0
  56. package/docs/TEST_INTELLIGENCE.md +29 -0
  57. package/docs/TEST_PRUNING.md +14 -0
  58. package/docs/TROUBLESHOOTING.md +198 -1
  59. package/docs/UNIVERSAL_INTEGRATION.md +31 -0
  60. package/docs/assets/diagrams/forgeloop-code-attestation-flow.html +2 -2
  61. package/docs/assets/diagrams/forgeloop-code-attestation-flow.receipt.json +5 -5
  62. package/docs/assets/diagrams/forgeloop-code-attestation-flow.svg +1 -1
  63. package/docs/assets/diagrams/forgeloop-engineering-flow.html +39 -26
  64. package/docs/assets/diagrams/forgeloop-engineering-flow.receipt.json +6 -6
  65. package/docs/assets/diagrams/forgeloop-engineering-flow.svg +26 -26
  66. package/docs/assets/diagrams/forgeloop-verification-trust-flow.html +2 -1
  67. package/docs/assets/diagrams/forgeloop-verification-trust-flow.receipt.json +5 -5
  68. package/docs/assets/diagrams/forgeloop-verification-trust-flow.svg +1 -1
  69. package/docs/diagrams/README.md +13 -9
  70. package/docs/diagrams/forgeloop-code-attestation-flow.workflow.json +1 -1
  71. package/docs/diagrams/forgeloop-engineering-flow.workflow.json +24 -19
  72. package/docs/diagrams/forgeloop-verification-trust-flow.workflow.json +1 -0
  73. package/docs/diagrams/reviews/forgeloop-code-attestation-flow.review.json +4 -4
  74. package/docs/diagrams/reviews/forgeloop-engineering-flow.review.json +4 -4
  75. package/docs/diagrams/reviews/forgeloop-verification-trust-flow.review.json +4 -4
  76. package/docs/documentation-manifest.json +774 -16
  77. package/docs/protocol-requirements.json +24 -0
  78. package/package.json +43 -11
  79. package/schemas/config.schema.json +14 -0
  80. package/schemas/context-plan.schema.json +18 -0
  81. package/schemas/semantic-decision.schema.json +46 -0
  82. package/schemas/task-bundle.schema.json +7 -2
  83. package/schemas/test-utility.schema.json +44 -0
  84. package/scripts/CI_VALIDATORS.md +6 -6
  85. package/scripts/benchmark-jev.mjs +5 -0
  86. package/scripts/benchmark-test-intelligence.mjs +4 -0
  87. package/scripts/generate-agent-protocol-summary.mjs +6 -3
  88. package/scripts/generate-forgeloop-skill.mjs +133 -0
  89. package/scripts/jev-smoke.mjs +19 -0
  90. package/scripts/run-mcp-clean-tests.mjs +30 -0
  91. package/skills/forgeloop/README.md +9 -0
  92. package/skills/forgeloop/SKILL.md +77 -0
  93. package/skills/forgeloop/references/lifecycle.md +9 -0
  94. package/skills/forgeloop/references/recovery.md +7 -0
  95. package/skills/forgeloop/references/verification.md +7 -0
  96. package/src/adapters/agent-browser/assertions.js +47 -0
  97. package/src/adapters/agent-browser/commands.js +54 -0
  98. package/src/adapters/agent-browser/index.js +3 -0
  99. package/src/adapters/agent-browser/locator.js +40 -0
  100. package/src/adapters/agent-browser/process.js +215 -0
  101. package/src/adapters/agent-browser/provider.js +316 -0
  102. package/src/adapters/emulated-services/constants.js +24 -0
  103. package/src/adapters/emulated-services/index.js +7 -0
  104. package/src/adapters/emulated-services/process.js +162 -0
  105. package/src/adapters/emulated-services/provider.js +289 -0
  106. package/src/adapters/opensrc/normalize.js +90 -0
  107. package/src/adapters/opensrc/process.js +248 -0
  108. package/src/adapters/opensrc/provider.js +338 -0
  109. package/src/adapters/opensrc/search.js +264 -0
  110. package/src/adapters/temporary-paths.js +18 -0
  111. package/src/adapters/typesafe/client.js +28 -0
  112. package/src/adapters/typesafe/engine.js +63 -0
  113. package/src/adapters/typesafe/normalize.js +41 -0
  114. package/src/cli.js +218 -174
  115. package/src/commands/action-show.js +5 -2
  116. package/src/commands/advance.js +5 -1
  117. package/src/commands/baseline.js +13 -11
  118. package/src/commands/checkpoint-revalidate.js +192 -0
  119. package/src/commands/complete.js +19 -3
  120. package/src/commands/context-plan.js +38 -0
  121. package/src/commands/contract-create.js +266 -0
  122. package/src/commands/contract-revise.js +236 -0
  123. package/src/commands/decision-show.js +14 -0
  124. package/src/commands/decision-status.js +22 -0
  125. package/src/commands/discover.js +41 -0
  126. package/src/commands/doctor.js +51 -13
  127. package/src/commands/gate-record.js +194 -0
  128. package/src/commands/gate-revalidate.js +135 -0
  129. package/src/commands/handoff-list.js +6 -1
  130. package/src/commands/handoff-show.js +6 -1
  131. package/src/commands/migrate-protocol.js +2 -2
  132. package/src/commands/model-route.js +40 -0
  133. package/src/commands/next.js +7 -1
  134. package/src/commands/policy-diff.js +25 -4
  135. package/src/commands/progress.js +17 -11
  136. package/src/commands/record-diagnosis.js +3 -0
  137. package/src/commands/route.js +146 -18
  138. package/src/commands/semantic-plan.js +41 -0
  139. package/src/commands/status.js +6 -1
  140. package/src/commands/storage-backup.js +15 -0
  141. package/src/commands/storage-migrate.js +5 -0
  142. package/src/commands/storage-migration-resume.js +5 -0
  143. package/src/commands/storage-migration-status.js +44 -0
  144. package/src/commands/storage-restore-resume.js +7 -0
  145. package/src/commands/storage-restore.js +8 -0
  146. package/src/commands/task-abandon.js +224 -0
  147. package/src/commands/task-list.js +8 -43
  148. package/src/commands/task-migrate-contract-bootstrap-repair.js +288 -0
  149. package/src/commands/task-migrate.js +3 -3
  150. package/src/commands/task-recover.js +10 -2
  151. package/src/commands/task-repair-contract-bootstrap.js +263 -0
  152. package/src/commands/task-scope.js +18 -2
  153. package/src/commands/task-show.js +16 -2
  154. package/src/commands/test-inventory.js +5 -0
  155. package/src/commands/test-prune-plan.js +5 -0
  156. package/src/commands/test-prune-probe.js +5 -0
  157. package/src/commands/test-utility.js +5 -0
  158. package/src/commands/validate-protocol.js +39 -15
  159. package/src/commands/validate-receipt.js +8 -1
  160. package/src/config/guides.json +4 -0
  161. package/src/core/action-ledger-projection.js +10 -3
  162. package/src/core/actions.js +38 -75
  163. package/src/core/activation.js +11 -3
  164. package/src/core/approvals.js +17 -51
  165. package/src/core/artifact-registry.js +83 -2
  166. package/src/core/artifacts.js +81 -27
  167. package/src/core/attachment-paths.js +45 -0
  168. package/src/core/attestation-coverage.js +6 -1
  169. package/src/core/attestation-verifier.js +21 -2
  170. package/src/core/attestation.js +17 -6
  171. package/src/core/audit-ux.js +514 -0
  172. package/src/core/audit.js +6 -1
  173. package/src/core/browser-verification/constants.js +149 -0
  174. package/src/core/browser-verification/normalize.js +254 -0
  175. package/src/core/browser-verification/provider.js +519 -0
  176. package/src/core/browser-verification/service.js +115 -0
  177. package/src/core/bundles.js +160 -66
  178. package/src/core/checkpoint-revalidation.js +321 -0
  179. package/src/core/cli-command-definitions.js +350 -7
  180. package/src/core/code-manifest.js +9 -3
  181. package/src/core/command-executors.js +274 -108
  182. package/src/core/command-input.js +136 -44
  183. package/src/core/completion-artifacts.js +85 -34
  184. package/src/core/completion-ownership.js +19 -8
  185. package/src/core/completion-recovery-rebind.js +11 -1
  186. package/src/core/completion.js +64 -15
  187. package/src/core/config.js +3 -0
  188. package/src/core/conformance.js +2 -1
  189. package/src/core/context-compiler/budget.js +9 -0
  190. package/src/core/context-compiler/candidates.js +39 -0
  191. package/src/core/context-compiler/compiler.js +63 -0
  192. package/src/core/context-compiler/fingerprint.js +11 -0
  193. package/src/core/context-compiler/policy.js +13 -0
  194. package/src/core/context-compiler/result.js +23 -0
  195. package/src/core/continuity-lint.js +13 -2
  196. package/src/core/continuity-reconciliation.js +16 -3
  197. package/src/core/continuity.js +16 -8
  198. package/src/core/contract-bootstrap-recovery.js +656 -0
  199. package/src/core/contract-revision.js +209 -0
  200. package/src/core/decision/artifact.js +70 -0
  201. package/src/core/decision/benchmarks.js +103 -0
  202. package/src/core/decision/cache.js +27 -0
  203. package/src/core/decision/constants.js +58 -0
  204. package/src/core/decision/cutover.js +34 -0
  205. package/src/core/decision/engine.js +22 -0
  206. package/src/core/decision/errors.js +68 -0
  207. package/src/core/decision/events.js +104 -0
  208. package/src/core/decision/freshness.js +19 -0
  209. package/src/core/decision/normalizers/index.js +115 -0
  210. package/src/core/decision/policy.js +18 -0
  211. package/src/core/decision/projection.js +16 -0
  212. package/src/core/decision/question-registry.js +201 -0
  213. package/src/core/decision/request.js +26 -0
  214. package/src/core/decision/resolver.js +138 -0
  215. package/src/core/decision/result.js +58 -0
  216. package/src/core/decision/service.js +181 -0
  217. package/src/core/decision/state-builder.js +65 -0
  218. package/src/core/decision/task-bindings.js +35 -0
  219. package/src/core/decision/test-provider.js +32 -0
  220. package/src/core/decision/thresholds.js +15 -0
  221. package/src/core/diagnosis-model.js +11 -0
  222. package/src/core/diagnosis.js +10 -1
  223. package/src/core/diagnostic-projection.js +29 -12
  224. package/src/core/diagnostic-record.js +28 -3
  225. package/src/core/efficiency.js +6 -1
  226. package/src/core/error-codes.js +278 -0
  227. package/src/core/events.js +535 -147
  228. package/src/core/evidence-readiness.js +9 -0
  229. package/src/core/execution-prerequisites.js +36 -13
  230. package/src/core/execution-profile.js +63 -38
  231. package/src/core/execution.js +26 -40
  232. package/src/core/filesystem.js +11 -0
  233. package/src/core/gate-artifact.js +105 -19
  234. package/src/core/gate-provenance.js +125 -0
  235. package/src/core/handoff.js +26 -14
  236. package/src/core/history.js +39 -35
  237. package/src/core/hypothesis-projection.js +32 -0
  238. package/src/core/information-gain-projection.js +104 -100
  239. package/src/core/inspect.js +12 -3
  240. package/src/core/integration-invocation-policy.js +37 -4
  241. package/src/core/integration-resources.js +119 -87
  242. package/src/core/ledger-event-collection.js +189 -0
  243. package/src/core/ledger-relations.js +23 -0
  244. package/src/core/model-router/constants.js +10 -0
  245. package/src/core/model-router/policy.js +103 -0
  246. package/src/core/model-router/router.js +37 -0
  247. package/src/core/native-storage.js +12 -0
  248. package/src/core/next-action-continuity.js +31 -9
  249. package/src/core/next-action-model.js +58 -0
  250. package/src/core/next-action-phases.js +131 -43
  251. package/src/core/next-action-refresh.js +43 -9
  252. package/src/core/next-action-review-phase.js +9 -4
  253. package/src/core/next-action-verification-phase.js +2 -1
  254. package/src/core/next-action.js +56 -9
  255. package/src/core/phase.js +266 -103
  256. package/src/core/policy-engine.js +12 -13
  257. package/src/core/preflight-consistency.js +89 -62
  258. package/src/core/preflight-loaders.js +48 -9
  259. package/src/core/preflight-model.js +6 -1
  260. package/src/core/preflight.js +29 -12
  261. package/src/core/progress.js +21 -10
  262. package/src/core/protocol-info.js +68 -0
  263. package/src/core/protocol-migration.js +7 -6
  264. package/src/core/protocol.js +20 -0
  265. package/src/core/reconcile-closure.js +281 -67
  266. package/src/core/recovery-history.js +67 -47
  267. package/src/core/reflection.js +72 -77
  268. package/src/core/responsibility.js +25 -13
  269. package/src/core/resumability.js +154 -44
  270. package/src/core/route-artifact.js +28 -4
  271. package/src/core/router.js +67 -1
  272. package/src/core/runtime-context.js +123 -61
  273. package/src/core/schema-validation.js +11 -3
  274. package/src/core/security-review/constants.js +64 -0
  275. package/src/core/security-review/normalize.js +245 -0
  276. package/src/core/security-review/provider.js +204 -0
  277. package/src/core/security-review/service.js +134 -0
  278. package/src/core/semantic-planning/constants.js +19 -0
  279. package/src/core/semantic-planning/projection.js +94 -0
  280. package/src/core/semantic-planning/service.js +15 -0
  281. package/src/core/settlement.js +12 -1
  282. package/src/core/signing/bundle-file.js +53 -0
  283. package/src/core/signing/bundle-reference.js +15 -0
  284. package/src/core/signing/sigstore.js +60 -33
  285. package/src/core/signing/statement-file.js +27 -0
  286. package/src/core/sources.js +37 -0
  287. package/src/core/storage-runtime-registry.js +41 -0
  288. package/src/core/structural-quality/artifacts.js +20 -14
  289. package/src/core/structural-quality/service.js +81 -56
  290. package/src/core/target-layout.js +1 -1
  291. package/src/core/task-claim-state.js +249 -15
  292. package/src/core/task-command.js +21 -1
  293. package/src/core/task-conflict-inspection.js +133 -102
  294. package/src/core/task-descriptor.js +29 -22
  295. package/src/core/task-discovery.js +288 -90
  296. package/src/core/task-lock.js +66 -306
  297. package/src/core/task-migration-validation.js +5 -5
  298. package/src/core/task-migration.js +17 -287
  299. package/src/core/task-paths.js +13 -0
  300. package/src/core/task-recovery.js +1 -0
  301. package/src/core/task-snapshot.js +51 -8
  302. package/src/core/task-storage-migration.js +18 -0
  303. package/src/core/templates.js +23 -8
  304. package/src/core/test-intelligence/benchmarks.js +68 -0
  305. package/src/core/test-intelligence/inventory.js +73 -0
  306. package/src/core/test-intelligence/prune.js +94 -0
  307. package/src/core/test-intelligence/semantic-state.js +15 -0
  308. package/src/core/test-intelligence/service.js +40 -0
  309. package/src/core/test-intelligence/utility.js +50 -0
  310. package/src/core/trace.js +164 -105
  311. package/src/core/trajectory-evaluation.js +15 -3
  312. package/src/core/trajectory-metrics.js +47 -32
  313. package/src/core/transaction.js +16 -287
  314. package/src/core/verification-scope.js +20 -12
  315. package/src/core/work-state.js +100 -59
  316. package/src/integration.d.ts +492 -0
  317. package/src/integration.js +54 -0
  318. package/src/providers/README.md +47 -0
  319. package/src/providers/capabilities.js +46 -0
  320. package/src/providers/errors.js +15 -0
  321. package/src/providers/index.js +29 -0
  322. package/src/providers/json-snapshot.js +105 -0
  323. package/src/providers/registry.js +152 -0
  324. package/src/repository-index/binary-manager.js +7 -5
  325. package/src/storage/artifact-bytes.js +22 -0
  326. package/src/storage/attachment-binding.js +11 -0
  327. package/src/storage/attachment-files.js +82 -0
  328. package/src/storage/attachment-references.js +36 -0
  329. package/src/storage/backup.js +53 -0
  330. package/src/storage/capabilities.js +31 -0
  331. package/src/storage/connection-owner.js +119 -0
  332. package/src/storage/connection.js +376 -0
  333. package/src/storage/existing-project-scope.js +45 -0
  334. package/src/storage/export-destination.js +44 -0
  335. package/src/storage/exporter.js +284 -0
  336. package/src/storage/file-durability.js +46 -0
  337. package/src/storage/importer.js +461 -0
  338. package/src/storage/index.js +74 -0
  339. package/src/storage/leases.js +63 -0
  340. package/src/storage/ledger-event-snapshot.js +150 -0
  341. package/src/storage/ledger-relations.js +220 -0
  342. package/src/storage/legacy-maintenance-boundary.js +18 -0
  343. package/src/storage/legacy-signature.js +115 -0
  344. package/src/storage/maintenance-handoff.js +129 -0
  345. package/src/storage/maintenance-owner.js +42 -0
  346. package/src/storage/maintenance.js +310 -0
  347. package/src/storage/metadata-json.js +35 -0
  348. package/src/storage/migration-activate.js +59 -0
  349. package/src/storage/migration-archive.js +57 -0
  350. package/src/storage/migration-attachment-root.js +61 -0
  351. package/src/storage/migration-candidate.js +398 -0
  352. package/src/storage/migration-publication.js +143 -0
  353. package/src/storage/migration-rollback-admission.js +54 -0
  354. package/src/storage/migration-rollback-preparation.js +132 -0
  355. package/src/storage/migration-rollback-publication.js +183 -0
  356. package/src/storage/migration-rollback-release.js +66 -0
  357. package/src/storage/migration-rollback-source-stage.js +103 -0
  358. package/src/storage/migration-rollback.js +43 -0
  359. package/src/storage/migration-source-partition.js +56 -0
  360. package/src/storage/migration-source.js +255 -0
  361. package/src/storage/migration-terminal.js +39 -0
  362. package/src/storage/migration-validation.js +75 -0
  363. package/src/storage/migration.js +43 -0
  364. package/src/storage/operational-attachments.js +49 -0
  365. package/src/storage/operational-context.js +50 -0
  366. package/src/storage/project-backup.js +98 -0
  367. package/src/storage/project-bootstrap.js +24 -0
  368. package/src/storage/project-boundary.js +79 -0
  369. package/src/storage/project-read-snapshot.js +18 -0
  370. package/src/storage/project-replacement.js +137 -0
  371. package/src/storage/project-restore.js +203 -0
  372. package/src/storage/record-definitions.js +45 -0
  373. package/src/storage/repository.js +507 -0
  374. package/src/storage/restore-journal.js +62 -0
  375. package/src/storage/restore-layout.js +30 -0
  376. package/src/storage/restore-preparation.js +84 -0
  377. package/src/storage/restore-replacement-archive.js +162 -0
  378. package/src/storage/restore-replacement-owner.js +31 -0
  379. package/src/storage/restore-replacement-preparation.js +128 -0
  380. package/src/storage/restore-replacement.js +142 -0
  381. package/src/storage/restore-terminal.js +32 -0
  382. package/src/storage/runtime.js +31 -0
  383. package/src/storage/schema.js +214 -0
  384. package/src/storage/singleton-import.js +84 -0
  385. package/src/storage/snapshot-continuity.js +16 -0
  386. package/src/storage/snapshot.js +36 -0
  387. package/src/storage/storage-marker.js +79 -0
  388. package/src/storage/task-guards.js +107 -0
  389. package/src/storage/topology.js +42 -0
  390. package/src/storage/transaction.js +179 -0
  391. package/src/storage/unit-of-work.js +663 -0
  392. package/src/storage/windows-process-incarnation.js +206 -0
  393. package/.forgeloop/forgeloop.gitignore +0 -4
  394. package/LICENSE-DOCS.md +0 -13
  395. package/src/core/transaction-maintenance.js +0 -70
@@ -1,3 +1,6 @@
1
+ import { needsExistingProjectScope } from "../storage/existing-project-scope.js";
2
+ import { getOperationalStore } from "../storage/operational-context.js";
3
+ import { ledgerTypeSummary } from "./ledger-event-collection.js";
1
4
  import {
2
5
  E_COMPLETION_OWNERSHIP_UNPROVEN,
3
6
  E_TASK_CLAIM_OWNERSHIP_INCONSISTENT,
@@ -6,8 +9,8 @@ import {
6
9
  E_TASK_RECOVERY_INCONSISTENT,
7
10
  } from "./error-codes.js";
8
11
  import { validateCompletionOwnershipProof } from "./completion-ownership.js";
9
- import { validateEventLedger } from "./events.js";
10
- import { classifyRecoveryHistory } from "./recovery-history.js";
12
+ import { validateEventLedger, validatePortableEventLedger, validateStateLedgerCoherence, withEventLedgerAudit } from "./events.js";
13
+ import { classifyRecoveryHistory, summarizeRecoveryHistory } from "./recovery-history.js";
11
14
  import { readTaskDescriptor } from "./task-descriptor.js";
12
15
  import { normalizeWriteClaims } from "./task-scope.js";
13
16
  import {
@@ -15,6 +18,35 @@ import {
15
18
  validateTaskRecoveryConsistency,
16
19
  } from "./task-recovery.js";
17
20
  import { readWorkState } from "./work-state.js";
21
+ import { readContract } from "./contract.js";
22
+ import { readPersistedRoute } from "./route-artifact.js";
23
+ import {
24
+ CONTRACT_BOOTSTRAP_REPAIR_EVENT,
25
+ resolveEffectiveContractBootstrapRepairAnchor,
26
+ resolveCanonicalPostRepairCheckpointBinding,
27
+ resolveCanonicalPostRepairRouteBinding,
28
+ sameCanonicalGuideList,
29
+ } from "./contract-bootstrap-recovery.js";
30
+ import { canonicalFingerprint } from "./artifacts.js";
31
+ import { stateIdentityErrors } from "./completion-relationships.js";
32
+ import { routeCheckpointMustMatchCurrentRoute } from "./resumability.js";
33
+
34
+ const REPAIR_PHASE_EVENTS = Object.freeze({
35
+ CONTRACT_READY: "CONTRACT_VALIDATED",
36
+ ROUTED: "ROUTE_VALIDATED",
37
+ DESIGNING: "DESIGN_GATE_STARTED",
38
+ PLANNED: "PLAN_RECORDED",
39
+ EXECUTING: "EXECUTION_STARTED",
40
+ VERIFYING: "VERIFICATION_STARTED",
41
+ DIAGNOSING: "VERIFICATION_STARTED",
42
+ CORRECTING: "VERIFICATION_STARTED",
43
+ REVIEWING: "REVIEW_STARTED",
44
+ COMPLETE: "COMPLETION_VALIDATED",
45
+ });
46
+
47
+ const REPAIR_ROUTE_PHASES = new Set([
48
+ "ROUTED", "DESIGNING", "PLANNED", "EXECUTING", "VERIFYING", "DIAGNOSING", "CORRECTING", "REVIEWING", "COMPLETE",
49
+ ]);
18
50
 
19
51
  function ownershipError(message, cause = null) {
20
52
  return {
@@ -24,10 +56,173 @@ function ownershipError(message, cause = null) {
24
56
  };
25
57
  }
26
58
 
59
+ function repairInvalid(message) {
60
+ return ownershipError(message, { code: "E_CONTRACT_BOOTSTRAP_REPAIR_INVALID" });
61
+ }
62
+
63
+ function lateRouteCheckpointErrors(events, state, marker) {
64
+ if (routeCheckpointMustMatchCurrentRoute(state.phase) || !REPAIR_PHASE_EVENTS[state.phase]) return [];
65
+ const checkpoint = resolveCanonicalPostRepairCheckpointBinding(events, marker);
66
+ if (!checkpoint) {
67
+ return [repairInvalid("Repaired late-phase state lacks an immutable route checkpoint binding")];
68
+ }
69
+ if (state.routeFingerprint !== checkpoint.routeFingerprint
70
+ || !sameCanonicalGuideList(state.selectedGuides, checkpoint.selectedGuides)) {
71
+ return [repairInvalid("Late-phase checkpoint route identity was rewritten after the canonical checkpoint binding")];
72
+ }
73
+ return [];
74
+ }
75
+
76
+ function repairArtifactErrors(artifacts) {
77
+ return [
78
+ ...(artifacts?.contractError
79
+ ? [repairInvalid(`Current contract artifact is invalid after a recorded repair: ${artifacts.contractError}`)]
80
+ : []),
81
+ ...(artifacts?.routeError
82
+ ? [repairInvalid(`Current route artifact is invalid after a recorded repair: ${artifacts.routeError}`)]
83
+ : []),
84
+ ];
85
+ }
86
+
87
+ function repairAnchorErrors(details, state, artifacts) {
88
+ const errors = [];
89
+ if (state.phase !== details.reconstructedPhase) {
90
+ errors.push(repairInvalid(
91
+ `Work-state phase ${state.phase} does not match repair anchor phase ${details.reconstructedPhase}`,
92
+ ));
93
+ }
94
+ if (canonicalFingerprint(state) !== details.reconstructedStateFingerprint) {
95
+ errors.push(repairInvalid("Work-state fingerprint does not match the repair anchor"));
96
+ }
97
+ const stateRouteFingerprint = state.routeFingerprint ?? null;
98
+ const currentRouteFingerprint = artifacts?.route?.fingerprint ?? null;
99
+ if (stateRouteFingerprint !== details.routeFingerprint
100
+ || currentRouteFingerprint !== details.routeFingerprint) {
101
+ errors.push(repairInvalid("Current route identity does not match the repair anchor"));
102
+ }
103
+ return errors;
104
+ }
105
+
106
+ function evolvedRepairErrors(anchor, events, state, artifacts) {
107
+ const errors = [];
108
+ const contract = artifacts?.contract ?? null;
109
+ const route = artifacts?.route ?? null;
110
+ if (!contract) errors.push(repairInvalid("Current contract is unavailable after a recorded repair"));
111
+ const routeRequired = REPAIR_ROUTE_PHASES.has(state.phase) || state.routeFingerprint !== undefined;
112
+ if (routeRequired && !route) {
113
+ errors.push(repairInvalid("Current route is required by the evolved task state but is unavailable"));
114
+ }
115
+ if (contract) {
116
+ const routeErrors = stateIdentityErrors({ contract, route, state });
117
+ const checkpointMustMatch = routeCheckpointMustMatchCurrentRoute(state.phase);
118
+ errors.push(...routeErrors
119
+ .filter((error) => checkpointMustMatch || error.code !== "E_ROUTE_GUIDE_MISMATCH")
120
+ .map((error) => repairInvalid(error.message)));
121
+ }
122
+ const currentRouteFingerprint = route?.fingerprint ?? null;
123
+ const binding = currentRouteFingerprint !== anchor.details.routeFingerprint
124
+ ? resolveCanonicalPostRepairRouteBinding(events, anchor.sourceMarker, currentRouteFingerprint)
125
+ : null;
126
+ if (currentRouteFingerprint !== anchor.details.routeFingerprint && !binding) {
127
+ errors.push(repairInvalid("Changed route identity lacks a canonical post-repair route binding"));
128
+ }
129
+ errors.push(...lateRouteCheckpointErrors(events, state, anchor.sourceMarker));
130
+ errors.push(...validateStateLedgerCoherence(state, events).map((error) => repairInvalid(error.message)));
131
+ const requiredEvent = REPAIR_PHASE_EVENTS[state.phase];
132
+ if (requiredEvent && !ledgerTypeSummary(events, requiredEvent).count) {
133
+ errors.push(repairInvalid(`Current work-state phase ${state.phase} is not supported by the repair ledger history`));
134
+ }
135
+ return errors;
136
+ }
137
+
138
+ function validateContractBootstrapRepairConsistency(taskId, events, state, artifacts) {
139
+ const anchor = resolveEffectiveContractBootstrapRepairAnchor(events);
140
+ if (!anchor) {
141
+ if (!ledgerTypeSummary(events, CONTRACT_BOOTSTRAP_REPAIR_EVENT).count) return [];
142
+ return [repairInvalid("Contract bootstrap repair marker is invalid")];
143
+ }
144
+ if (!state) return [repairInvalid("Work-state is missing after a recorded contract bootstrap repair")];
145
+ const details = anchor.details;
146
+ const errors = [];
147
+ if (state.taskId !== taskId) errors.push(repairInvalid("Work-state taskId does not match the repaired task"));
148
+ if (!Number.isInteger(state.revision) || state.revision < 0) {
149
+ return [...errors, repairInvalid("Work-state revision is missing or invalid after a recorded repair")];
150
+ }
151
+ const anchorRevision = details.reconstructedStateRevision;
152
+ if (state.revision < anchorRevision) {
153
+ return [...errors, repairInvalid("Work-state revision rolled back behind the repair anchor")];
154
+ }
155
+ if (state.contractFingerprint !== details.contractFingerprint) {
156
+ errors.push(repairInvalid("Work-state contract fingerprint does not match repair-time contract identity"));
157
+ }
158
+ errors.push(...repairArtifactErrors(artifacts));
159
+ return state.revision === anchorRevision
160
+ ? [...errors, ...repairAnchorErrors(details, state, artifacts)]
161
+ : [...errors, ...evolvedRepairErrors(anchor, events, state, artifacts)];
162
+ }
163
+
164
+ /**
165
+ * Async cross-artifact consistency collector for a recorded contract bootstrap
166
+ * repair. The pure classifier stays filesystem-free; this reads the current
167
+ * task-scoped contract and route artifacts through their canonical readers so
168
+ * schema validation, artifact bounds, task-scoped paths, and fingerprint
169
+ * semantics stay consistent with the rest of the protocol.
170
+ *
171
+ * With no repair marker this performs no extra work.
172
+ */
173
+ async function collectContractBootstrapRepairConsistency(target, packageRoot, taskId, events, state) {
174
+ const anchor = resolveEffectiveContractBootstrapRepairAnchor(events);
175
+ if (!anchor) return null;
176
+ const details = anchor.details;
177
+ const artifacts = { contract: null, route: null, contractError: null, routeError: null };
178
+
179
+ // Contract binding: the current contract must exist, validate, and bind to
180
+ // the marker and work state.
181
+ try {
182
+ const contract = await readContract(target, packageRoot, { taskId });
183
+ artifacts.contract = contract;
184
+ if (contract.fingerprint !== details.contractFingerprint) {
185
+ artifacts.contractError = `contract fingerprint ${contract.fingerprint} does not match marker contract fingerprint ${details.contractFingerprint}`;
186
+ } else if (state && state.contractFingerprint !== details.contractFingerprint) {
187
+ artifacts.contractError = "work-state contract fingerprint does not match marker contract fingerprint";
188
+ }
189
+ } catch (error) {
190
+ if (error.code === "E_STATE_REVISION_CONFLICT") throw error;
191
+ artifacts.contractError = error.code === "ARTIFACT_MISSING"
192
+ ? "contract artifact is missing after a recorded repair"
193
+ : `contract artifact is invalid after a recorded repair: ${error.message}`;
194
+ }
195
+
196
+ // Route binding is anchored exactly at repair time, then follows the
197
+ // current state/route identity after the checkpoint advances.
198
+ const routeRequired = state && (REPAIR_ROUTE_PHASES.has(state.phase)
199
+ || state.routeFingerprint !== undefined);
200
+ if (routeRequired || details.routeFingerprint !== null) {
201
+ try {
202
+ const route = await readPersistedRoute(target, packageRoot, { taskId });
203
+ artifacts.route = route;
204
+ if (route.value?.contractFingerprint !== undefined
205
+ && route.value.contractFingerprint !== details.contractFingerprint) {
206
+ artifacts.routeError = "route artifact contract binding does not match repair anchor contract fingerprint";
207
+ }
208
+ } catch (error) {
209
+ if (error.code === "E_STATE_REVISION_CONFLICT") throw error;
210
+ artifacts.routeError = error.code === "ARTIFACT_MISSING"
211
+ ? "route artifact is missing after a routed repair"
212
+ : `route artifact is invalid after a routed repair: ${error.message}`;
213
+ }
214
+ }
215
+
216
+ return artifacts;
217
+ }
218
+
27
219
  function appendClaims(target, claims, errors, source) {
28
220
  if (claims === undefined || claims === null) return;
29
221
  try {
30
- target.push(...normalizeWriteClaims(claims));
222
+ const normalized = normalizeWriteClaims(claims);
223
+ if (target instanceof Set || typeof target.add === "function") {
224
+ for (const claim of normalized) target.add(claim);
225
+ } else target.push(...normalized);
31
226
  } catch (error) {
32
227
  errors.push(ownershipError(`Invalid ${source} write claims: ${error.message}`, error));
33
228
  }
@@ -39,12 +234,12 @@ function appendClaims(target, claims, errors, source) {
39
234
  * classified recovery history. Classification is a pure function of this
40
235
  * evidence, so conflict inspection can reuse it without rereading artifacts.
41
236
  */
42
- export async function collectTaskClaimEvidence(target, {
237
+ async function collectClaimEvidence(target, {
43
238
  taskId,
44
239
  packageRoot,
45
240
  descriptor: suppliedDescriptor = null,
46
241
  state: suppliedState = null,
47
- } = {}) {
242
+ } = {}, suppliedLedger = null) {
48
243
  const errors = [];
49
244
  let descriptor = suppliedDescriptor;
50
245
  let state = suppliedState;
@@ -55,6 +250,7 @@ export async function collectTaskClaimEvidence(target, {
55
250
  try {
56
251
  descriptor = (await readTaskDescriptor(target, taskId, packageRoot)).value;
57
252
  } catch (error) {
253
+ if (error.code === "E_STATE_REVISION_CONFLICT") throw error;
58
254
  errors.push(ownershipError(`Task descriptor cannot establish claim ownership: ${error.message}`, error));
59
255
  }
60
256
  }
@@ -62,6 +258,7 @@ export async function collectTaskClaimEvidence(target, {
62
258
  try {
63
259
  state = await readWorkState(target, { taskId, packageRoot });
64
260
  } catch (error) {
261
+ if (error.code === "E_STATE_REVISION_CONFLICT") throw error;
65
262
  errors.push(ownershipError(`Task work state cannot establish claim ownership: ${error.message}`, error));
66
263
  }
67
264
  }
@@ -69,14 +266,27 @@ export async function collectTaskClaimEvidence(target, {
69
266
  try {
70
267
  recovery = (await readTaskRecovery(target, { taskId, packageRoot }))?.value ?? null;
71
268
  } catch (error) {
269
+ if (error.code === "E_STATE_REVISION_CONFLICT") throw error;
72
270
  errors.push(ownershipError(`Task recovery artifact cannot establish claim ownership: ${error.message}`, error));
73
271
  }
74
272
 
75
273
  try {
76
- ledger = await validateEventLedger(target, packageRoot, { taskId });
274
+ ledger = suppliedLedger ?? await (getOperationalStore(target) || await needsExistingProjectScope(target) ? validateEventLedger : validatePortableEventLedger)(target, packageRoot, { taskId });
77
275
  } catch (error) {
276
+ if (error.code === "E_STATE_REVISION_CONFLICT") throw error;
78
277
  errors.push(ownershipError(`Task event ledger cannot establish claim ownership: ${error.message}`, error));
79
278
  }
279
+ const repairArtifacts = await collectContractBootstrapRepairConsistency(target, packageRoot, taskId, ledger.events, state);
280
+ return buildTaskClaimEvidence({ taskId, descriptor, state, recovery, ledger, repairArtifacts, initialErrors: errors });
281
+ }
282
+
283
+ export async function collectTaskClaimEvidence(target, options = {}) {
284
+ return collectClaimEvidence(target, options);
285
+ }
286
+
287
+ /** Shared pure ownership evidence projection for filesystem and store snapshots. */
288
+ export function buildTaskClaimEvidence({ taskId, descriptor, state, recovery, ledger, repairArtifacts = null, initialErrors = [] }) {
289
+ const errors = [...initialErrors];
80
290
  if (!ledger.valid) {
81
291
  for (const error of ledger.errors) {
82
292
  errors.push(ownershipError(`Task event ledger is invalid: ${error.message}`, error));
@@ -85,16 +295,29 @@ export async function collectTaskClaimEvidence(target, {
85
295
  if (ledger.events.some((event) => event.taskId !== taskId)) {
86
296
  errors.push(ownershipError(`Task event ledger contains an event for a different task`));
87
297
  }
298
+ if (state) {
299
+ for (const error of validateStateLedgerCoherence(state, ledger.events)) {
300
+ if (![
301
+ "E_CHECKPOINT_REVALIDATION_UNSAFE",
302
+ "E_CONTRACT_REVISION_UNSAFE",
303
+ ].includes(error.code)) continue;
304
+ errors.push(ownershipError(`Task state and event ledger are incoherent: ${error.message}`, error));
305
+ }
306
+ }
307
+
308
+ const repairConsistencyErrors = validateContractBootstrapRepairConsistency(taskId, ledger.events, state, repairArtifacts);
309
+ errors.push(...repairConsistencyErrors);
88
310
 
89
- const history = classifyRecoveryHistory(ledger.events);
90
311
  const descriptorClaims = [];
91
312
  appendClaims(descriptorClaims, descriptor?.writeClaims, errors, "descriptor");
92
313
  const normalizedDescriptorClaims = normalizeWriteClaims(descriptorClaims);
93
314
 
94
- const historicalClaims = [...normalizedDescriptorClaims];
95
- for (const cycle of history.recoveries) {
96
- appendClaims(historicalClaims, cycle.event?.details?.releasedClaims, errors, "recovery ledger");
97
- }
315
+ const historicalClaims = new Set(normalizedDescriptorClaims);
316
+ const observeRecovery = cycle => appendClaims(historicalClaims, cycle.event?.details?.releasedClaims, errors, "recovery ledger");
317
+ const history = Array.isArray(ledger.events)
318
+ ? classifyRecoveryHistory(ledger.events)
319
+ : summarizeRecoveryHistory(ledger.events, observeRecovery);
320
+ if (Array.isArray(ledger.events)) for (const cycle of history.recoveries) observeRecovery(cycle);
98
321
  appendClaims(historicalClaims, recovery?.releasedClaims, errors, "recovery artifact");
99
322
 
100
323
  return {
@@ -106,7 +329,7 @@ export async function collectTaskClaimEvidence(target, {
106
329
  ledger,
107
330
  history,
108
331
  normalizedDescriptorClaims,
109
- historicalWriteClaims: normalizeWriteClaims(historicalClaims),
332
+ historicalWriteClaims: normalizeWriteClaims([...historicalClaims]),
110
333
  errors,
111
334
  };
112
335
  }
@@ -229,7 +452,7 @@ export function classifyTaskClaimState(evidence) {
229
452
  claimState: "ACTIVE",
230
453
  mutationAllowed: true,
231
454
  recovery: null,
232
- recoveryStatus: history.completedRecoveries.length > 0 ? "COMPLETED" : "ABSENT",
455
+ recoveryStatus: (history.completedRecoveryCount ?? history.completedRecoveries.length) > 0 ? "COMPLETED" : "ABSENT",
233
456
  valid: true,
234
457
  ownershipValid: true,
235
458
  reasonCodes: [],
@@ -243,9 +466,20 @@ export function classifyTaskClaimState(evidence) {
243
466
  * tombstone, and the complete validated task ledger. Any disagreement retains
244
467
  * every claim that can be recovered from validated inputs and fails closed.
245
468
  */
469
+ export async function withTaskClaimEvidence(target, options, callback) {
470
+ let store;
471
+ try { store = getOperationalStore(target); } catch { /* Preserve collected fail-closed evidence for invalid contexts. */ }
472
+ if (store && !store.hasPreparedMutations()
473
+ && typeof options.taskId === "string" && options.taskId) {
474
+ return withEventLedgerAudit(target, options.packageRoot, { taskId: options.taskId }, async ledger => (
475
+ callback(await collectClaimEvidence(target, options, ledger))
476
+ ));
477
+ }
478
+ return callback(await collectTaskClaimEvidence(target, options));
479
+ }
480
+
246
481
  export async function resolveTaskClaimState(target, options = {}) {
247
- const evidence = await collectTaskClaimEvidence(target, options);
248
- return classifyTaskClaimState(evidence);
482
+ return withTaskClaimEvidence(target, options, classifyTaskClaimState);
249
483
  }
250
484
 
251
485
  export async function assertTaskMutationAllowed(target, options = {}) {
@@ -2,6 +2,8 @@ import { resolveTaskContext, TASK_SELECTION_MODES } from "./task-context.js";
2
2
  import { withTaskTransaction } from "./transaction.js";
3
3
  import { assertTaskMutationAllowed } from "./task-claim-state.js";
4
4
  import { assertWorkspaceBinding } from "./workspace-binding.js";
5
+ import { getOperationalStore } from "../storage/operational-context.js";
6
+ import { withTaskLock } from "./task-lock.js";
5
7
 
6
8
  export async function withResolvedTask(
7
9
  target,
@@ -27,15 +29,33 @@ export async function withTaskMutation(
27
29
  callback,
28
30
  { explicitRequired = false, skipWorkspaceBinding = false } = {},
29
31
  ) {
32
+ if (!getOperationalStore(target)) {
33
+ const { withProjectStorage } = await import("../storage/project-boundary.js");
34
+ return withProjectStorage(target, () => withTaskMutation(target, options, operation, callback, { explicitRequired, skipWorkspaceBinding }));
35
+ }
30
36
  const taskOption = options.taskId ?? options.task ?? null;
31
37
  const taskContext = await resolveTaskContext(target, {
32
38
  taskId: taskOption,
33
- explicitRequired,
39
+ explicitRequired: explicitRequired || Boolean(getOperationalStore(target)),
34
40
  packageRoot: options.packageRoot,
35
41
  selectionMode: TASK_SELECTION_MODES.MUTATION,
36
42
  });
37
43
 
38
44
  if (taskContext) {
45
+ if (getOperationalStore(target) && ["run-action", "run-check"].includes(operation)) {
46
+ return withTaskLock(target, taskContext.taskId, operation, async () => {
47
+ await withTaskTransaction({ target, taskId: taskContext.taskId, operation: `${operation}:prepare`, packageRoot: options.packageRoot }, async () => {
48
+ await assertTaskMutationAllowed(target, { taskId: taskContext.taskId, packageRoot: options.packageRoot });
49
+ if (!skipWorkspaceBinding) await assertWorkspaceBinding(target, { taskId: taskContext.taskId, packageRoot: options.packageRoot, operation });
50
+ });
51
+ // External work runs with a durable semantic reservation and no open
52
+ // database transaction. Its domain services commit intent/outcome in
53
+ // separate transactions, so a crash cannot erase a durable start.
54
+ const result = await callback(taskContext);
55
+ await withTaskTransaction({ target, taskId: taskContext.taskId, operation, packageRoot: options.packageRoot, recordCommitEvent: true }, () => undefined);
56
+ return result;
57
+ });
58
+ }
39
59
  return withTaskTransaction({ target, taskId: taskContext.taskId, operation, packageRoot: options.packageRoot, recordCommitEvent: true }, async (transaction) => {
40
60
  await assertTaskMutationAllowed(target, { taskId: taskContext.taskId, packageRoot: options.packageRoot });
41
61
  if (!skipWorkspaceBinding) {