@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
@@ -2,8 +2,9 @@ import { classifyLoadedWorkState, readWorkState } from "./work-state.js";
2
2
  import { taskArtifactPath } from "./task-paths.js";
3
3
  import { readLockInfo, classifyLockStaleness } from "./task-lock.js";
4
4
  import { validateStateLedgerCoherence } from "./events.js";
5
+ import { ledgerEventAt, ledgerEventsOfTypes } from "./ledger-event-collection.js";
5
6
  import { currentRepositoryFingerprint } from "./repository.js";
6
- import { collectTaskClaimEvidence, classifyTaskClaimState } from "./task-claim-state.js";
7
+ import { withTaskClaimEvidence, classifyTaskClaimState } from "./task-claim-state.js";
7
8
 
8
9
  export const TASK_CONFLICT_CLASSIFICATIONS = Object.freeze([
9
10
  "ACTIVE",
@@ -55,13 +56,37 @@ function checkCount(state, status) {
55
56
  }
56
57
 
57
58
  function lastMeaningfulActivity(state, events) {
58
- const candidates = [
59
- ...(state?.lastUpdated ? [{ at: state.lastUpdated, type: "WORK_STATE_UPDATED" }] : []),
60
- ...events
61
- .filter((event) => MEANINGFUL_ACTIVITY_EVENTS.has(event.event))
62
- .map((event) => ({ at: event.at, type: event.event })),
63
- ].filter((candidate) => Number.isFinite(Date.parse(candidate.at)));
64
- return candidates.sort((left, right) => Date.parse(right.at) - Date.parse(left.at))[0] ?? null;
59
+ let latest = state?.lastUpdated && Number.isFinite(Date.parse(state.lastUpdated))
60
+ ? { at: state.lastUpdated, type: "WORK_STATE_UPDATED" }
61
+ : null;
62
+ for (const event of ledgerEventsOfTypes(events, [...MEANINGFUL_ACTIVITY_EVENTS])) {
63
+ const timestamp = Date.parse(event.at);
64
+ if (Number.isFinite(timestamp) && (!latest || timestamp > Date.parse(latest.at))) {
65
+ latest = { at: event.at, type: event.event };
66
+ }
67
+ }
68
+ return latest;
69
+ }
70
+
71
+ function isInitialTaskLedger(events, taskId) {
72
+ return events.length >= 2
73
+ && ledgerEventAt(events, 0)?.taskId === taskId
74
+ && ledgerEventAt(events, 0)?.event === "TASK_RECEIVED"
75
+ && ledgerEventAt(events, 1)?.taskId === taskId
76
+ && ledgerEventAt(events, 1)?.event === "TRANSACTION_COMMITTED"
77
+ && ledgerEventAt(events, 1)?.details?.operation === "task-create"
78
+ && !events.slice(2).some((event) => [
79
+ "CONTRACT_VALIDATED", "ROUTE_VALIDATED", "PREFLIGHT_READY", "EXECUTION_STARTED",
80
+ "VERIFICATION_STARTED", "VERIFICATION_RECORDED", "REVIEW_STARTED", "COMPLETION_VALIDATED",
81
+ "TASK_RECOVERY_RECORDED", "OPERATOR_RECOVERY_RECORDED", "TASK_RECOVERY_RESUMED",
82
+ ].includes(event.event));
83
+ }
84
+
85
+ function deriveEarlyPhase(events, taskId) {
86
+ if (!isInitialTaskLedger(events, taskId)) return null;
87
+ return events.some((event) => event.event === "DISCOVERY_STARTED")
88
+ ? "DISCOVERING"
89
+ : "RECEIVED";
65
90
  }
66
91
 
67
92
  /**
@@ -97,6 +122,7 @@ export function classifyConflictEvidence(evidence, {
97
122
  totalChecks,
98
123
  verificationEvidenceCount,
99
124
  recoveryStatus,
125
+ earlyPhase,
100
126
  } = evidence;
101
127
 
102
128
  if (!ledgerValid) {
@@ -107,10 +133,11 @@ export function classifyConflictEvidence(evidence, {
107
133
  };
108
134
  }
109
135
  const KNOWN_PHASES = new Set([
110
- "RECEIVED", "DISCOVERING", "CONTRACT_READY", "ROUTED", "DESIGNING", "PLANNED",
136
+ "RECEIVED", "DISCOVERING", "CONTRACT_READY", "ROUTED", "DESIGNING", "PLANNED", "BLOCKED",
111
137
  ...POST_EXECUTION_PHASES,
112
138
  ]);
113
- if (!phase || !KNOWN_PHASES.has(phase)) {
139
+ const effectivePhase = phase ?? earlyPhase;
140
+ if (!effectivePhase || !KNOWN_PHASES.has(effectivePhase)) {
114
141
  return {
115
142
  classification: "INCONSISTENT",
116
143
  reasonCodes: ["E_PHASE_UNKNOWN"],
@@ -151,7 +178,7 @@ export function classifyConflictEvidence(evidence, {
151
178
  };
152
179
  }
153
180
 
154
- if (phase === "COMPLETE") {
181
+ if (effectivePhase === "COMPLETE") {
155
182
  return {
156
183
  classification: "COMPLETE",
157
184
  reasonCodes: ["TASK_COMPLETE"],
@@ -175,7 +202,7 @@ export function classifyConflictEvidence(evidence, {
175
202
  };
176
203
  }
177
204
 
178
- if (POST_EXECUTION_PHASES.has(phase)) {
205
+ if (POST_EXECUTION_PHASES.has(effectivePhase)) {
179
206
  if (staleOnlyRepositoryDrift) {
180
207
  return {
181
208
  classification: "RECOVERABLE",
@@ -224,98 +251,102 @@ export async function inspectTaskConflictState(target, {
224
251
  now = Date.now(),
225
252
  ignoredLockId = null,
226
253
  } = {}) {
227
- const [lockInfo, stateResult, ownershipEvidence] = await Promise.all([
228
- readLockInfo(target, taskId),
229
- readWorkState(target, { packageRoot, taskId })
230
- .then((value) => ({ value, error: null }))
231
- .catch((error) => ({ value: null, error })),
232
- collectTaskClaimEvidence(target, { packageRoot, taskId }),
233
- ]);
234
- const claimProjection = classifyTaskClaimState(ownershipEvidence);
235
- const state = stateResult.value;
236
- const recovery = claimProjection.recovery;
237
-
238
- const lockClassification = ignoredLockId && lockInfo?.lockId === ignoredLockId
239
- ? { status: "NONE", stale: false }
240
- : classifyLockStaleness(lockInfo, now);
241
-
242
- let freshness = null;
243
- if (state) {
244
- try {
245
- freshness = await classifyLoadedWorkState({
246
- target,
247
- state,
248
- contractFile: taskArtifactPath(taskId, "contract"),
249
- });
250
- } catch {
251
- freshness = { status: "UNKNOWN", reasons: ["E_STATE_UNREADABLE"] };
254
+ return withTaskClaimEvidence(target, { packageRoot, taskId }, async ownershipEvidence => {
255
+ const [lockInfo, stateResult] = await Promise.all([
256
+ readLockInfo(target, taskId),
257
+ readWorkState(target, { packageRoot, taskId })
258
+ .then((value) => ({ value, error: null }))
259
+ .catch((error) => ({ value: null, error })),
260
+ ]);
261
+ const claimProjection = classifyTaskClaimState(ownershipEvidence);
262
+ const state = stateResult.value;
263
+ const recovery = claimProjection.recovery;
264
+
265
+ const lockClassification = ignoredLockId && lockInfo?.lockId === ignoredLockId
266
+ ? { status: "NONE", stale: false }
267
+ : classifyLockStaleness(lockInfo, now);
268
+
269
+ let freshness = null;
270
+ if (state) {
271
+ try {
272
+ freshness = await classifyLoadedWorkState({
273
+ target,
274
+ state,
275
+ contractFile: taskArtifactPath(taskId, "contract"),
276
+ });
277
+ } catch {
278
+ freshness = { status: "UNKNOWN", reasons: ["E_STATE_UNREADABLE"] };
279
+ }
252
280
  }
253
- }
254
281
 
255
- // Reuse the ownership snapshot's already-validated ledger; no second full
256
- // ledger parse inside this immutable inspection.
257
- const coherenceErrors = ownershipEvidence.state && ownershipEvidence.ledger
258
- ? validateStateLedgerCoherence(ownershipEvidence.state, ownershipEvidence.ledger.events)
259
- : [];
260
- const ledgerValid = ownershipEvidence.ledger.valid && coherenceErrors.length === 0;
261
- const ledgerEvents = ownershipEvidence.ledger.events;
262
- const ledgerErrors = [...ownershipEvidence.ledger.errors, ...coherenceErrors];
263
-
264
- const repository = await currentRepositoryFingerprint(target);
265
- const meaningfulActivity = lastMeaningfulActivity(state, ledgerEvents);
266
- const recoveryConsistencyErrors = claimProjection.ownershipErrors ?? claimProjection.errors ?? [];
267
- const healthReasonCodes = [
268
- ...(stateResult.error ? ["E_STATE_UNREADABLE"] : []),
269
- ...(claimProjection.ownershipValid === false
270
- ? claimProjection.reasonCodes
271
- : []),
272
- ];
273
-
274
- const evidence = {
275
- healthy: healthReasonCodes.length === 0,
276
- healthReasonCodes,
277
- descriptorHealthy: true,
278
- phase: state?.phase ?? null,
279
- lastUpdated: state?.lastUpdated ?? null,
280
- lastMeaningfulActivityAt: meaningfulActivity?.at ?? null,
281
- lastMeaningfulEventType: meaningfulActivity?.type ?? null,
282
- workStateRevision: state?.revision ?? 0,
283
- lockStatus: lockClassification.status,
284
- lockId: lockInfo?.lockId ?? null,
285
- lockExpiresAt: lockClassification.expiresAt ?? null,
286
- freshnessStatus: freshness?.status ?? "UNKNOWN",
287
- freshnessReasons: freshness?.reasons ?? [],
288
- ledgerValid,
289
- ledgerLastSeq: ledgerEvents.at(-1)?.seq ?? 0,
290
- ledgerErrors,
291
- recordedChecks: passedCheckCount(state),
292
- passedCheckCount: passedCheckCount(state),
293
- failedCheckCount: checkCount(state, "failed"),
294
- blockedCheckCount: checkCount(state, "blocked"),
295
- totalChecks: state?.checks?.length ?? 0,
296
- verificationEvidenceCount: state?.verificationEvidence?.length ?? 0,
297
- recoveryStatus: claimProjection.claimState === "RELEASED_BY_RECOVERY"
298
- ? "RECOVERED"
299
- : recovery?.status ?? null,
300
- recoveryConsistencyErrors,
301
- claimState: claimProjection.claimState,
302
- historicalWriteClaims: claimProjection.historicalWriteClaims,
303
- effectiveWriteClaims: claimProjection.effectiveWriteClaims,
304
- mutationAllowed: claimProjection.mutationAllowed,
305
- ownershipValid: claimProjection.ownershipValid,
306
- ownershipErrors: recoveryConsistencyErrors,
307
- repositoryBranch: repository.branch,
308
- repositoryHead: repository.head,
309
- };
282
+ // Reuse the ownership snapshot's already-validated ledger; no second full
283
+ // ledger parse inside this immutable inspection.
284
+ const coherenceErrors = ownershipEvidence.state && ownershipEvidence.ledger
285
+ ? validateStateLedgerCoherence(ownershipEvidence.state, ownershipEvidence.ledger.events)
286
+ : [];
287
+ const ledgerValid = ownershipEvidence.ledger.valid && coherenceErrors.length === 0;
288
+ const ledgerEvents = ownershipEvidence.ledger.events;
289
+ const ledgerErrors = [...ownershipEvidence.ledger.errors, ...coherenceErrors];
310
290
 
311
- const verdict = classifyConflictEvidence(evidence, { now });
291
+ const repository = await currentRepositoryFingerprint(target);
292
+ const initialTask = !state && ledgerValid && ownershipEvidence.descriptor
293
+ && isInitialTaskLedger(ledgerEvents, taskId)
294
+ && !ownershipEvidence.recovery;
295
+ const meaningfulActivity = lastMeaningfulActivity(state, ledgerEvents);
296
+ const recoveryConsistencyErrors = claimProjection.ownershipErrors ?? claimProjection.errors ?? [];
297
+ const healthReasonCodes = [
298
+ ...(stateResult.error ? ["E_STATE_UNREADABLE"] : []),
299
+ ...(claimProjection.ownershipValid === false
300
+ ? claimProjection.reasonCodes
301
+ : []),
302
+ ];
312
303
 
313
- return {
314
- taskId,
315
- classification: verdict.classification,
316
- reasonCodes: verdict.reasonCodes,
317
- recoverable: verdict.recoverable ?? false,
318
- ...(verdict.recoveredBy ? { recoveredBy: verdict.recoveredBy } : {}),
319
- evidence,
320
- };
304
+ const evidence = {
305
+ healthy: healthReasonCodes.length === 0,
306
+ healthReasonCodes,
307
+ descriptorHealthy: true,
308
+ phase: state?.phase ?? (initialTask ? deriveEarlyPhase(ledgerEvents, taskId) : null),
309
+ lastUpdated: state?.lastUpdated ?? null,
310
+ lastMeaningfulActivityAt: meaningfulActivity?.at ?? null,
311
+ lastMeaningfulEventType: meaningfulActivity?.type ?? null,
312
+ workStateRevision: state?.revision ?? 0,
313
+ lockStatus: lockClassification.status,
314
+ lockId: lockInfo?.lockId ?? null,
315
+ lockExpiresAt: lockClassification.expiresAt ?? null,
316
+ freshnessStatus: freshness?.status ?? (initialTask ? "FRESH" : "UNKNOWN"),
317
+ freshnessReasons: freshness?.reasons ?? [],
318
+ ledgerValid,
319
+ ledgerLastSeq: ledgerEvents.at(-1)?.seq ?? 0,
320
+ ledgerErrors,
321
+ recordedChecks: passedCheckCount(state),
322
+ passedCheckCount: passedCheckCount(state),
323
+ failedCheckCount: checkCount(state, "failed"),
324
+ blockedCheckCount: checkCount(state, "blocked"),
325
+ totalChecks: state?.checks?.length ?? 0,
326
+ verificationEvidenceCount: state?.verificationEvidence?.length ?? 0,
327
+ recoveryStatus: claimProjection.claimState === "RELEASED_BY_RECOVERY"
328
+ ? "RECOVERED"
329
+ : recovery?.status ?? null,
330
+ recoveryConsistencyErrors,
331
+ claimState: claimProjection.claimState,
332
+ historicalWriteClaims: claimProjection.historicalWriteClaims,
333
+ effectiveWriteClaims: claimProjection.effectiveWriteClaims,
334
+ mutationAllowed: claimProjection.mutationAllowed,
335
+ ownershipValid: claimProjection.ownershipValid,
336
+ ownershipErrors: recoveryConsistencyErrors,
337
+ repositoryBranch: repository.branch,
338
+ repositoryHead: repository.head,
339
+ };
340
+
341
+ const verdict = classifyConflictEvidence(evidence, { now });
342
+
343
+ return {
344
+ taskId,
345
+ classification: verdict.classification,
346
+ reasonCodes: verdict.reasonCodes,
347
+ recoverable: verdict.recoverable ?? false,
348
+ ...(verdict.recoveredBy ? { recoveredBy: verdict.recoveredBy } : {}),
349
+ evidence,
350
+ };
351
+ });
321
352
  }
@@ -1,5 +1,5 @@
1
1
  import { PROTOCOL_VERSION } from "./protocol.js";
2
- import { readJsonArtifact, writeJsonArtifact } from "./artifacts.js";
2
+ import { readJsonArtifact, readPortableJsonArtifact, writeJsonArtifact } from "./artifacts.js";
3
3
  import { assertSchema, readSchema } from "./schema-validation.js";
4
4
  import { getPackageRoot } from "./templates.js";
5
5
  import { assertTaskDescriptorIdentity, assertTaskId, taskStorageKey } from "./task-identity.js";
@@ -7,6 +7,8 @@ import { normalizeWriteClaims } from "./task-scope.js";
7
7
  import { taskArtifactPath, TASK_STATE_ROOT } from "./task-paths.js";
8
8
  import { assertSafePath, ensureWithin, fileExists } from "./filesystem.js";
9
9
  import { E_TASK_DESCRIPTOR_INVALID, E_TASK_NOT_FOUND } from "./error-codes.js";
10
+ import { operationalArtifactExists } from "../storage/operational-context.js";
11
+ import { withNativeReadScope } from "./native-storage.js";
10
12
 
11
13
  export const TASK_DESCRIPTOR_SCHEMA_VERSION = 1;
12
14
 
@@ -42,29 +44,34 @@ export async function validateTaskDescriptor(descriptor, packageRoot = getPackag
42
44
  }
43
45
 
44
46
  export async function readTaskDescriptor(target, taskIdOrKey, packageRoot = getPackageRoot()) {
45
- // If it's a 64-char key, use it directly; otherwise derive storage key
46
- const isKey = typeof taskIdOrKey === "string" && /^[a-f0-9]{64}$/.test(taskIdOrKey);
47
- const relativePath = isKey
48
- ? `${TASK_STATE_ROOT}/${taskIdOrKey}/task.json`
49
- : taskArtifactPath(taskIdOrKey, "descriptor");
47
+ return withNativeReadScope(target, async () => {
48
+ // If it's a 64-char key, use it directly; otherwise derive storage key
49
+ const isKey = typeof taskIdOrKey === "string" && /^[a-f0-9]{64}$/.test(taskIdOrKey);
50
+ const relativePath = isKey
51
+ ? `${TASK_STATE_ROOT}/${taskIdOrKey}/task.json`
52
+ : taskArtifactPath(taskIdOrKey, "descriptor");
50
53
 
51
- await assertSafePath(target, relativePath);
52
- const fullPath = ensureWithin(target, relativePath);
53
- if (!(await fileExists(fullPath))) {
54
- const error = new Error(`Task descriptor not found: ${relativePath}`);
55
- error.code = E_TASK_NOT_FOUND;
56
- error.artifacts = [relativePath];
57
- throw error;
58
- }
54
+ const operationalExists = operationalArtifactExists(target, relativePath);
55
+ if (operationalExists === null) await assertSafePath(target, relativePath);
56
+ const fullPath = ensureWithin(target, relativePath);
57
+ if (operationalExists === false || (operationalExists === null && !(await fileExists(fullPath)))) {
58
+ const error = new Error(`Task descriptor not found: ${relativePath}`);
59
+ error.code = E_TASK_NOT_FOUND;
60
+ error.artifacts = [relativePath];
61
+ throw error;
62
+ }
59
63
 
60
- const artifact = await readJsonArtifact(target, relativePath, "task-descriptor", packageRoot);
61
- try {
62
- await validateTaskDescriptor(artifact.value, packageRoot);
63
- } catch (error) {
64
- error.code = E_TASK_DESCRIPTOR_INVALID;
65
- throw error;
66
- }
67
- return { ...artifact, ...artifact.value, value: artifact.value };
64
+ // An unselected legacy descriptor is inspection input, never writable authority.
65
+ const reader = operationalExists === null ? readPortableJsonArtifact : readJsonArtifact;
66
+ const artifact = await reader(target, relativePath, "task-descriptor", packageRoot);
67
+ try {
68
+ await validateTaskDescriptor(artifact.value, packageRoot);
69
+ } catch (error) {
70
+ error.code = E_TASK_DESCRIPTOR_INVALID;
71
+ throw error;
72
+ }
73
+ return { ...artifact, ...artifact.value, value: artifact.value };
74
+ });
68
75
  }
69
76
 
70
77
  export async function writeTaskDescriptor(target, descriptor, packageRoot = getPackageRoot(), options = {}) {