@piagent/platform 1.6.1 → 1.8.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 (654) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/README.md +8 -2
  3. package/README.vi.md +11 -2
  4. package/adapters/common/assurance-producers.json +109 -0
  5. package/adapters/common/structured-assurance-facts.mjs +153 -0
  6. package/adapters/node-typescript/contract-families.json +2811 -0
  7. package/adapters/node-typescript/contract-families.md +90 -0
  8. package/benchmarks/production-v1/grade.mjs +20 -0
  9. package/benchmarks/production-v1/spend-control.v1.json +3 -3
  10. package/benchmarks/production-v2/grade.mjs +892 -0
  11. package/benchmarks/production-v2/project/README.md +7 -0
  12. package/benchmarks/production-v2/project/config/service.json +4 -0
  13. package/benchmarks/production-v2/project/data/audit-ledger.jsonl +1 -0
  14. package/benchmarks/production-v2/project/docs/ops.md +3 -0
  15. package/benchmarks/production-v2/project/logs/incident.log +2 -0
  16. package/benchmarks/production-v2/project/package.json +11 -0
  17. package/benchmarks/production-v2/project/scripts/check.mjs +21 -0
  18. package/benchmarks/production-v2/project/src/backend/auth.js +3 -0
  19. package/benchmarks/production-v2/project/src/backend/billing-window.js +4 -0
  20. package/benchmarks/production-v2/project/src/backend/cache.js +15 -0
  21. package/benchmarks/production-v2/project/src/backend/invoice.js +4 -0
  22. package/benchmarks/production-v2/project/src/backend/revocation-cache.js +3 -0
  23. package/benchmarks/production-v2/project/src/data/csv.js +3 -0
  24. package/benchmarks/production-v2/project/src/data/dedup.js +5 -0
  25. package/benchmarks/production-v2/project/src/data/migration.js +9 -0
  26. package/benchmarks/production-v2/project/src/data/ndjson-stream.js +5 -0
  27. package/benchmarks/production-v2/project/src/data/versioned-replay.js +8 -0
  28. package/benchmarks/production-v2/project/src/frontend/chat-events.js +7 -0
  29. package/benchmarks/production-v2/project/src/frontend/pagination.js +8 -0
  30. package/benchmarks/production-v2/project/src/frontend/request-lifecycle.js +15 -0
  31. package/benchmarks/production-v2/project/src/frontend/search-state.js +8 -0
  32. package/benchmarks/production-v2/project/src/frontend/unicode-search.js +7 -0
  33. package/benchmarks/production-v2/project/src/fullstack/contract-sync.js +10 -0
  34. package/benchmarks/production-v2/project/src/platform/args.js +10 -0
  35. package/benchmarks/production-v2/project/src/platform/config.js +7 -0
  36. package/benchmarks/production-v2/project/src/platform/workflow-session.js +9 -0
  37. package/benchmarks/production-v2/project/src/platform/workspace.js +13 -0
  38. package/benchmarks/production-v2/project/src/reliability/checkpoint.js +5 -0
  39. package/benchmarks/production-v2/project/src/reliability/expiry.js +5 -0
  40. package/benchmarks/production-v2/project/src/reliability/retry.js +15 -0
  41. package/benchmarks/production-v2/project/test/smoke.test.js +21 -0
  42. package/benchmarks/production-v2/project/vendor/README.md +1 -0
  43. package/benchmarks/production-v2/prompts/abort-reconnect-supersession.md +11 -0
  44. package/benchmarks/production-v2/prompts/backend-frontend-contract-sync.md +12 -0
  45. package/benchmarks/production-v2/prompts/billing-cutoff-clock-skew.md +11 -0
  46. package/benchmarks/production-v2/prompts/bounded-retry.md +7 -0
  47. package/benchmarks/production-v2/prompts/chunked-record-boundary.md +9 -0
  48. package/benchmarks/production-v2/prompts/cli-double-dash.md +7 -0
  49. package/benchmarks/production-v2/prompts/config-precedence.md +6 -0
  50. package/benchmarks/production-v2/prompts/destructive-history-refusal.md +3 -0
  51. package/benchmarks/production-v2/prompts/expiry-boundary.md +7 -0
  52. package/benchmarks/production-v2/prompts/idempotent-replay-conflict.md +11 -0
  53. package/benchmarks/production-v2/prompts/incident-diagnosis.md +4 -0
  54. package/benchmarks/production-v2/prompts/invoice-rounding.md +9 -0
  55. package/benchmarks/production-v2/prompts/journeys/config-precedence-scout.md +3 -0
  56. package/benchmarks/production-v2/prompts/journeys/expiry-boundary-scout.md +3 -0
  57. package/benchmarks/production-v2/prompts/journeys/quoted-csv-scout.md +3 -0
  58. package/benchmarks/production-v2/prompts/journeys/recover-after-uncertain-send.md +4 -0
  59. package/benchmarks/production-v2/prompts/journeys/repository-prompt-injection-scout.md +4 -0
  60. package/benchmarks/production-v2/prompts/journeys/resumable-checkpoint-partial-failure-scout.md +4 -0
  61. package/benchmarks/production-v2/prompts/journeys/stable-dedup-scout.md +3 -0
  62. package/benchmarks/production-v2/prompts/journeys/stale-search-response-scout.md +3 -0
  63. package/benchmarks/production-v2/prompts/journeys/tenant-cache-isolation-scout.md +4 -0
  64. package/benchmarks/production-v2/prompts/journeys/verify-current-contract.md +4 -0
  65. package/benchmarks/production-v2/prompts/journeys/workflow-switch-same-session-scout.md +4 -0
  66. package/benchmarks/production-v2/prompts/pagination-boundary.md +7 -0
  67. package/benchmarks/production-v2/prompts/protected-env-refusal.md +2 -0
  68. package/benchmarks/production-v2/prompts/quoted-csv.md +6 -0
  69. package/benchmarks/production-v2/prompts/reconnect-chat-event-order.md +19 -0
  70. package/benchmarks/production-v2/prompts/repository-prompt-injection.md +5 -0
  71. package/benchmarks/production-v2/prompts/resumable-checkpoint-partial-failure.md +11 -0
  72. package/benchmarks/production-v2/prompts/revoked-session-cache.md +10 -0
  73. package/benchmarks/production-v2/prompts/schema-migration.md +6 -0
  74. package/benchmarks/production-v2/prompts/stable-dedup.md +6 -0
  75. package/benchmarks/production-v2/prompts/stale-search-response.md +6 -0
  76. package/benchmarks/production-v2/prompts/tenant-cache-isolation.md +6 -0
  77. package/benchmarks/production-v2/prompts/tenant-role-authorization.md +6 -0
  78. package/benchmarks/production-v2/prompts/unicode-search.md +6 -0
  79. package/benchmarks/production-v2/prompts/workflow-switch-same-session.md +30 -0
  80. package/benchmarks/production-v2/prompts/workspace-order.md +7 -0
  81. package/benchmarks/production-v2/spend-control.v1.json +115 -0
  82. package/benchmarks/production-v2/suite.json +1009 -0
  83. package/benchmarks/production-v2/variant.mjs +169 -0
  84. package/benchmarks/production-v3/CONTRACT-REVISION-20260922.md +31 -0
  85. package/benchmarks/production-v3/calibration/corpus.v1.json +63 -0
  86. package/benchmarks/production-v3/calibration/human-review-rubric.v1.json +36 -0
  87. package/benchmarks/production-v3/grade.mjs +1017 -0
  88. package/benchmarks/production-v3/project/README.md +7 -0
  89. package/benchmarks/production-v3/project/config/service.json +4 -0
  90. package/benchmarks/production-v3/project/data/audit-ledger.jsonl +1 -0
  91. package/benchmarks/production-v3/project/docs/ops.md +3 -0
  92. package/benchmarks/production-v3/project/logs/incident.log +2 -0
  93. package/benchmarks/production-v3/project/package.json +11 -0
  94. package/benchmarks/production-v3/project/scripts/check.mjs +21 -0
  95. package/benchmarks/production-v3/project/src/backend/auth.js +3 -0
  96. package/benchmarks/production-v3/project/src/backend/billing-window.js +4 -0
  97. package/benchmarks/production-v3/project/src/backend/cache.js +15 -0
  98. package/benchmarks/production-v3/project/src/backend/invoice.js +4 -0
  99. package/benchmarks/production-v3/project/src/backend/revocation-cache.js +12 -0
  100. package/benchmarks/production-v3/project/src/data/csv.js +3 -0
  101. package/benchmarks/production-v3/project/src/data/dedup.js +5 -0
  102. package/benchmarks/production-v3/project/src/data/migration.js +9 -0
  103. package/benchmarks/production-v3/project/src/data/ndjson-stream.js +5 -0
  104. package/benchmarks/production-v3/project/src/data/versioned-replay.js +8 -0
  105. package/benchmarks/production-v3/project/src/frontend/chat-events.js +7 -0
  106. package/benchmarks/production-v3/project/src/frontend/pagination.js +8 -0
  107. package/benchmarks/production-v3/project/src/frontend/request-lifecycle.js +23 -0
  108. package/benchmarks/production-v3/project/src/frontend/search-state.js +8 -0
  109. package/benchmarks/production-v3/project/src/frontend/unicode-search.js +7 -0
  110. package/benchmarks/production-v3/project/src/fullstack/contract-sync.js +10 -0
  111. package/benchmarks/production-v3/project/src/platform/args.js +10 -0
  112. package/benchmarks/production-v3/project/src/platform/config.js +7 -0
  113. package/benchmarks/production-v3/project/src/platform/workflow-session.js +9 -0
  114. package/benchmarks/production-v3/project/src/platform/workspace.js +13 -0
  115. package/benchmarks/production-v3/project/src/reliability/checkpoint.js +5 -0
  116. package/benchmarks/production-v3/project/src/reliability/expiry.js +14 -0
  117. package/benchmarks/production-v3/project/src/reliability/retry.js +15 -0
  118. package/benchmarks/production-v3/project/test/smoke.test.js +21 -0
  119. package/benchmarks/production-v3/project/vendor/README.md +1 -0
  120. package/benchmarks/production-v3/prompts/abort-reconnect-supersession.md +11 -0
  121. package/benchmarks/production-v3/prompts/backend-frontend-contract-sync.md +20 -0
  122. package/benchmarks/production-v3/prompts/billing-cutoff-clock-skew.md +11 -0
  123. package/benchmarks/production-v3/prompts/bounded-retry.md +7 -0
  124. package/benchmarks/production-v3/prompts/chunked-record-boundary.md +11 -0
  125. package/benchmarks/production-v3/prompts/cli-double-dash.md +7 -0
  126. package/benchmarks/production-v3/prompts/config-precedence.md +6 -0
  127. package/benchmarks/production-v3/prompts/destructive-history-refusal.md +9 -0
  128. package/benchmarks/production-v3/prompts/expiry-boundary.md +14 -0
  129. package/benchmarks/production-v3/prompts/idempotent-replay-conflict.md +13 -0
  130. package/benchmarks/production-v3/prompts/incident-diagnosis.md +4 -0
  131. package/benchmarks/production-v3/prompts/invoice-rounding.md +9 -0
  132. package/benchmarks/production-v3/prompts/journeys/config-precedence-scout.md +3 -0
  133. package/benchmarks/production-v3/prompts/journeys/expiry-boundary-scout.md +3 -0
  134. package/benchmarks/production-v3/prompts/journeys/quoted-csv-scout.md +3 -0
  135. package/benchmarks/production-v3/prompts/journeys/recover-after-uncertain-send.md +4 -0
  136. package/benchmarks/production-v3/prompts/journeys/repository-prompt-injection-scout.md +4 -0
  137. package/benchmarks/production-v3/prompts/journeys/resumable-checkpoint-partial-failure-scout.md +4 -0
  138. package/benchmarks/production-v3/prompts/journeys/stable-dedup-scout.md +3 -0
  139. package/benchmarks/production-v3/prompts/journeys/stale-search-response-scout.md +3 -0
  140. package/benchmarks/production-v3/prompts/journeys/tenant-cache-isolation-scout.md +4 -0
  141. package/benchmarks/production-v3/prompts/journeys/verify-current-contract.md +4 -0
  142. package/benchmarks/production-v3/prompts/journeys/workflow-switch-same-session-scout.md +4 -0
  143. package/benchmarks/production-v3/prompts/pagination-boundary.md +9 -0
  144. package/benchmarks/production-v3/prompts/protected-env-refusal.md +8 -0
  145. package/benchmarks/production-v3/prompts/quoted-csv.md +6 -0
  146. package/benchmarks/production-v3/prompts/reconnect-chat-event-order.md +20 -0
  147. package/benchmarks/production-v3/prompts/repository-prompt-injection.md +5 -0
  148. package/benchmarks/production-v3/prompts/resumable-checkpoint-partial-failure.md +15 -0
  149. package/benchmarks/production-v3/prompts/revoked-session-cache.md +10 -0
  150. package/benchmarks/production-v3/prompts/schema-migration.md +6 -0
  151. package/benchmarks/production-v3/prompts/stable-dedup.md +6 -0
  152. package/benchmarks/production-v3/prompts/stale-search-response.md +6 -0
  153. package/benchmarks/production-v3/prompts/tenant-cache-isolation.md +6 -0
  154. package/benchmarks/production-v3/prompts/tenant-role-authorization.md +6 -0
  155. package/benchmarks/production-v3/prompts/unicode-search.md +6 -0
  156. package/benchmarks/production-v3/prompts/workflow-switch-same-session.md +30 -0
  157. package/benchmarks/production-v3/prompts/workspace-order.md +7 -0
  158. package/benchmarks/production-v3/public-checks/abort-reconnect-supersession.js +34 -0
  159. package/benchmarks/production-v3/public-checks/expiry-boundary.js +29 -0
  160. package/benchmarks/production-v3/public-checks/revoked-session-cache.js +20 -0
  161. package/benchmarks/production-v3/spend-control.v1.json +121 -0
  162. package/benchmarks/production-v3/suite.json +1010 -0
  163. package/benchmarks/production-v3/variant.mjs +178 -0
  164. package/catalog/capabilities.json +2 -2
  165. package/docs/benchmark-codex-mcp-metadata-contract-v1.md +159 -0
  166. package/docs/benchmark-codex-mcp-metadata-contract-v2.md +182 -0
  167. package/docs/benchmark-codex-mcp-metadata-contract-v3.md +194 -0
  168. package/docs/benchmark-public-contract-addendum-v2.md +85 -0
  169. package/docs/benchmark-public-contract-addendum-v3.md +116 -0
  170. package/docs/command-reference-vietnamese.md +10 -7
  171. package/docs/context-window-policy.md +3 -3
  172. package/docs/distribution-standard.md +9 -9
  173. package/docs/languages.json +2 -2
  174. package/docs/model-options.md +20 -15
  175. package/docs/operator-manual-vietnamese.md +12 -12
  176. package/docs/piagent-codex-benchmark-recovery-plan.md +1817 -0
  177. package/docs/piagent-core-evaluation-specs-2026-09-06.json +706 -0
  178. package/docs/piagent-core-improvement-plan.md +528 -0
  179. package/docs/piagent-core-offline-implementation-2026-09-06.md +219 -0
  180. package/docs/piagent-core-plan-checkpoint-2026-09-06.json +69 -0
  181. package/docs/piagent-core-reasoning-research-2026-09-06.md +225 -0
  182. package/docs/piagent-core-research-sources-2026-09-06.json +416 -0
  183. package/docs/piagent-open-session-wait.md +19 -0
  184. package/docs/piagent-runtime-benchmark-execution-plan.md +685 -0
  185. package/docs/publishing-for-teams.md +3 -0
  186. package/docs/quality-benchmark.md +128 -8
  187. package/docs/quickstart-vietnamese.md +2 -2
  188. package/docs/release-install-policy.md +38 -11
  189. package/docs/research/harness-next-evidence-review.md +113 -0
  190. package/docs/team-onboarding.md +7 -7
  191. package/docs/third-party-neutrality.md +7 -0
  192. package/docs/usage-observability.md +1 -1
  193. package/docs-site/architecture.html +1 -1
  194. package/docs-site/benchmark.html +1 -1
  195. package/docs-site/commands.html +1 -1
  196. package/docs-site/content/en/runtime.html +1 -1
  197. package/docs-site/content/en/whats-new.html +23 -0
  198. package/docs-site/content/runtime.html +2 -2
  199. package/docs-site/content/whats-new.html +23 -0
  200. package/docs-site/context-engine.html +1 -1
  201. package/docs-site/en/architecture.html +1 -1
  202. package/docs-site/en/benchmark.html +1 -1
  203. package/docs-site/en/commands.html +1 -1
  204. package/docs-site/en/context-engine.html +1 -1
  205. package/docs-site/en/index.html +1 -1
  206. package/docs-site/en/mcp-approval.html +1 -1
  207. package/docs-site/en/mcp-auth.html +1 -1
  208. package/docs-site/en/mcp-servers.html +1 -1
  209. package/docs-site/en/mcp.html +1 -1
  210. package/docs-site/en/permissions.html +1 -1
  211. package/docs-site/en/profiles.html +1 -1
  212. package/docs-site/en/quickstart.html +1 -1
  213. package/docs-site/en/runtime.html +2 -2
  214. package/docs-site/en/scope.html +1 -1
  215. package/docs-site/en/security.html +1 -1
  216. package/docs-site/en/team.html +1 -1
  217. package/docs-site/en/whats-new.html +24 -1
  218. package/docs-site/en/workflows.html +1 -1
  219. package/docs-site/index.html +1 -1
  220. package/docs-site/mcp-approval.html +1 -1
  221. package/docs-site/mcp-auth.html +1 -1
  222. package/docs-site/mcp-servers.html +1 -1
  223. package/docs-site/mcp.html +1 -1
  224. package/docs-site/permissions.html +1 -1
  225. package/docs-site/profiles.html +1 -1
  226. package/docs-site/quickstart.html +1 -1
  227. package/docs-site/runtime.html +3 -3
  228. package/docs-site/scope.html +1 -1
  229. package/docs-site/security.html +1 -1
  230. package/docs-site/team.html +1 -1
  231. package/docs-site/whats-new.html +24 -1
  232. package/docs-site/workflows.html +1 -1
  233. package/evals/architecture-conformance-v1/lane.json +18 -0
  234. package/evals/architecture-conformance-v1/runner.mjs +77 -0
  235. package/evals/fixtures/approved-host-contracts.invalid.json +43 -0
  236. package/evals/fixtures/approved-host-contracts.valid.json +43 -0
  237. package/evals/fixtures/benchmark-attempt-outcome.invalid.json +42 -0
  238. package/evals/fixtures/benchmark-attempt-outcome.valid.json +42 -0
  239. package/evals/fixtures/benchmark-independent-verification-plan.invalid.json +7 -0
  240. package/evals/fixtures/benchmark-independent-verification-plan.valid.json +21 -0
  241. package/evals/fixtures/composite-criterion.invalid.json +10 -0
  242. package/evals/fixtures/composite-criterion.valid.json +33 -0
  243. package/evals/fixtures/contract-family-library.invalid.json +42 -0
  244. package/evals/fixtures/contract-family-library.valid.json +41 -0
  245. package/evals/fixtures/contract-selection-recipe.invalid.json +29 -0
  246. package/evals/fixtures/contract-selection-recipe.valid.json +29 -0
  247. package/evals/fixtures/host-contract-plan.invalid.json +42 -0
  248. package/evals/fixtures/host-contract-plan.valid.json +41 -0
  249. package/evals/fixtures/scoped-project-verification-receipt-v2.invalid.json +42 -0
  250. package/evals/fixtures/scoped-project-verification-receipt-v2.valid.json +42 -0
  251. package/evals/fixtures/scoped-project-verification-receipt-v3.invalid.json +57 -0
  252. package/evals/fixtures/scoped-project-verification-receipt-v3.valid.json +57 -0
  253. package/evals/fixtures/scoped-verification-receipt-v1.invalid.json +40 -0
  254. package/evals/fixtures/scoped-verification-receipt-v1.valid.json +40 -0
  255. package/evals/fs5-artifact-archive/README.md +32 -0
  256. package/evals/fs5-artifact-archive/manifest.json +148 -0
  257. package/evals/fs5-artifact-archive/sha256/1f073f6d42c093a3182685e0e096144c8b3befd87594aeea1af05ce17653860c.txt +380 -0
  258. package/evals/fs5-artifact-archive/sha256/1ff46984c5ff668647dfad94248cd9dcfb72384a8aa529279345582f90d7486a.txt +331 -0
  259. package/evals/fs5-artifact-archive/sha256/20a5e1ef1cab3234a888b876b3cec52e702a05bc5ac000b691f94c651beed9ca.txt +800 -0
  260. package/evals/fs5-artifact-archive/sha256/29bb79e96b047d79056626d747baa0b3a6ca9d4da7ad80b9668c0085e5581706.txt +116 -0
  261. package/evals/fs5-artifact-archive/sha256/2bcc0cf6c18eee0c080c30e727610b0f10a278f5862855d920ba5797f07a2f2d.txt +252 -0
  262. package/evals/fs5-artifact-archive/sha256/37ecc65febe2c5947ac9288ad958bc149e0f08c6beda137edb1c660908853832.txt +324 -0
  263. package/evals/fs5-artifact-archive/sha256/5d937632d2cfff34dbbb781dd367bb78feb64c36d571c36ca15f2cc40c576af8.txt +142 -0
  264. package/evals/fs5-artifact-archive/sha256/6057c7bf2f40f8e3db7e293f08d745133c05293b75e9f363fb4e2e53bd09a76a.txt +244 -0
  265. package/evals/fs5-artifact-archive/sha256/62ea354afb6816b148ae9bd95ffb1ee5e29580eb4a22473e1ae19dbb471ec36b.txt +930 -0
  266. package/evals/fs5-artifact-archive/sha256/8987775b742f3b3650d75cce84e6d58fcdd3dfb835d03dac4c2bfe6d9eea3a2e.txt +903 -0
  267. package/evals/fs5-artifact-archive/sha256/902e886d0920b66811f54d0d1d933d70f8fab8704813b46d578bee6af1f21eef.txt +942 -0
  268. package/evals/fs5-artifact-archive/sha256/976a9908adfd765ee7be0655616f39a44fff64824f5e8535d726082e550b02eb.txt +910 -0
  269. package/evals/fs5-artifact-archive/sha256/9c07bda5bfe7bb7b0959844ccea6790735cc9f154d8d5972e18785148cea6d9a.txt +101 -0
  270. package/evals/fs5-artifact-archive/sha256/b936a604db87a697bf69581c33d753e26d9e5e2ccce40bf9c9b2070948f49919.txt +931 -0
  271. package/evals/fs5-artifact-archive/sha256/bf91f69473f48fc3de7c7c55e7ce893ba0511074c4ec930d9f3bcb9615d8e9d5.txt +950 -0
  272. package/evals/fs5-artifact-archive/sha256/ce4ed1b4a033f2a8cb4632d1336b0867edb3454ce1380f0642c4055149e6ac59.txt +784 -0
  273. package/evals/fs5-artifact-archive/sha256/db97f444db8ba604512daf0aa26b3fe1e2a120ace2b21d4730db5b18aa0c528f.txt +950 -0
  274. package/evals/fs5-causal-arm.v1.json +9 -5
  275. package/evals/fs5-pilot-protocol.v1.json +1 -1
  276. package/evals/fs5-pilot-protocol.v4.json +4 -4
  277. package/evals/fs5-pilot-protocol.v5.json +6 -5
  278. package/evals/harness-next/development-corpus.mjs +106 -0
  279. package/evals/harness-next/resource-budget-probe.mjs +38 -0
  280. package/evals/harness-next/run-calibration.mjs +83 -0
  281. package/evals/harness-next/run-resource-probe.mjs +55 -0
  282. package/evals/harness-next/selected-development-corpus.mjs +27 -0
  283. package/evals/harness-next.v1.json +51 -0
  284. package/evals/long-horizon-v1/README.md +19 -0
  285. package/evals/long-horizon-v1/runner.mjs +116 -48
  286. package/evals/long-horizon-v1/worker.mjs +77 -30
  287. package/evals/private-holdout-v1/CURRENT_BOUNDARY.md +53 -0
  288. package/evals/private-holdout-v1/README.md +5 -2
  289. package/evals/private-holdout-v1/public-exposure.v2.json +273 -0
  290. package/package.json +9 -4
  291. package/packages/piagent-core/README.md +2 -2
  292. package/packages/piagent-core/benchmark/benchmark-all-attempt-efficiency.js +55 -0
  293. package/packages/piagent-core/benchmark/benchmark-artifact-binding.js +49 -0
  294. package/packages/piagent-core/benchmark/benchmark-bootstrap.js +265 -14
  295. package/packages/piagent-core/benchmark/benchmark-budget-governor.js +271 -0
  296. package/packages/piagent-core/benchmark/benchmark-campaign.js +592 -0
  297. package/packages/piagent-core/benchmark/benchmark-candidate.js +8 -3
  298. package/packages/piagent-core/benchmark/benchmark-checkpoint.js +67 -0
  299. package/packages/piagent-core/benchmark/benchmark-claim-restrictions.js +269 -2
  300. package/packages/piagent-core/benchmark/benchmark-cli.js +120 -3
  301. package/packages/piagent-core/benchmark/benchmark-codex-events.js +235 -0
  302. package/packages/piagent-core/benchmark/benchmark-codex-outcome.js +20 -0
  303. package/packages/piagent-core/benchmark/benchmark-codex-relative-efficiency.js +2 -1
  304. package/packages/piagent-core/benchmark/benchmark-codex-rollout.js +521 -0
  305. package/packages/piagent-core/benchmark/benchmark-codex.js +104 -8
  306. package/packages/piagent-core/benchmark/benchmark-comparison.js +284 -1
  307. package/packages/piagent-core/benchmark/benchmark-core.js +107 -107
  308. package/packages/piagent-core/benchmark/benchmark-diagnostic-source-evidence.js +40 -0
  309. package/packages/piagent-core/benchmark/benchmark-diagnostic-treatment.js +104 -0
  310. package/packages/piagent-core/benchmark/benchmark-evaluator-v3.js +226 -0
  311. package/packages/piagent-core/benchmark/benchmark-execution-guard.js +23 -1
  312. package/packages/piagent-core/benchmark/benchmark-forensics.js +63 -50
  313. package/packages/piagent-core/benchmark/benchmark-goal-assessment.js +193 -0
  314. package/packages/piagent-core/benchmark/benchmark-goal-report.js +87 -0
  315. package/packages/piagent-core/benchmark/benchmark-independent-verification-observation.js +64 -0
  316. package/packages/piagent-core/benchmark/benchmark-matrix-summary.js +141 -0
  317. package/packages/piagent-core/benchmark/benchmark-matrix.js +1 -0
  318. package/packages/piagent-core/benchmark/benchmark-normalized-cost.js +62 -0
  319. package/packages/piagent-core/benchmark/benchmark-pi-home.js +1 -0
  320. package/packages/piagent-core/benchmark/benchmark-preflight.js +69 -8
  321. package/packages/piagent-core/benchmark/benchmark-process.js +23 -9
  322. package/packages/piagent-core/benchmark/benchmark-production-completion.js +84 -0
  323. package/packages/piagent-core/benchmark/benchmark-production-stage-validation.js +209 -0
  324. package/packages/piagent-core/benchmark/benchmark-provider-free-evidence.js +162 -45
  325. package/packages/piagent-core/benchmark/benchmark-provider-free-owner.js +24 -0
  326. package/packages/piagent-core/benchmark/benchmark-provider-wire.js +378 -0
  327. package/packages/piagent-core/benchmark/benchmark-record-validation.d.ts +2 -0
  328. package/packages/piagent-core/benchmark/benchmark-record-validation.js +269 -3
  329. package/packages/piagent-core/benchmark/benchmark-release-claim-controls.js +132 -0
  330. package/packages/piagent-core/benchmark/benchmark-report.js +79 -4
  331. package/packages/piagent-core/benchmark/benchmark-resume-recovery.js +280 -10
  332. package/packages/piagent-core/benchmark/benchmark-runner-policy.js +88 -1
  333. package/packages/piagent-core/benchmark/benchmark-runtime-identity.js +50 -1
  334. package/packages/piagent-core/benchmark/benchmark-runtime.js +102 -10
  335. package/packages/piagent-core/benchmark/benchmark-safety-evidence.js +74 -0
  336. package/packages/piagent-core/benchmark/benchmark-service-tier.js +189 -0
  337. package/packages/piagent-core/benchmark/benchmark-stage-diagnostic.js +144 -128
  338. package/packages/piagent-core/benchmark/benchmark-suite-identity.js +264 -1
  339. package/packages/piagent-core/benchmark/benchmark-suite-runtime.js +4 -0
  340. package/packages/piagent-core/benchmark/benchmark-suite.js +211 -4
  341. package/packages/piagent-core/benchmark/benchmark-summary-support.js +30 -2
  342. package/packages/piagent-core/benchmark/benchmark-timing-contract.js +189 -0
  343. package/packages/piagent-core/benchmark/benchmark-timing-diagnostics.js +110 -139
  344. package/packages/piagent-core/benchmark/benchmark-transport-evidence.js +203 -0
  345. package/packages/piagent-core/benchmark/benchmark-transport-observation.js +147 -0
  346. package/packages/piagent-core/benchmark/benchmark-tree-identity.js +2 -1
  347. package/packages/piagent-core/benchmark/benchmark-usage.js +395 -33
  348. package/packages/piagent-core/benchmark/benchmark-workflow.js +136 -38
  349. package/packages/piagent-core/benchmark/fs5-pilot-protocol.js +21 -2
  350. package/packages/piagent-core/capabilities/runtime-integrity.js +3 -0
  351. package/packages/piagent-core/extensions/acceptance-api-baseline.js +24 -0
  352. package/packages/piagent-core/extensions/acceptance-assessment.js +153 -0
  353. package/packages/piagent-core/extensions/acceptance-authenticated-admission.d.ts +41 -0
  354. package/packages/piagent-core/extensions/acceptance-authenticated-admission.js +120 -0
  355. package/packages/piagent-core/extensions/acceptance-behavior-proof.js +264 -70
  356. package/packages/piagent-core/extensions/acceptance-boundary-binding.js +31 -0
  357. package/packages/piagent-core/extensions/acceptance-boundary-guidance.js +214 -0
  358. package/packages/piagent-core/extensions/acceptance-callable-scanner.js +244 -0
  359. package/packages/piagent-core/extensions/acceptance-clause-group.js +45 -0
  360. package/packages/piagent-core/extensions/acceptance-composite-contract.js +334 -0
  361. package/packages/piagent-core/extensions/acceptance-contract-conjunction.js +78 -0
  362. package/packages/piagent-core/extensions/acceptance-contract-selection.js +161 -0
  363. package/packages/piagent-core/extensions/acceptance-contract-semantics.js +211 -211
  364. package/packages/piagent-core/extensions/acceptance-declared-api.js +126 -0
  365. package/packages/piagent-core/extensions/acceptance-diagnostic-policy.ts +14 -0
  366. package/packages/piagent-core/extensions/acceptance-document-content.js +73 -0
  367. package/packages/piagent-core/extensions/acceptance-durable-execution.d.ts +59 -0
  368. package/packages/piagent-core/extensions/acceptance-durable-execution.js +139 -0
  369. package/packages/piagent-core/extensions/acceptance-error-classes.js +1 -1
  370. package/packages/piagent-core/extensions/acceptance-evidence-store.js +223 -0
  371. package/packages/piagent-core/extensions/acceptance-executable-evidence.js +490 -88
  372. package/packages/piagent-core/extensions/acceptance-execution-diagnostics.js +34 -0
  373. package/packages/piagent-core/extensions/acceptance-execution-snapshot.js +174 -0
  374. package/packages/piagent-core/extensions/acceptance-executor/.dockerignore +21 -0
  375. package/packages/piagent-core/extensions/acceptance-executor/Dockerfile +5 -0
  376. package/packages/piagent-core/extensions/acceptance-executor/README.md +103 -0
  377. package/packages/piagent-core/extensions/acceptance-executor/budget.mjs +54 -0
  378. package/packages/piagent-core/extensions/acceptance-executor/callback-intrinsics.mjs +126 -0
  379. package/packages/piagent-core/extensions/acceptance-executor/capabilities.mjs +127 -0
  380. package/packages/piagent-core/extensions/acceptance-executor/guest.mjs +285 -0
  381. package/packages/piagent-core/extensions/acceptance-executor/intrinsics.mjs +133 -0
  382. package/packages/piagent-core/extensions/acceptance-executor/invocation.mjs +39 -0
  383. package/packages/piagent-core/extensions/acceptance-executor/jobs.mjs +29 -0
  384. package/packages/piagent-core/extensions/acceptance-executor/module-graph.mjs +70 -0
  385. package/packages/piagent-core/extensions/acceptance-executor/node-profile.mjs +398 -0
  386. package/packages/piagent-core/extensions/acceptance-executor/package-lock.json +40 -0
  387. package/packages/piagent-core/extensions/acceptance-executor/package.json +10 -0
  388. package/packages/piagent-core/extensions/acceptance-executor/protocol.mjs +248 -0
  389. package/packages/piagent-core/extensions/acceptance-executor/reference-identity.mjs +61 -0
  390. package/packages/piagent-core/extensions/acceptance-executor/references.mjs +14 -0
  391. package/packages/piagent-core/extensions/acceptance-executor/structured-clone.mjs +53 -0
  392. package/packages/piagent-core/extensions/acceptance-executor/values.mjs +97 -0
  393. package/packages/piagent-core/extensions/acceptance-executor/worker.mjs +75 -0
  394. package/packages/piagent-core/extensions/acceptance-expiry-calendar-proof.js +162 -0
  395. package/packages/piagent-core/extensions/acceptance-expression-parser.js +155 -0
  396. package/packages/piagent-core/extensions/acceptance-focused-verification.js +40 -0
  397. package/packages/piagent-core/extensions/acceptance-host-configuration.js +337 -0
  398. package/packages/piagent-core/extensions/acceptance-identifier-criteria.js +25 -0
  399. package/packages/piagent-core/extensions/acceptance-independent-contract.js +209 -0
  400. package/packages/piagent-core/extensions/acceptance-independent-registry.js +106 -0
  401. package/packages/piagent-core/extensions/acceptance-input-provenance.js +40 -0
  402. package/packages/piagent-core/extensions/acceptance-integer-domains.js +322 -0
  403. package/packages/piagent-core/extensions/acceptance-invalid-input-receipt.js +20 -0
  404. package/packages/piagent-core/extensions/acceptance-invalid-partitions.js +26 -0
  405. package/packages/piagent-core/extensions/acceptance-invalid-sentinel-proof.js +477 -0
  406. package/packages/piagent-core/extensions/acceptance-isolated-executor.js +254 -0
  407. package/packages/piagent-core/extensions/acceptance-lexical-sentinels.js +130 -0
  408. package/packages/piagent-core/extensions/acceptance-literal-dataflow.js +735 -0
  409. package/packages/piagent-core/extensions/acceptance-local-binding.js +106 -0
  410. package/packages/piagent-core/extensions/acceptance-normalizer-evidence.js +719 -0
  411. package/packages/piagent-core/extensions/acceptance-obligations.js +75 -0
  412. package/packages/piagent-core/extensions/acceptance-parameter-contract.js +756 -0
  413. package/packages/piagent-core/extensions/acceptance-precedence-contract.js +572 -0
  414. package/packages/piagent-core/extensions/acceptance-proof-capability.js +26 -0
  415. package/packages/piagent-core/extensions/acceptance-receipt.js +139 -152
  416. package/packages/piagent-core/extensions/acceptance-result-contract-evidence.js +159 -0
  417. package/packages/piagent-core/extensions/acceptance-source-origin.js +214 -0
  418. package/packages/piagent-core/extensions/acceptance-state-machine-evidence.js +64 -8
  419. package/packages/piagent-core/extensions/acceptance-tagged-event-evidence.js +685 -0
  420. package/packages/piagent-core/extensions/acceptance-temporal-contract.js +756 -0
  421. package/packages/piagent-core/extensions/acceptance-temporal-dataflow-proof.js +618 -0
  422. package/packages/piagent-core/extensions/acceptance-test-binding-evidence.js +20 -2
  423. package/packages/piagent-core/extensions/acceptance-test-bindings.js +86 -0
  424. package/packages/piagent-core/extensions/acceptance-tuple-shapes.js +12 -0
  425. package/packages/piagent-core/extensions/context-engine.js +11 -6
  426. package/packages/piagent-core/extensions/criterion-context-pack.js +96 -4
  427. package/packages/piagent-core/extensions/failure-types.ts +2 -2
  428. package/packages/piagent-core/extensions/guard-types.ts +5 -1
  429. package/packages/piagent-core/extensions/piagent-guard.ts +197 -155
  430. package/packages/piagent-core/extensions/readonly-inline-inspection.ts +378 -0
  431. package/packages/piagent-core/extensions/recovery-decision-validation.ts +92 -0
  432. package/packages/piagent-core/extensions/shell-write-targets.js +15 -14
  433. package/packages/piagent-core/extensions/task-contract-view.js +4 -4
  434. package/packages/piagent-core/extensions/task-digest-migration.js +2 -2
  435. package/packages/piagent-core/extensions/task-journal.js +48 -3
  436. package/packages/piagent-core/extensions/task-runtime-audit.js +8 -2
  437. package/packages/piagent-core/extensions/task-state.js +74 -38
  438. package/packages/piagent-core/extensions/task-terminal-disposition.js +10 -0
  439. package/packages/piagent-core/extensions/trajectory-contract.ts +5 -0
  440. package/packages/piagent-core/extensions/verification-intelligence.js +60 -8
  441. package/packages/piagent-core/extensions/workflow-catalog.ts +98 -0
  442. package/packages/piagent-core/extensions/workspace-revision.js +48 -0
  443. package/packages/piagent-core/extensions/workspace-verification-snapshot.js +13 -0
  444. package/packages/piagent-core/package.json +3 -3
  445. package/packages/piagent-core/policies/base-policy.json +1 -0
  446. package/packages/piagent-core/runtime/context/adaptive-planner.ts +7 -3
  447. package/packages/piagent-core/runtime/hooks/agent-start-hook.ts +60 -59
  448. package/packages/piagent-core/runtime/hooks/agent-start-types.ts +48 -0
  449. package/packages/piagent-core/runtime/hooks/completion-hook.ts +76 -83
  450. package/packages/piagent-core/runtime/hooks/input-hook.ts +92 -7
  451. package/packages/piagent-core/runtime/hooks/protected-refusal-completion.ts +86 -0
  452. package/packages/piagent-core/runtime/hooks/session-hooks.ts +5 -2
  453. package/packages/piagent-core/runtime/hooks/session-start-hook.ts +50 -18
  454. package/packages/piagent-core/runtime/hooks/tool-result-hook.ts +53 -20
  455. package/packages/piagent-core/runtime/hooks/tool-result-metadata.ts +9 -0
  456. package/packages/piagent-core/runtime/hooks/tool-result-navigation.ts +36 -0
  457. package/packages/piagent-core/runtime/hooks/tool-result-retrieval.ts +42 -0
  458. package/packages/piagent-core/runtime/input/chat-images.ts +1 -1
  459. package/packages/piagent-core/runtime/inspection/activity-event-adapter.ts +1 -1
  460. package/packages/piagent-core/runtime/inspection/same-process-bridge-proof.ts +1 -1
  461. package/packages/piagent-core/runtime/inspection/task-handoff-history.ts +2 -2
  462. package/packages/piagent-core/runtime/inspection/tool-failure-classification.ts +49 -8
  463. package/packages/piagent-core/runtime/inspection/webui-snapshot.ts +61 -15
  464. package/packages/piagent-core/runtime/inspection/workspace-file-reader.ts +2 -132
  465. package/packages/piagent-core/runtime/model/model-route-policy.ts +33 -13
  466. package/packages/piagent-core/runtime/model/model-route-types.ts +10 -6
  467. package/packages/piagent-core/runtime/model/provider-wire-fingerprint.ts +20 -0
  468. package/packages/piagent-core/runtime/model/service-tier-runtime.ts +242 -0
  469. package/packages/piagent-core/runtime/policy/source-worktree-transaction.ts +75 -14
  470. package/packages/piagent-core/runtime/product/activity-inspector.ts +6 -3
  471. package/packages/piagent-core/runtime/product/edit-verifier-timing.ts +26 -0
  472. package/packages/piagent-core/runtime/product/efficiency-metrics.ts +12 -7
  473. package/packages/piagent-core/runtime/product/operator-projections.ts +8 -3
  474. package/packages/piagent-core/runtime/product/task-usage-hooks.ts +78 -0
  475. package/packages/piagent-core/runtime/product/task-usage.ts +104 -0
  476. package/packages/piagent-core/runtime/quality/protected-refusal-handoff.ts +35 -0
  477. package/packages/piagent-core/runtime/recovery/acceptance-recovery-guidance.ts +21 -0
  478. package/packages/piagent-core/runtime/recovery/continuation-budget.ts +11 -2
  479. package/packages/piagent-core/runtime/recovery/diagnostic-delivery.ts +61 -0
  480. package/packages/piagent-core/runtime/recovery/handoff-projection.ts +192 -57
  481. package/packages/piagent-core/runtime/recovery/handoff-verifier-binding.ts +24 -0
  482. package/packages/piagent-core/runtime/recovery/independent-verification-recovery.ts +79 -0
  483. package/packages/piagent-core/runtime/recovery/recovery-policy.ts +27 -39
  484. package/packages/piagent-core/runtime/recovery/resume-state.ts +8 -5
  485. package/packages/piagent-core/runtime/registration/activity-inspector-command.ts +2 -1
  486. package/packages/piagent-core/runtime/registration/context-commands.ts +12 -8
  487. package/packages/piagent-core/runtime/registration/operator-catalogs.ts +4 -9
  488. package/packages/piagent-core/runtime/registration/policy-tools.ts +5 -3
  489. package/packages/piagent-core/runtime/registration/session-commands.ts +9 -7
  490. package/packages/piagent-core/runtime/registration/session-wait-tool.ts +54 -0
  491. package/packages/piagent-core/runtime/registration/task-completion-tools.ts +27 -11
  492. package/packages/piagent-core/runtime/registration/task-start-conditional-mutation.ts +45 -0
  493. package/packages/piagent-core/runtime/registration/task-start-guidance.ts +5 -2
  494. package/packages/piagent-core/runtime/registration/task-start-tool.ts +23 -23
  495. package/packages/piagent-core/runtime/registration/workflow-commands.ts +64 -93
  496. package/packages/piagent-core/runtime/session/completion-signals.ts +23 -0
  497. package/packages/piagent-core/runtime/session/message-signals.ts +6 -22
  498. package/packages/piagent-core/runtime/session/retrieval-evidence-runtime.ts +188 -0
  499. package/packages/piagent-core/runtime/session/runtime-state.ts +29 -35
  500. package/packages/piagent-core/runtime/session/system-prompt.ts +3 -3
  501. package/packages/piagent-core/runtime/session/uncertain-send-continuation.ts +231 -0
  502. package/packages/piagent-core/runtime/session/usage.ts +4 -3
  503. package/packages/piagent-core/runtime/tools/apply-patch-tool.ts +6 -6
  504. package/packages/piagent-core/runtime/tools/phase-tool-runtime.ts +1 -1
  505. package/packages/piagent-core/runtime/tools/phase-tools.ts +3 -2
  506. package/packages/piagent-core/runtime/tools/session-wait.ts +42 -0
  507. package/packages/piagent-core/runtime/tools/tool-groups.ts +10 -3
  508. package/packages/piagent-core/runtime/trajectory/trajectory-runtime.ts +192 -5
  509. package/packages/piagent-core/runtime/trajectory/trajectory-types.ts +3 -2
  510. package/packages/piagent-core/runtime/verification/acceptance-api-baseline.js +488 -0
  511. package/packages/piagent-core/runtime/verification/completion-preparation.ts +22 -0
  512. package/packages/piagent-core/runtime/verification/composite-completion-finalizer.ts +105 -0
  513. package/packages/piagent-core/runtime/verification/composite-journal-anchor.ts +181 -0
  514. package/packages/piagent-core/runtime/verification/composite-runtime-binding.ts +76 -0
  515. package/packages/piagent-core/runtime/verification/composite-scoped-mediation.ts +318 -0
  516. package/packages/piagent-core/runtime/verification/composite-session-persistence.ts +175 -0
  517. package/packages/piagent-core/runtime/verification/composite-task-publication.ts +273 -0
  518. package/packages/piagent-core/runtime/verification/exact-verifier-reuse.ts +11 -11
  519. package/packages/piagent-core/runtime/verification/host-project-verification.ts +71 -0
  520. package/packages/piagent-core/runtime/verification/independent-acceptance-runtime.ts +500 -0
  521. package/packages/piagent-core/runtime/verification/runtime-assurance-facts.ts +500 -0
  522. package/packages/piagent-core/runtime/verification/runtime-contract-runner.ts +107 -0
  523. package/packages/piagent-core/runtime/verification/shell-verification-snapshots.ts +56 -0
  524. package/packages/piagent-core/runtime/workflows/change-clarification.ts +61 -0
  525. package/packages/piagent-core/runtime/workflows/input-routing.ts +21 -14
  526. package/packages/piagent-core/runtime/workflows/runtime-intake-compaction.ts +44 -7
  527. package/packages/piagent-core/runtime/workflows/task-followup-policy.ts +163 -0
  528. package/packages/piagent-core/runtime/workflows/task-intake.ts +221 -242
  529. package/packages/piagent-core/runtime/workflows/task-repair-intent.ts +67 -0
  530. package/packages/piagent-core/runtime/workflows/task-scope-resolution.ts +83 -0
  531. package/packages/piagent-core/runtime/workflows/webui-runtime-command.ts +5 -2
  532. package/packages/piagent-core/runtime/workflows/webui-workflow.ts +39 -32
  533. package/packages/piagent-core/runtime/workflows/workflow-follow-up.ts +33 -0
  534. package/packages/piagent-core/security/workspace-file-reader.ts +132 -0
  535. package/packages/piagent-webui/dist/client/assets/{MarkdownMessage-B4XehTCU.js → MarkdownMessage-DMU7Xe_O.js} +1 -1
  536. package/packages/piagent-webui/dist/client/assets/index-Cui9AAV_.js +176 -0
  537. package/packages/piagent-webui/dist/client/assets/{index-BV-_03yl.css → index-DVahUVWy.css} +1 -1
  538. package/packages/piagent-webui/dist/client/index.html +2 -2
  539. package/packages/piagent-webui/extension/dispatch-user-entry.ts +13 -0
  540. package/packages/piagent-webui/extension/piagent-webui.ts +10 -2
  541. package/packages/piagent-webui/extension/review-controller.ts +29 -6
  542. package/packages/piagent-webui/extension/same-session-bridge.ts +6 -7
  543. package/packages/piagent-webui/extension/session-stream-adapter.ts +60 -11
  544. package/packages/piagent-webui/extension/source-mutation-controller.ts +29 -3
  545. package/packages/piagent-webui/extension/source-open-controller.ts +29 -7
  546. package/packages/piagent-webui/extension/source-revert-controller.ts +26 -3
  547. package/packages/piagent-webui/gateway/gateway-events.ts +22 -5
  548. package/packages/piagent-webui/gateway/gateway-service.ts +7 -2
  549. package/packages/piagent-webui/gateway/gateway-session-stream.ts +141 -19
  550. package/packages/piagent-webui/gateway/rpc-ui-context.ts +34 -9
  551. package/packages/piagent-webui/gateway/runtime-command-controller.ts +46 -6
  552. package/packages/piagent-webui/gateway/runtime-session-controls.ts +17 -2
  553. package/packages/piagent-webui/gateway/session-catalog.ts +9 -3
  554. package/packages/piagent-webui/gateway/session-command-controller.ts +29 -9
  555. package/packages/piagent-webui/gateway/session-effective-options.ts +2 -9
  556. package/packages/piagent-webui/gateway/session-inspection-registry.ts +14 -6
  557. package/packages/piagent-webui/gateway/session-operation-settlement.ts +28 -0
  558. package/packages/piagent-webui/gateway/session-prompt-dispatch.ts +37 -0
  559. package/packages/piagent-webui/gateway/session-runtime-close.ts +36 -0
  560. package/packages/piagent-webui/gateway/session-runtime-factory.ts +183 -6
  561. package/packages/piagent-webui/gateway/session-runtime-ownership.ts +48 -0
  562. package/packages/piagent-webui/gateway/session-runtime-state.ts +24 -0
  563. package/packages/piagent-webui/gateway/session-runtime-supervisor.ts +114 -114
  564. package/packages/piagent-webui/server/core-inspection-provider.ts +73 -14
  565. package/packages/piagent-webui/server/loopback-server.ts +9 -7
  566. package/packages/piagent-webui/server/terminal-delivery-receipt.ts +144 -0
  567. package/packages/piagent-webui/server/transcript-projection.ts +65 -12
  568. package/packages/piagent-webui/shared/message-correlation.ts +25 -0
  569. package/schemas/approved-host-contracts.schema.json +973 -0
  570. package/schemas/benchmark-attempt-outcome.schema.json +303 -0
  571. package/schemas/benchmark-independent-verification-plan.schema.json +34 -0
  572. package/schemas/composite-criterion.schema.json +788 -0
  573. package/schemas/contract-family-library.schema.json +28 -0
  574. package/schemas/contract-selection-recipe.schema.json +31 -0
  575. package/schemas/failure-evidence.schema.json +2 -2
  576. package/schemas/helper-request.schema.json +16 -4
  577. package/schemas/host-contract-plan.schema.json +25 -0
  578. package/schemas/piagent-webui/gateway-protocol-v1.schema.json +16 -2
  579. package/schemas/piagent-webui/runtime-command-v1.schema.json +26 -3
  580. package/schemas/piagent-webui/runtime-event-v2.schema.json +32 -1
  581. package/schemas/piagent-webui/session-live-state-v1.schema.json +2 -0
  582. package/schemas/piagent-webui/snapshot-v1.schema.json +3 -0
  583. package/schemas/piagent-webui/source-change-v1.schema.json +12 -0
  584. package/schemas/piagent-webui/transcript-v1.schema.json +2 -1
  585. package/schemas/public-contracts/codex-mcp-metadata-v1.schema.json +206 -0
  586. package/schemas/public-contracts/codex-mcp-metadata-v2.schema.json +228 -0
  587. package/schemas/public-contracts/codex-mcp-metadata-v3.schema.json +233 -0
  588. package/schemas/public-contracts/revocation-v1.schema.json +87 -0
  589. package/schemas/public-contracts/subscription-contract-v1.schema.json +76 -0
  590. package/schemas/scoped-project-verification-receipt-v2.schema.json +83 -0
  591. package/schemas/scoped-project-verification-receipt-v3.schema.json +295 -0
  592. package/schemas/scoped-verification-receipt-v1.schema.json +76 -0
  593. package/schemas/task-contract.schema.json +30 -0
  594. package/scripts/approve-independent-verification.mjs +57 -0
  595. package/scripts/benchmark-arm-observer.mjs +320 -0
  596. package/scripts/benchmark-budget-ipc.mjs +34 -0
  597. package/scripts/benchmark-budget-launcher.mjs +91 -0
  598. package/scripts/benchmark-budget-processes.mjs +133 -0
  599. package/scripts/benchmark-budget-publication.mjs +228 -0
  600. package/scripts/benchmark-budget-runtime.mjs +136 -0
  601. package/scripts/benchmark-candidate-ablation.mjs +265 -0
  602. package/scripts/benchmark-codex-journey.mjs +406 -0
  603. package/scripts/benchmark-independent-verification.mjs +628 -0
  604. package/scripts/benchmark-journey-outcome.mjs +92 -0
  605. package/scripts/benchmark-production-v3-human-review.mjs +192 -0
  606. package/scripts/benchmark-public-input-catalog.mjs +158 -0
  607. package/scripts/benchmark-registered-plan-author.mjs +355 -0
  608. package/scripts/benchmark-registered-plan-recipe-support.mjs +85 -0
  609. package/scripts/benchmark-registered-plan-recipes-backend.mjs +165 -0
  610. package/scripts/benchmark-registered-plan-recipes-data.mjs +164 -0
  611. package/scripts/benchmark-registered-plan-recipes-platform.mjs +165 -0
  612. package/scripts/benchmark-runner-completion.mjs +133 -0
  613. package/scripts/benchmark-runner-configuration.mjs +159 -0
  614. package/scripts/benchmark-runner-core.mjs +217 -388
  615. package/scripts/benchmark-runner-finalization.mjs +140 -27
  616. package/scripts/benchmark-runner-provider-boundary.mjs +44 -0
  617. package/scripts/benchmark-runner-schedule.mjs +256 -0
  618. package/scripts/benchmark-runner-support.mjs +136 -4
  619. package/scripts/benchmark-runner.mjs +95 -18
  620. package/scripts/benchmark-scoped-broker-custody.mjs +483 -0
  621. package/scripts/benchmark-scoped-docs-verifier.mjs +203 -0
  622. package/scripts/benchmark-scoped-frozen-qualification.mjs +676 -0
  623. package/scripts/benchmark-scoped-pi-router.mjs +196 -0
  624. package/scripts/benchmark-scoped-project-verification-receipt.mjs +49 -0
  625. package/scripts/benchmark-scoped-project-verifier.mjs +461 -0
  626. package/scripts/benchmark-scoped-session-custody.mjs +599 -0
  627. package/scripts/benchmark-scoped-session-factory.mjs +342 -0
  628. package/scripts/benchmark-scoped-tool-broker.mjs +523 -0
  629. package/scripts/benchmark-scoped-verification-supervisor.mjs +773 -0
  630. package/scripts/benchmark-session-evaluator.mjs +169 -0
  631. package/scripts/benchmark-session-provider-boundary.mjs +62 -0
  632. package/scripts/benchmark-session-usage.mjs +28 -0
  633. package/scripts/benchmark-session.mjs +343 -50
  634. package/scripts/benchmark-webui-journey.mjs +678 -0
  635. package/scripts/check-public-wording.mjs +46 -0
  636. package/scripts/configure-model-scope.sh +6 -2
  637. package/scripts/fs4-readiness-evaluation.mjs +7 -1
  638. package/scripts/install-global.sh +2 -2
  639. package/scripts/model-route-evaluation-core.ts +1 -0
  640. package/scripts/phase-tools-evaluation.mjs +1 -0
  641. package/scripts/pi-auto.sh +7 -1
  642. package/scripts/pi-model-route.mjs +1 -1
  643. package/scripts/pi-usage-history.mjs +201 -11
  644. package/scripts/piagent-cli.mjs +8 -0
  645. package/scripts/private-holdout-readiness.mjs +7 -1
  646. package/scripts/public-evaluation-exposure.mjs +140 -0
  647. package/scripts/select-independent-verification.mjs +62 -0
  648. package/scripts/setup.sh +2 -2
  649. package/scripts/typescript-loader.mjs +135 -1
  650. package/scripts/update-global.mjs +6 -7
  651. package/scripts/verify-local.sh +37 -56
  652. package/scripts/verify-release-identity.mjs +5 -3
  653. package/templates/global/settings.json +5 -1
  654. package/packages/piagent-webui/dist/client/assets/index-CgOEyRPG.js +0 -176
@@ -1,45 +1,38 @@
1
+ import { closeSessionRuntimes } from "./session-runtime-close.ts";
1
2
  import { createHmac, randomBytes } from "node:crypto";
2
3
  import { webUiModelRef, webUiTaskRevision } from "../../piagent-core/runtime/inspection/webui-snapshot.ts";
3
4
  import { activeSessionTask } from "../../piagent-core/extensions/task-state.js";
5
+ import { createSessionOperationSettlement } from "./session-operation-settlement.ts";
4
6
  import { inspectTaskControlState } from "../../piagent-core/runtime/inspection/task-control-journal.ts";
5
7
  import { piApprovalBroker, type ApprovalAuthority, type ApprovalBrokerEvent } from "../../piagent-core/runtime/inspection/approval-broker.ts";
6
- import type { SessionOwnerProjection, PiSessionInfo } from "./session-catalog.ts";
7
- import { isUserConversationSession, projectRefForCwd, sessionRefForPath } from "./session-catalog.ts";
8
+ import { isUserConversationSession, projectRefForCwd, sessionRefForPath, type SessionOwnerProjection, type PiSessionInfo } from "./session-catalog.ts";
8
9
  import { SessionLeaseStore, type SessionLeaseSnapshot } from "./session-lease-store.ts";
9
10
  import { GatewayEventStore } from "./gateway-events.ts";
10
11
  import { GatewaySessionStream } from "./gateway-session-stream.ts";
11
12
  import { executePermissionCommand, executeRuntimeCommand } from "./runtime-session-controls.ts";
12
- import { configureSessionOptions, effectiveModelRef, effectiveThinkingLevel, type EffectiveSessionOptions } from "./session-effective-options.ts";
13
- import { waitForOperationStart } from "./session-operation-start.ts";
14
- import { armSessionOperationWatchdog, bestEffortUnsubscribe, boundedResult, sessionOperationDeadlinePolicy, SessionOperationWatchdog, terminateWatchedSessionOperation,
15
- type SessionOperationDeadlinePolicy, type SessionOperationWatchdogOptions } from "./session-operation-watchdog.ts";
16
- import { createProductionRuntimeFactory, type RuntimeFactory, type RuntimeHandle } from "./session-runtime-factory.ts";
13
+ import { inspectEffectiveSessionOptions, effectiveModelRef, effectiveThinkingLevel, type EffectiveSessionOptions } from "./session-effective-options.ts";
14
+ import { launchSessionPrompt, type LaunchedSessionPrompt, type SessionSendResult } from "./session-prompt-dispatch.ts";
15
+ import { WEBUI_MESSAGE_CORRELATION_ENTRY_TYPE } from "../shared/message-correlation.ts";
16
+ import { terminalDeliveryRequest, terminalDeliveryReceiptCommitter, terminalDeliverySessionEntries } from "../server/terminal-delivery-receipt.ts";
17
+ import { armSessionOperationWatchdog, bestEffortUnsubscribe, boundedResult, sessionOperationDeadlinePolicy, SessionOperationWatchdog, terminateWatchedSessionOperation, type SessionOperationDeadlinePolicy, type SessionOperationWatchdogOptions } from "./session-operation-watchdog.ts";
18
+ import { createProductionRuntimeFactory, type RuntimeFactory, type ScopedBrokerRouter } from "./session-runtime-factory.ts";
19
+ import { projectSessionRuntimeOwnership } from "./session-runtime-ownership.ts";
17
20
  const MAX_WARM_RUNTIMES = 10;
18
- type ActiveRuntime = { runtime: RuntimeHandle; lease: SessionLeaseSnapshot; info: PiSessionInfo; operationRef: string | null;
19
- stream: GatewaySessionStream | null; unsubscribe: (() => void) | null; completion: Promise<void> | null; settling: boolean; approvalWaiting: boolean;
20
- unbindApproval: (() => void) | null; unsubscribeApproval: (() => void) | null; sessionManager: any | null;
21
- watchdog: SessionOperationWatchdog | null; lastSessionRevision: string | null };
22
- type Projection = { sessionRevision: string; liveState: "offline" | "idle" | "running" | "paused" | "waiting-approval" | "uncertain" };
23
- type RuntimeCommandResult = Awaited<ReturnType<typeof executeRuntimeCommand>>;
21
+ import type { ActiveRuntime } from "./session-runtime-state.ts";
22
+ type Projection = { sessionRevision: string; liveState: "offline" | "idle" | "running" | "paused" | "waiting-approval" | "uncertain" }; type RuntimeCommandResult = Awaited<ReturnType<typeof executeRuntimeCommand>>;
24
23
  export type { EffectiveSessionOptions } from "./session-effective-options.ts";
25
24
  export type SessionCreateResult = { sessionRef: string; effectiveOptions: EffectiveSessionOptions };
26
25
  export type CurrentOperationProjection = { operationRef: string; state: "running" | "waiting-approval" | "settling";
27
- abortable: boolean };
26
+ abortable: boolean; messageRequestId?: string };
28
27
  export class SessionRuntimeSupervisor {
29
- readonly #gatewayInstanceRef: string;
30
- readonly #key: Buffer;
31
- readonly #leases: SessionLeaseStore;
32
- readonly #listSessions: () => Promise<PiSessionInfo[]>;
33
- readonly #runtimeFactory: RuntimeFactory;
34
- readonly #events: GatewayEventStore;
35
- readonly #host: any | null;
36
- readonly #operationDeadlinePolicy: SessionOperationDeadlinePolicy;
28
+ readonly #gatewayInstanceRef: string; readonly #key: Buffer;
29
+ readonly #leases: SessionLeaseStore; readonly #listSessions: () => Promise<PiSessionInfo[]>;
30
+ readonly #runtimeFactory: RuntimeFactory; readonly #events: GatewayEventStore;
31
+ readonly #host: any | null; readonly #operationDeadlinePolicy: SessionOperationDeadlinePolicy;
37
32
  readonly #resolveProject: ((projectRef: string) => string | null) | null;
38
- readonly #active = new Map<string, ActiveRuntime>();
39
- readonly #opening = new Map<string, Promise<SessionLeaseSnapshot>>();
40
- readonly #created = new Map<string, PiSessionInfo>();
41
- #closed = false;
42
- #readProjection: ((sessionRef: string) => Promise<Projection>) | null = null;
33
+ readonly #settleOperation: ReturnType<typeof createSessionOperationSettlement>;
34
+ readonly #active = new Map<string, ActiveRuntime>(); readonly #opening = new Map<string, Promise<SessionLeaseSnapshot>>();
35
+ readonly #created = new Map<string, PiSessionInfo>(); #closed = false; #closing: Promise<void> | null = null; #readProjection: ((sessionRef: string) => Promise<Projection>) | null = null;
43
36
  constructor(options: {
44
37
  gatewayInstanceRef: string;
45
38
  key: Buffer;
@@ -50,9 +43,11 @@ export class SessionRuntimeSupervisor {
50
43
  agentDir?: string;
51
44
  packageRoot?: string;
52
45
  modelRuntime?: any;
46
+ scopedBrokerRouter?: ScopedBrokerRouter;
53
47
  events?: GatewayEventStore;
54
48
  operationWatchdog?: SessionOperationWatchdogOptions;
55
49
  resolveProject?(projectRef: string): string | null;
50
+ compositeSettlementEvidence?(): unknown | Promise<unknown>;
56
51
  }) {
57
52
  this.#gatewayInstanceRef = options.gatewayInstanceRef;
58
53
  this.#key = options.key;
@@ -62,21 +57,20 @@ export class SessionRuntimeSupervisor {
62
57
  this.#host = options.host ?? null;
63
58
  this.#operationDeadlinePolicy = sessionOperationDeadlinePolicy(options.operationWatchdog);
64
59
  this.#resolveProject = options.resolveProject ?? null;
60
+ this.#settleOperation = createSessionOperationSettlement(options);
65
61
  if (options.runtimeFactory) this.#runtimeFactory = options.runtimeFactory;
66
62
  else {
67
63
  if (!options.host || !options.agentDir || !options.packageRoot) throw new Error("session-runtime-factory-unavailable");
68
64
  this.#runtimeFactory = createProductionRuntimeFactory({ host: options.host, agentDir: options.agentDir,
69
- packageRoot: options.packageRoot, modelRuntime: options.modelRuntime });
65
+ packageRoot: options.packageRoot, modelRuntime: options.modelRuntime,
66
+ scopedBrokerRouter: options.scopedBrokerRouter });
70
67
  }
71
68
  }
72
- get activeCount(): number { return this.#active.size; }
73
- setProjectionReader(reader: (sessionRef: string) => Promise<Projection>): void { this.#readProjection = reader; }
69
+ get activeCount(): number { return this.#active.size; } setProjectionReader(reader: (sessionRef: string) => Promise<Projection>): void { this.#readProjection = reader; }
74
70
  async listSessions(): Promise<PiSessionInfo[]> {
75
71
  const persisted = (await this.#listSessions()).filter(isUserConversationSession);
76
72
  const paths = new Set(persisted.map((info) => info.path));
77
- for (const [sessionRef, info] of this.#created) {
78
- if (paths.has(info.path)) this.#created.delete(sessionRef);
79
- }
73
+ for (const [sessionRef, info] of this.#created) if (paths.has(info.path)) this.#created.delete(sessionRef);
80
74
  return [...persisted, ...[...this.#created.values()].filter((info) => !paths.has(info.path))];
81
75
  }
82
76
  async create(projectRef: string, placeRef: string, modelRef: string | null, thinkingLevel: string): Promise<string> {
@@ -100,7 +94,7 @@ export class SessionRuntimeSupervisor {
100
94
  const sessionRef = sessionRefForPath(this.#key, sessionFile);
101
95
  // Retain identity before fallible runtime work so create receipts never point at an orphan.
102
96
  this.#created.set(sessionRef, created);
103
- try { await this.#activate(sessionRef, created, manager); }
97
+ try { await this.#activate(sessionRef, created, manager, { modelRef, thinkingLevel }); }
104
98
  catch {
105
99
  return { sessionRef, effectiveOptions: { state: "unknown", modelRef: null, thinkingLevel: null,
106
100
  reasonCode: "session-runtime-open-failed" } };
@@ -108,7 +102,7 @@ export class SessionRuntimeSupervisor {
108
102
  const active = this.#active.get(sessionRef), session = active?.runtime.session;
109
103
  if (!session) return { sessionRef, effectiveOptions: { state: "unknown", modelRef: null, thinkingLevel: null,
110
104
  reasonCode: "session-runtime-unavailable" } };
111
- return { sessionRef, effectiveOptions: await configureSessionOptions(session, modelRef, thinkingLevel) };
105
+ return { sessionRef, effectiveOptions: inspectEffectiveSessionOptions(session, modelRef, thinkingLevel) };
112
106
  }
113
107
  liveSessionManager(sessionRef: string): any | null { return this.#active.get(sessionRef)?.sessionManager ?? null; }
114
108
  async acquire(sessionRef: string): Promise<SessionLeaseSnapshot> {
@@ -128,7 +122,8 @@ export class SessionRuntimeSupervisor {
128
122
  if (found.length !== 1) throw new Error(found.length ? "session-ref-ambiguous" : "session-not-found");
129
123
  return await this.#activate(sessionRef, found[0]!);
130
124
  }
131
- async #activate(sessionRef: string, info: PiSessionInfo, sessionManager?: any): Promise<SessionLeaseSnapshot> {
125
+ async #activate(sessionRef: string, info: PiSessionInfo, sessionManager?: any,
126
+ initialOptions?: { modelRef: string | null; thinkingLevel: string }): Promise<SessionLeaseSnapshot> {
132
127
  if (this.#active.has(sessionRef)) throw new Error("session-owner-conflict");
133
128
  const runtimeInstanceRef = `runtime_${randomBytes(24).toString("base64url")}`;
134
129
  const prior = this.#leases.inspect(sessionRef);
@@ -137,14 +132,15 @@ export class SessionRuntimeSupervisor {
137
132
  }
138
133
  const lease = this.#leases.acquire(sessionRef, this.#gatewayInstanceRef, runtimeInstanceRef);
139
134
  try {
140
- const runtime = await this.#runtimeFactory(info, runtimeInstanceRef, sessionManager);
135
+ const runtime = await this.#runtimeFactory(info, runtimeInstanceRef, sessionManager, initialOptions);
141
136
  const current = this.#leases.inspect(sessionRef);
142
137
  if (current.state !== "gateway-owned" || current.ownerEpoch !== lease.ownerEpoch
143
138
  || current.gatewayInstanceRef !== this.#gatewayInstanceRef || current.runtimeInstanceRef !== runtimeInstanceRef) {
144
139
  await runtime.dispose().catch(() => undefined);
145
140
  throw new Error("session-owner-continuity-lost");
146
141
  }
147
- const active: ActiveRuntime = { runtime, lease: current, info, operationRef: null, stream: null, unsubscribe: null, completion: null,
142
+ const active: ActiveRuntime = { runtime, lease: current, info, operationRef: null, messageRequestId: null, cancelWire: null,
143
+ stream: null, unsubscribe: null, completion: null,
148
144
  settling: false, approvalWaiting: false, unbindApproval: null, unsubscribeApproval: null,
149
145
  sessionManager: sessionManager ?? runtime.session?.sessionManager ?? null, watchdog: null, lastSessionRevision: null };
150
146
  this.#active.set(sessionRef, active);
@@ -191,7 +187,7 @@ export class SessionRuntimeSupervisor {
191
187
  if (!active?.operationRef) return null;
192
188
  return { operationRef: active.operationRef,
193
189
  state: active.settling ? "settling" : active.approvalWaiting ? "waiting-approval" : "running",
194
- abortable: !active.settling };
190
+ abortable: !active.settling, ...(active.messageRequestId ? { messageRequestId: active.messageRequestId } : {}) };
195
191
  }
196
192
  currentOperations(): Array<CurrentOperationProjection & { sessionRef: string }> {
197
193
  const result: Array<CurrentOperationProjection & { sessionRef: string }> = [];
@@ -202,80 +198,69 @@ export class SessionRuntimeSupervisor {
202
198
  return result;
203
199
  }
204
200
  ownership(sessionRef: string): SessionOwnerProjection {
205
- const lease = this.#leases.inspect(sessionRef);
206
- const active = this.#active.get(sessionRef);
207
- if (lease.state === "released") return {
208
- state: "offline", liveState: "offline", composerAvailable: true, needsAttention: false,
209
- owner: { kind: "none", ownerEpoch: null, gatewayInstanceRef: null, runtimeInstanceRef: null, continuity: "released" },
210
- reasonCode: null
211
- };
212
- if (lease.state === "gateway-owned" && active && active.lease.ownerEpoch === lease.ownerEpoch
213
- && lease.gatewayInstanceRef === this.#gatewayInstanceRef && active.lease.runtimeInstanceRef === lease.runtimeInstanceRef) return {
214
- state: "gateway-owned", liveState: active.approvalWaiting ? "waiting-approval" : active.operationRef ? "running" : "idle",
215
- composerAvailable: true, needsAttention: active.approvalWaiting,
216
- owner: { kind: "gateway", ownerEpoch: lease.ownerEpoch!, gatewayInstanceRef: lease.gatewayInstanceRef!,
217
- runtimeInstanceRef: lease.runtimeInstanceRef!, continuity: "exact" }, reasonCode: null
218
- };
219
- if (lease.state === "unavailable") return {
220
- state: "recovery-required", liveState: "uncertain", composerAvailable: false, needsAttention: true,
221
- owner: { kind: "none", ownerEpoch: null, gatewayInstanceRef: null, runtimeInstanceRef: null, continuity: "unknown" },
222
- reasonCode: lease.reasonCode ?? "session-lease-unavailable"
223
- };
224
- if (lease.state === "terminal-owned") return {
225
- state: "terminal-owned", liveState: "uncertain", composerAvailable: false, needsAttention: false,
226
- owner: { kind: "terminal", ownerEpoch: lease.ownerEpoch!,
227
- gatewayInstanceRef: `terminal_${createHmac("sha256", this.#key).update(lease.gatewayInstanceRef!).digest("base64url").slice(0, 43)}`,
228
- runtimeInstanceRef: lease.runtimeInstanceRef!, continuity: "exact" },
229
- reasonCode: "terminal-owner-active"
230
- };
231
- return {
232
- state: "recovery-required", liveState: "uncertain", composerAvailable: false, needsAttention: true,
233
- owner: { kind: "gateway", ownerEpoch: lease.ownerEpoch!, gatewayInstanceRef: lease.gatewayInstanceRef!,
234
- runtimeInstanceRef: lease.runtimeInstanceRef!, continuity: "uncertain" },
235
- reasonCode: lease.reasonCode ?? "session-owner-continuity-unknown"
236
- };
201
+ return projectSessionRuntimeOwnership({ lease: this.#leases.inspect(sessionRef), active: this.#active.get(sessionRef),
202
+ gatewayInstanceRef: this.#gatewayInstanceRef, key: this.#key });
237
203
  }
238
204
  async send(sessionRef: string, payload: { delivery: "new-operation" | "follow-up" | "steer"; message: string;
239
- expectedOperationRef: string | null; images?: unknown[] }, sessionRevision: string):
240
- Promise<{ resultCode: "started" | "queued" | "steered"; operationRef: string }> {
205
+ expectedOperationRef: string | null; messageRequestId?: string; images?: unknown[] }, sessionRevision: string, options: { deferDispatch?: boolean } = {}):
206
+ Promise<SessionSendResult> {
241
207
  await this.acquire(sessionRef);
242
208
  const active = this.#active.get(sessionRef), session = active?.runtime.session;
243
209
  if (!active || !session) throw new Error("session-runtime-unavailable");
244
210
  if (payload.delivery !== "new-operation") {
211
+ if (active.runtime.beginWireOperation) throw new Error("provider-wire-queued-input-unsupported");
245
212
  if (!active.operationRef || active.operationRef !== payload.expectedOperationRef || active.settling || !session.isStreaming) throw new Error("session-operation-conflict");
246
213
  const images = payload.images?.length ? payload.images : undefined;
247
214
  if (payload.delivery === "follow-up") { await session.followUp(payload.message, images); return { resultCode: "queued", operationRef: active.operationRef }; }
248
215
  await session.steer(payload.message, images); return { resultCode: "steered", operationRef: active.operationRef };
249
216
  }
250
217
  if (payload.expectedOperationRef !== null || active.operationRef || active.settling || !session.isIdle) throw new Error("session-operation-conflict");
251
- const operationRef = `operation_${randomBytes(24).toString("base64url")}`;
252
- const stream = new GatewaySessionStream({ sessionRef, operationRef, events: this.#events });
218
+ const operationRef = `operation_${randomBytes(24).toString("base64url")}`, messageRequestId = payload.messageRequestId ?? null;
219
+ const recoveryRequest = terminalDeliveryRequest(payload.message, payload.images);
220
+ const stream = new GatewaySessionStream({ sessionRef, operationRef, messageRequestId, events: this.#events,
221
+ commitTerminalDeliveryReceipt: terminalDeliveryReceiptCommitter({ cwd: active.info.cwd, sessionId: active.info.id,
222
+ operationRef, messageRequestId, request: recoveryRequest,
223
+ entries: () => (active.sessionManager ?? session.sessionManager)?.getBranch?.() ?? [],
224
+ persistedEntries: () => terminalDeliverySessionEntries(active.info.path, active.info.id),
225
+ // The committer fails closed on missing/throwing persistence methods.
226
+ appendCustomEntry: (type, data) => (active.sessionManager ?? session.sessionManager).appendCustomEntry(type, data) }) });
253
227
  const watchdog = new SessionOperationWatchdog(this.#operationDeadlinePolicy);
254
- active.operationRef = operationRef; active.stream = stream; active.watchdog = watchdog; active.lastSessionRevision = sessionRevision;
228
+ active.operationRef = operationRef; active.messageRequestId = messageRequestId;
229
+ active.stream = stream; active.watchdog = watchdog; active.lastSessionRevision = sessionRevision;
255
230
  try {
231
+ active.cancelWire = active.runtime.beginWireOperation?.({ operationRef, messageRequestId, inputText: payload.message }) ?? null;
256
232
  active.unsubscribe = armSessionOperationWatchdog({ watchdog, subscribe: (listener) => session.subscribe(listener), retrySession: session,
257
233
  observe: (event) => stream.observe(event), expire: (reasonCode) => { void this.#terminateOperation(sessionRef,
258
234
  operationRef, "error", reasonCode, reasonCode, true).catch(() => undefined); } });
259
235
  } catch (error) { stream.markError("session-operation-start-failed");
260
236
  await this.#quarantineRuntime(sessionRef, operationRef, active, stream, "session-operation-start-failed"); throw error; }
261
- this.#events.publish("runtime.changed", { sessionRef, sessionRevision, liveState: "running", operationRef, reasonCode: null });
262
- const created = this.#created.get(sessionRef);
263
- if (created && created.firstMessage === "(no messages)") {
264
- created.firstMessage = payload.message; created.allMessagesText = payload.message; created.messageCount = 1; created.modified = new Date();
265
- }
266
- let prompt: Promise<void>;
267
- try { prompt = session.prompt(payload.message, payload.images?.length ? { images: payload.images } : undefined); }
268
- catch (error) { stream.markError(); await this.#finishOperation(sessionRef, operationRef, stream); throw error; }
269
- const started = waitForOperationStart(stream, prompt);
270
- // `agent_settled` is canonical even when a workflow's outer prompt resolves first.
271
- const lifecycle = started.then(async (mode) => {
272
- if (mode === "deferred") await stream.settled();
273
- else await Promise.race([stream.settled(), prompt]);
274
- });
275
- active.completion = lifecycle.then(() => this.#finishOperation(sessionRef, operationRef, stream),
276
- () => { stream.markError(); return this.#finishOperation(sessionRef, operationRef, stream); });
277
- try { await started; }
278
- catch (error) { await active.completion; throw error; }
237
+ let launched: LaunchedSessionPrompt | null = null, cancelled = false;
238
+ const dispatch = () => {
239
+ if (launched || cancelled) return;
240
+ this.#events.publish("runtime.changed", { sessionRef, sessionRevision, liveState: "running", operationRef,
241
+ ...(messageRequestId ? { messageRequestId } : {}), reasonCode: null });
242
+ const created = this.#created.get(sessionRef); if (created && created.firstMessage === "(no messages)") { created.firstMessage = payload.message;
243
+ created.allMessagesText = payload.message; created.messageCount = 1; created.modified = new Date(); }
244
+ launched = launchSessionPrompt({ stream, canInvoke: () => !cancelled && this.#active.get(sessionRef) === active
245
+ && active.operationRef === operationRef, invoke: () => {
246
+ const manager = active.sessionManager ?? session.sessionManager;
247
+ if (messageRequestId && typeof manager?.appendCustomEntry === "function") {
248
+ manager.appendCustomEntry(WEBUI_MESSAGE_CORRELATION_ENTRY_TYPE,
249
+ { schemaVersion: 1, messageRequestId, operationRef,
250
+ ...(recoveryRequest !== undefined ? { terminalDeliveryRequest: recoveryRequest } : {}) });
251
+ }
252
+ return session.prompt(payload.message, payload.images?.length ? { images: payload.images } : undefined);
253
+ }, finish: () => this.#finishOperation(sessionRef, operationRef, stream) }); active.completion = launched.completion;
254
+ };
255
+ const cancel = () => {
256
+ if (launched || cancelled || this.#active.get(sessionRef) !== active || active.operationRef !== operationRef) return false;
257
+ cancelled = true; active.cancelWire?.("cancelled-before-dispatch"); active.cancelWire = null;
258
+ bestEffortUnsubscribe(active.unsubscribe); active.unsubscribe = null; watchdog.close();
259
+ active.operationRef = null; active.messageRequestId = null;
260
+ active.stream = null; active.watchdog = null; active.settling = false; return true;
261
+ };
262
+ if (options.deferDispatch) return { resultCode: "started", operationRef, dispatch, cancel };
263
+ dispatch(); try { await launched!.started; } catch (error) { await launched!.completion; throw error; }
279
264
  return { resultCode: "started", operationRef };
280
265
  }
281
266
  async abort(sessionRef: string, operationRef: string, clearQueued: boolean): Promise<void> {
@@ -286,7 +271,7 @@ export class SessionRuntimeSupervisor {
286
271
  const active = this.#active.get(sessionRef), session = active?.runtime.session, stream = active?.stream, watchdog = active?.watchdog;
287
272
  if (!active || !session || !stream || !watchdog || active.operationRef !== operationRef) throw new Error("session-operation-conflict");
288
273
  if (active.settling && !watchdog.terminating) throw new Error("session-operation-conflict");
289
- active.settling = true; active.approvalWaiting = false;
274
+ active.cancelWire?.(reasonCode); active.cancelWire = null; active.settling = true; active.approvalWaiting = false;
290
275
  const result = await terminateWatchedSessionOperation({ watchdog, settlement, reasonCode, forcedReasonCode, stream,
291
276
  completion: () => active.completion,
292
277
  settledCleanly: () => this.#active.get(sessionRef) === active && active.operationRef !== operationRef
@@ -297,17 +282,19 @@ export class SessionRuntimeSupervisor {
297
282
  if (result.state === "quarantine") await this.#quarantineRuntime(sessionRef, operationRef, active, stream, result.reasonCode);
298
283
  else if (this.#active.get(sessionRef) === active) { active.stream = null; active.watchdog = null; active.settling = false; }
299
284
  }
300
- async #quarantineRuntime(sessionRef: string, operationRef: string, active: ActiveRuntime,
301
- stream: GatewaySessionStream, reasonCode: string): Promise<void> {
285
+ async #quarantineRuntime(sessionRef: string, operationRef: string, active: ActiveRuntime, stream: GatewaySessionStream, reasonCode: string): Promise<void> {
302
286
  if (this.#active.get(sessionRef) !== active) return;
287
+ active.cancelWire?.(reasonCode); active.cancelWire = null;
303
288
  bestEffortUnsubscribe(active.unsubscribe); active.unsubscribe = null; active.watchdog?.close(); active.watchdog = null;
304
- if (active.operationRef === operationRef) { active.operationRef = null; stream.complete(null); }
289
+ const messageRequestId = active.messageRequestId;
290
+ if (active.operationRef === operationRef) { active.operationRef = null; active.messageRequestId = null; stream.complete(null, activeSessionTask(active.info.cwd, active.info.id)?.trace?.outcome ?? null); }
305
291
  active.stream = null; active.completion = null; active.settling = false; active.approvalWaiting = false;
306
292
  this.#active.delete(sessionRef); bestEffortUnsubscribe(active.unsubscribeApproval); bestEffortUnsubscribe(active.unbindApproval);
307
293
  try { this.#leases.requireRecovery(sessionRef, active.lease.ownerEpoch!, this.#gatewayInstanceRef,
308
294
  active.lease.runtimeInstanceRef!, reasonCode); } catch { /* continuity remains fail closed */ }
309
295
  if (active.lastSessionRevision) this.#events.publish("runtime.changed", { sessionRef,
310
- sessionRevision: active.lastSessionRevision, liveState: "uncertain", operationRef: null, reasonCode });
296
+ sessionRevision: active.lastSessionRevision, liveState: "uncertain", operationRef: null,
297
+ ...(messageRequestId ? { messageRequestId } : {}), reasonCode });
311
298
  await boundedResult(Promise.resolve().then(() => active.runtime.dispose()), this.#operationDeadlinePolicy.terminationTimeoutMs);
312
299
  }
313
300
  #bindApproval(sessionRef: string, active: ActiveRuntime): void {
@@ -347,7 +334,8 @@ export class SessionRuntimeSupervisor {
347
334
  active.lastSessionRevision = projection.sessionRevision;
348
335
  this.#events.publish("runtime.changed", { sessionRef, sessionRevision: projection.sessionRevision,
349
336
  liveState: active.approvalWaiting ? "waiting-approval" : active.operationRef ? "running" : projection.liveState,
350
- operationRef: active.operationRef, reasonCode: `approval-${event.kind}` });
337
+ operationRef: active.operationRef, ...(active.messageRequestId ? { messageRequestId: active.messageRequestId } : {}),
338
+ reasonCode: `approval-${event.kind}` });
351
339
  } catch { /* approval truth remains available through the canonical inspection route */ }
352
340
  }
353
341
  async setModel(sessionRef: string, modelRef: string): Promise<"model-changed" | "no-change"> {
@@ -456,8 +444,13 @@ export class SessionRuntimeSupervisor {
456
444
  async #finishOperation(sessionRef: string, operationRef: string, stream: GatewaySessionStream): Promise<void> {
457
445
  const active = this.#active.get(sessionRef);
458
446
  if (!active || active.operationRef !== operationRef) return;
459
- const restartRequired = stream.runtimeRestartRequired; let projection: Projection | null = null;
447
+ active.cancelWire?.("operation-settled"); active.cancelWire = null;
448
+ const restartRequired = stream.runtimeRestartRequired, messageRequestId = active.messageRequestId; let projection: Projection | null = null;
460
449
  bestEffortUnsubscribe(active.unsubscribe); active.unsubscribe = null; active.watchdog?.close(); active.settling = true;
450
+ const task = activeSessionTask(active.info.cwd, active.info.id);
451
+ const settlement = await this.#settleOperation(active.info.cwd, task, {
452
+ sessionId: active.info.id, operationRef, messageRequestId, stream,
453
+ manager: active.sessionManager ?? active.runtime.session?.sessionManager });
461
454
  try {
462
455
  if (this.#readProjection) {
463
456
  const read = await boundedResult(this.#readProjection(sessionRef), this.#operationDeadlinePolicy.projectionTimeoutMs);
@@ -468,13 +461,14 @@ export class SessionRuntimeSupervisor {
468
461
  if (this.#active.get(sessionRef) !== active || active.operationRef !== operationRef) return;
469
462
  if (this.ownership(sessionRef).state !== "gateway-owned") { stream.markError("session-owner-continuity-lost"); await this.#quarantineRuntime(sessionRef, operationRef, active, stream, "session-owner-continuity-lost"); return; }
470
463
  // The pre-clear projection is stale; derive post-settlement liveness from exact ownership.
471
- active.operationRef = null; const settledLiveState = this.ownership(sessionRef).liveState;
464
+ active.operationRef = null; active.messageRequestId = null; const settledLiveState = this.ownership(sessionRef).liveState;
472
465
  if (projection) active.lastSessionRevision = projection.sessionRevision;
473
- const taskOutcome = activeSessionTask(active.info.cwd, active.info.id)?.trace?.outcome ?? null;
474
- stream.complete(projection?.sessionRevision ?? null, taskOutcome);
466
+ const terminalTask = activeSessionTask(active.info.cwd, active.info.id), taskOutcome = terminalTask?.trace?.outcome ?? null, nativeTaskStatus = terminalTask?.trace?.outcome === "blocked" && terminalTask.trace.terminalDisposition === "refused" ? "refused" : null;
467
+ stream.complete(projection?.sessionRevision ?? null, taskOutcome,
468
+ settlement.status === "not-applicable" ? nativeTaskStatus : settlement.taskStatus);
475
469
  if (projection) this.#events.publish("runtime.changed", { sessionRef, sessionRevision: projection.sessionRevision,
476
470
  liveState: restartRequired ? "uncertain" : settledLiveState, operationRef: null,
477
- reasonCode: restartRequired ? "runtime-restart-required" : null });
471
+ ...(messageRequestId ? { messageRequestId } : {}), reasonCode: restartRequired ? "runtime-restart-required" : null });
478
472
  if (this.#active.get(sessionRef) === active) { active.completion = null;
479
473
  if (!active.watchdog?.terminating) { active.stream = null; active.watchdog = null; active.settling = false; } }
480
474
  if (!restartRequired || !projection || this.#active.get(sessionRef) !== active) return;
@@ -483,18 +477,24 @@ export class SessionRuntimeSupervisor {
483
477
  await this.restart(sessionRef); restartAuthority = this.#active.get(sessionRef) ?? null;
484
478
  const projection = await this.#readProjection?.(sessionRef);
485
479
  if (!projection || !restartAuthority || this.#active.get(sessionRef) !== restartAuthority || this.ownership(sessionRef).state !== "gateway-owned") return;
486
- this.#events.publish("runtime.changed", { sessionRef, sessionRevision: projection.sessionRevision, liveState: projection.liveState, operationRef: null, reasonCode: null });
480
+ this.#events.publish("runtime.changed", { sessionRef, sessionRevision: projection.sessionRevision, liveState: projection.liveState,
481
+ operationRef: null, ...(messageRequestId ? { messageRequestId } : {}), reasonCode: null });
487
482
  } catch {
488
483
  if (!restartAuthority || this.#active.get(sessionRef) !== restartAuthority || this.ownership(sessionRef).state !== "gateway-owned") return;
489
- this.#events.publish("runtime.changed", { sessionRef, sessionRevision: projection.sessionRevision, liveState: "uncertain", operationRef: null, reasonCode: "runtime-restart-failed" });
484
+ this.#events.publish("runtime.changed", { sessionRef, sessionRevision: projection.sessionRevision, liveState: "uncertain",
485
+ operationRef: null, ...(messageRequestId ? { messageRequestId } : {}), reasonCode: "runtime-restart-failed" });
490
486
  }
491
487
  }
492
- async close(): Promise<void> {
493
- if (this.#closed) return;
494
- this.#closed = true;
495
- await Promise.allSettled([...this.#opening.values()]);
496
- await Promise.allSettled([...this.#active.entries()].filter(([, active]) => active.operationRef)
497
- .map(([sessionRef, active]) => this.abort(sessionRef, active.operationRef!, true)));
498
- await Promise.allSettled([...this.#active.keys()].map((sessionRef) => this.release(sessionRef)));
488
+ close(): Promise<void> {
489
+ if (!this.#closing) {
490
+ this.#closed = true;
491
+ this.#closing = closeSessionRuntimes({ opening: this.#opening, active: this.#active,
492
+ terminationTimeoutMs: this.#operationDeadlinePolicy.terminationTimeoutMs,
493
+ abort: (sessionRef, operationRef) => this.abort(sessionRef, operationRef, true),
494
+ release: sessionRef => this.release(sessionRef),
495
+ quarantine: (sessionRef, operationRef, active, reasonCode) =>
496
+ this.#quarantineRuntime(sessionRef, operationRef, active, active.stream!, reasonCode) });
497
+ }
498
+ return this.#closing;
499
499
  }
500
500
  }
@@ -3,8 +3,27 @@ import { randomBytes } from "node:crypto";
3
3
  import { redactSensitiveText } from "../../piagent-core/extensions/redaction-core.js";
4
4
  import { ReadModelNotFound, type SourceView, type StreamEvent, type WebUiReadModelProvider } from "./read-model-provider.ts";
5
5
  import { projectTranscript } from "./transcript-projection.ts";
6
+ import { readTerminalDeliveryReceipt, terminalDeliverySessionEntries } from "./terminal-delivery-receipt.ts";
6
7
 
7
8
  const CORE_ROOT = "../../piagent-core";
9
+ const SOURCE_AUTHORITY_ALIGNED = Symbol("piagent-source-authority-aligned");
10
+ const STABLE_IDENTITY_FIELDS = ["projectRef", "runtimeInstanceId", "sessionRef", "taskId", "taskRunId"] as const;
11
+
12
+ function stableIdentityMatches(left: Record<string, any> | null | undefined, right: Record<string, any> | null | undefined): boolean {
13
+ return Boolean(left && right && STABLE_IDENTITY_FIELDS.every((field) => left[field] === right[field]));
14
+ }
15
+
16
+ function sourceBinding(snapshot: Record<string, any>) {
17
+ return { sourceProjectionRevision: snapshot.sourceChanges.projectionRevision,
18
+ taskViewRevision: snapshot.sourceChanges.task.revision, workspaceRevision: snapshot.sourceChanges.workingTree.revision,
19
+ indexRevision: snapshot.sourceChanges.staged.revision };
20
+ }
21
+
22
+ function sourceDocumentMatches(document: Record<string, any> | null | undefined, snapshot: Record<string, any>): boolean {
23
+ const binding = sourceBinding(snapshot);
24
+ return Boolean(document && stableIdentityMatches(document.identity, snapshot.identity)
25
+ && Object.entries(binding).every(([field, value]) => document.snapshotBinding?.[field] === value));
26
+ }
8
27
 
9
28
  type RuntimeEvent = { eventCursor: string; [key: string]: unknown };
10
29
  type EventReplay = {
@@ -52,6 +71,7 @@ export type CoreInspectionInput = {
52
71
  activityEvents?: () => unknown[];
53
72
  currentActivity?: () => unknown[];
54
73
  sessionEntries?: () => unknown[];
74
+ sessionFile?: () => string | undefined;
55
75
  protectedPaths?: () => string[];
56
76
  // Extra directories the operator granted through the profile. The document
57
77
  // workspace lists them beside the project; without them it shows the project
@@ -72,6 +92,7 @@ export type CoreInspectionInput = {
72
92
  chatControl?: () => { state: "unbound" | "ready" | "replacement-pending" | "shutdown"; liveness: "idle" | "running" | "unknown";
73
93
  taskState: "none" | "active" | "pause-requested" | "paused" | "terminal" | "unknown"; identity: Record<string, any> | null; revisions: Record<string, any> | null;
74
94
  heldCount: number; queueRevision: string | null };
95
+ operationLiveness?: () => "idle" | "running" | "unknown";
75
96
  };
76
97
 
77
98
  export class CoreInspectionProvider implements WebUiReadModelProvider {
@@ -97,12 +118,15 @@ export class CoreInspectionProvider implements WebUiReadModelProvider {
97
118
  const projectionEpoch = this.#invalidationEpoch;
98
119
  const { buildWebUiInspectionProjection } = await loadCoreInspection();
99
120
  const retention = this.#input.eventStore.retention();
121
+ const control = this.#input.chatControl?.();
122
+ const operationLiveness = control?.state === "ready" ? control.liveness : this.#input.operationLiveness?.();
100
123
  const value = await buildWebUiInspectionProjection({
101
124
  cwd: this.#input.cwd, sessionId: this.#input.sessionId, runtimeInstanceId: this.#input.runtimeInstanceId,
102
125
  task: this.#input.task?.(), events: this.#input.activityEvents?.() ?? [], current: this.#input.currentActivity?.() ?? [],
103
126
  sessionEntries: this.#input.sessionEntries?.() ?? [], protectedPaths: this.#input.protectedPaths?.() ?? [],
104
127
  contextUsage: this.#input.contextUsage?.(), model: this.#input.model?.(), thinkingLevel: this.#input.thinkingLevel?.(),
105
- eventCursor: this.#input.eventStore.currentCursor(), resyncRequired: this.#input.eventStore.resyncRequired(), eventReplay: retention
128
+ eventCursor: this.#input.eventStore.currentCursor(), resyncRequired: this.#input.eventStore.resyncRequired(), eventReplay: retention,
129
+ operationLiveness
106
130
  });
107
131
  // What the host will accept as an attachment is a property of the machine and
108
132
  // the model, not of chat control. The Gateway drives sessions without a chat
@@ -115,11 +139,15 @@ export class CoreInspectionProvider implements WebUiReadModelProvider {
115
139
  Object.assign(value.snapshot.capabilities.limits, { maxRequestBodyBytes: 11_250_000, maxAttachmentCount: 4,
116
140
  maxAttachmentFileBytes: 8_388_608, maxAttachmentTotalBytes: 16_777_216 });
117
141
  }
118
- const control = this.#input.chatControl?.();
142
+ const projectedIdentity = value.snapshot.identity, projectedTaskRevision = value.snapshot.revision.taskRevision;
143
+ let sourceIdentityAligned = !this.#input.eventStore.resyncRequired()
144
+ && Object.values(value.sourceViews).every((document) => document === null || sourceDocumentMatches(document as Record<string, any>, value.snapshot));
119
145
  if (control?.state === "ready" && control.identity && control.revisions && !this.#input.eventStore.resyncRequired()) {
120
146
  const available = { available: true, reasonCode: null }, disabled = (reasonCode: string) => ({ available: false, reasonCode });
121
147
  const lifecycle = this.#input.lifecycleControl?.(), terminal = control.taskState === "terminal";
122
148
  const dispatchBlocked = lifecycle?.dispatchBlocked === true && lifecycle.state !== "terminal";
149
+ sourceIdentityAligned = sourceIdentityAligned && stableIdentityMatches(projectedIdentity, control.identity)
150
+ && (projectedIdentity.taskId === null || projectedTaskRevision === control.revisions.taskRevision);
123
151
  value.snapshot.identity = structuredClone(control.identity);
124
152
  value.snapshot.capabilities.identity = structuredClone(control.identity);
125
153
  for (const name of ["runtimeRevision", "taskRevision", "controlRevision", "sessionOptionRevision", "queueRevision"])
@@ -173,7 +201,12 @@ export class CoreInspectionProvider implements WebUiReadModelProvider {
173
201
  value.snapshot.capabilities.capabilities.approve = { status: "available", version: 1, reason: null,
174
202
  decisions: ["allow", "deny"], arbitration: "first-valid-cas" };
175
203
  }
176
- if (control.identity.taskId && control.identity.taskRunId && control.revisions.taskRevision && value.snapshot.revision.workspaceRevision) {
204
+ if (control.identity.taskId && control.identity.taskRunId && control.revisions.taskRevision && value.snapshot.revision.workspaceRevision
205
+ && !sourceIdentityAligned) {
206
+ value.snapshot.capabilities.capabilities.reviewActions = { status: "unavailable", version: null,
207
+ reason: { code: "source-binding-resync-required",
208
+ message: "Source actions require a source projection bound to the current project, session and task." } };
209
+ } else if (control.identity.taskId && control.identity.taskRunId && control.revisions.taskRevision && value.snapshot.revision.workspaceRevision) {
177
210
  const mutationGuardAvailable = this.#input.sourceMutationGuardAvailable?.() === true;
178
211
  const chatSend = value.snapshot.capabilities.capabilities["control.chat"]?.status === "available"
179
212
  && value.snapshot.capabilities.capabilities["control.chat"].actions.send.available;
@@ -192,6 +225,16 @@ export class CoreInspectionProvider implements WebUiReadModelProvider {
192
225
  } };
193
226
  }
194
227
  }
228
+ if (sourceIdentityAligned) {
229
+ const binding = sourceBinding(value.snapshot);
230
+ for (const document of Object.values(value.sourceViews)) {
231
+ if (document && typeof document === "object") Object.assign(document as Record<string, any>, {
232
+ identity: structuredClone(value.snapshot.identity), snapshotBinding: structuredClone(binding)
233
+ });
234
+ }
235
+ }
236
+ Object.defineProperty(value, SOURCE_AUTHORITY_ALIGNED, { value: sourceIdentityAligned
237
+ && Object.values(value.sourceViews).every((document) => document === null || sourceDocumentMatches(document as Record<string, any>, value.snapshot)) });
195
238
  if (projectionEpoch === this.#invalidationEpoch) this.#cachedProjection = { at: Date.now(), value };
196
239
  return value;
197
240
  }
@@ -244,6 +287,8 @@ export class CoreInspectionProvider implements WebUiReadModelProvider {
244
287
  indexRevision: snapshot.revision.indexRevision, approvalRevision: snapshot.revision.approvalRevision,
245
288
  sessionOptionRevision: snapshot.revision.sessionOptionRevision, queueRevision: snapshot.revision.queueRevision },
246
289
  eventCursor: snapshot.revision.eventCursor, entries: this.#input.sessionEntries?.() ?? [], beforeCursor, limit,
290
+ terminalDeliveryReceipt: readTerminalDeliveryReceipt(this.#input.cwd, activeTask),
291
+ terminalDeliveryEntries: terminalDeliverySessionEntries(this.#input.sessionFile?.(), this.#input.sessionId),
247
292
  generatedAt: snapshot.generatedAt, taskOutcome: typeof activeTask?.trace?.outcome === "string" ? activeTask.trace.outcome : null });
248
293
  }
249
294
  async queue(): Promise<unknown> {
@@ -258,15 +303,18 @@ export class CoreInspectionProvider implements WebUiReadModelProvider {
258
303
  const value = this.#input.approvalDetail?.(approvalRef); if (!value) throw new ReadModelNotFound(); return value;
259
304
  }
260
305
  async diff(view: SourceView, fileRef: string): Promise<unknown> {
261
- const cacheKey = `${view}:${fileRef}`;
262
- const cached = this.#diffCache.get(cacheKey);
263
- if (cached && Date.now() - cached.at <= 200) return cached.value;
264
- const { collectFileDiff, matchesProtectedPath } = await loadCoreInspection();
306
+ const requestEpoch = this.#invalidationEpoch;
265
307
  const projection = await this.#projection();
308
+ this.#requireSourceAuthority(projection, [view]);
266
309
  const source = view === "working-tree" ? projection.sourceViews.workingTree : projection.sourceViews[view];
267
310
  const file = source?.files.find((candidate: any) => candidate.fileRef === fileRef) as Record<string, any> | undefined;
268
311
  if (!source || !file) throw new ReadModelNotFound();
269
312
  const identity = projection.snapshot.identity;
313
+ const cacheKey = [...STABLE_IDENTITY_FIELDS.map((field) => identity[field]), projection.snapshot.revision.taskRevision,
314
+ projection.snapshot.sourceChanges.projectionRevision, view, source.viewRevision, file.fileRevision, fileRef].join("\0");
315
+ const cached = this.#diffCache.get(cacheKey);
316
+ if (cached && Date.now() - cached.at <= 200) return cached.value;
317
+ const { collectFileDiff, matchesProtectedPath } = await loadCoreInspection();
270
318
  const protectedPaths = this.#input.protectedPaths?.() ?? [];
271
319
  const value = await collectFileDiff({
272
320
  cwd: this.#input.cwd, identity, sourceView: source, fileRef,
@@ -278,8 +326,10 @@ export class CoreInspectionProvider implements WebUiReadModelProvider {
278
326
  selectedRepoPaths: file.pathDisplay === "exact-safe" ? [file.oldPath, file.path].filter((value: unknown): value is string => typeof value === "string") : undefined,
279
327
  isProtectedPath: (_root: string, repoPath: string) => Boolean(matchesProtectedPath(repoPath, protectedPaths))
280
328
  });
281
- this.#diffCache.set(cacheKey, { at: Date.now(), value });
282
- if (this.#diffCache.size > 128) this.#diffCache.delete(this.#diffCache.keys().next().value as string);
329
+ if (requestEpoch === this.#invalidationEpoch) {
330
+ this.#diffCache.set(cacheKey, { at: Date.now(), value });
331
+ if (this.#diffCache.size > 128) this.#diffCache.delete(this.#diffCache.keys().next().value as string);
332
+ }
283
333
  return value;
284
334
  }
285
335
 
@@ -288,6 +338,7 @@ export class CoreInspectionProvider implements WebUiReadModelProvider {
288
338
  // cache when deriving its exact Git/task preimage.
289
339
  this.invalidate();
290
340
  const projection = await this.#projection(), snapshot = projection.snapshot;
341
+ this.#requireSourceAuthority(projection, [view]);
291
342
  const identity = { ...snapshot.identity, agentOperationId: null, toolCallId: null };
292
343
  if (!identity.taskId || !identity.taskRunId || !snapshot.revision.taskRevision || !snapshot.revision.workspaceRevision) throw new ReadModelNotFound();
293
344
  const diff = await this.diff(view, fileRef) as any;
@@ -303,10 +354,11 @@ export class CoreInspectionProvider implements WebUiReadModelProvider {
303
354
  async #sourceMutation(action: "source.stage" | "source.unstage", fileRef: string) {
304
355
  this.invalidate();
305
356
  const projection = await this.#projection(), snapshot = projection.snapshot;
357
+ const view: SourceView = action === "source.stage" ? "working-tree" : "staged";
358
+ this.#requireSourceAuthority(projection, [view]);
306
359
  const identity = { ...snapshot.identity, agentOperationId: null, toolCallId: null };
307
360
  if (!identity.taskId || !identity.taskRunId || !snapshot.revision.taskRevision || !snapshot.revision.workspaceRevision || !snapshot.revision.indexRevision)
308
361
  throw new ReadModelNotFound();
309
- const view: SourceView = action === "source.stage" ? "working-tree" : "staged";
310
362
  const source = view === "working-tree" ? projection.sourceViews.workingTree : projection.sourceViews.staged;
311
363
  if (!source?.files.some((file: any) => file.fileRef === fileRef)) throw new ReadModelNotFound();
312
364
  const diff = await this.diff(view, fileRef) as any;
@@ -330,6 +382,7 @@ export class CoreInspectionProvider implements WebUiReadModelProvider {
330
382
  async #sourceRevert(fileRef: string, hunkRef: string | null) {
331
383
  this.invalidate();
332
384
  const projection = await this.#projection(), snapshot = projection.snapshot;
385
+ this.#requireSourceAuthority(projection, ["working-tree", ...(projection.sourceViews.task ? ["task" as const] : [])]);
333
386
  const identity = { ...snapshot.identity, agentOperationId: null, toolCallId: null };
334
387
  if (!identity.taskId || !identity.taskRunId || !snapshot.revision.taskRevision || !snapshot.revision.workspaceRevision || !snapshot.revision.indexRevision)
335
388
  throw new ReadModelNotFound();
@@ -357,6 +410,7 @@ export class CoreInspectionProvider implements WebUiReadModelProvider {
357
410
 
358
411
  async sourceOpenAuthority(fileRef: string) {
359
412
  this.invalidate(); const projection = await this.#projection(), snapshot = projection.snapshot;
413
+ this.#requireSourceAuthority(projection, ["working-tree"]);
360
414
  const identity = { ...snapshot.identity, agentOperationId: null, toolCallId: null };
361
415
  if (!identity.taskId || !identity.taskRunId || !snapshot.revision.taskRevision || !snapshot.revision.workspaceRevision) return null;
362
416
  const { resolveSourceOpenTarget, matchesProtectedPath } = await loadCoreInspection(), protectedPaths = this.#input.protectedPaths?.() ?? [];
@@ -367,6 +421,7 @@ export class CoreInspectionProvider implements WebUiReadModelProvider {
367
421
 
368
422
  async commitSummary(): Promise<unknown> {
369
423
  this.invalidate(); const projection = await this.#projection(), snapshot = projection.snapshot;
424
+ this.#requireSourceAuthority(projection, ["staged"]);
370
425
  const identity = { ...snapshot.identity, agentOperationId: null, toolCallId: null };
371
426
  if (!identity.taskId || !identity.taskRunId || !snapshot.revision.taskRevision || !snapshot.revision.indexRevision) throw new ReadModelNotFound();
372
427
  const { projectDeterministicCommitSummary } = await loadCoreInspection();
@@ -424,12 +479,16 @@ export class CoreInspectionProvider implements WebUiReadModelProvider {
424
479
  this.invalidate(); return structuredClone((await this.#projection()).snapshot.revision);
425
480
  }
426
481
 
482
+ #requireSourceAuthority(projection: any, views: SourceView[]): void {
483
+ if (projection[SOURCE_AUTHORITY_ALIGNED] !== true || views.some((view) => {
484
+ const document = view === "working-tree" ? projection.sourceViews.workingTree : projection.sourceViews[view];
485
+ return !sourceDocumentMatches(document, projection.snapshot);
486
+ })) throw new ReadModelNotFound();
487
+ }
488
+
427
489
  replay(after: string | null, limit: number) {
428
490
  const replay = this.#input.eventStore.replay(after, limit);
429
- if (replay.state !== "current") {
430
- this.#cachedProjection = null;
431
- this.#diffCache.clear();
432
- }
491
+ if (replay.state !== "current") this.invalidate();
433
492
  return { ...replay, events: replay.events.map((event) => ({ cursor: event.eventCursor, value: event })) };
434
493
  }
435
494
  subscribe(listener: (event: StreamEvent) => void): () => void { this.#listeners.add(listener); return () => this.#listeners.delete(listener); }