@piagent/platform 1.6.0 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (736) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/README.md +24 -15
  3. package/README.vi.md +36 -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 +27 -3
  10. package/benchmarks/production-v1/suite.json +5 -1
  11. package/benchmarks/production-v2/grade.mjs +892 -0
  12. package/benchmarks/production-v2/project/README.md +7 -0
  13. package/benchmarks/production-v2/project/config/service.json +4 -0
  14. package/benchmarks/production-v2/project/data/audit-ledger.jsonl +1 -0
  15. package/benchmarks/production-v2/project/docs/ops.md +3 -0
  16. package/benchmarks/production-v2/project/logs/incident.log +2 -0
  17. package/benchmarks/production-v2/project/package.json +11 -0
  18. package/benchmarks/production-v2/project/scripts/check.mjs +21 -0
  19. package/benchmarks/production-v2/project/src/backend/auth.js +3 -0
  20. package/benchmarks/production-v2/project/src/backend/billing-window.js +4 -0
  21. package/benchmarks/production-v2/project/src/backend/cache.js +15 -0
  22. package/benchmarks/production-v2/project/src/backend/invoice.js +4 -0
  23. package/benchmarks/production-v2/project/src/backend/revocation-cache.js +3 -0
  24. package/benchmarks/production-v2/project/src/data/csv.js +3 -0
  25. package/benchmarks/production-v2/project/src/data/dedup.js +5 -0
  26. package/benchmarks/production-v2/project/src/data/migration.js +9 -0
  27. package/benchmarks/production-v2/project/src/data/ndjson-stream.js +5 -0
  28. package/benchmarks/production-v2/project/src/data/versioned-replay.js +8 -0
  29. package/benchmarks/production-v2/project/src/frontend/chat-events.js +7 -0
  30. package/benchmarks/production-v2/project/src/frontend/pagination.js +8 -0
  31. package/benchmarks/production-v2/project/src/frontend/request-lifecycle.js +15 -0
  32. package/benchmarks/production-v2/project/src/frontend/search-state.js +8 -0
  33. package/benchmarks/production-v2/project/src/frontend/unicode-search.js +7 -0
  34. package/benchmarks/production-v2/project/src/fullstack/contract-sync.js +10 -0
  35. package/benchmarks/production-v2/project/src/platform/args.js +10 -0
  36. package/benchmarks/production-v2/project/src/platform/config.js +7 -0
  37. package/benchmarks/production-v2/project/src/platform/workflow-session.js +9 -0
  38. package/benchmarks/production-v2/project/src/platform/workspace.js +13 -0
  39. package/benchmarks/production-v2/project/src/reliability/checkpoint.js +5 -0
  40. package/benchmarks/production-v2/project/src/reliability/expiry.js +5 -0
  41. package/benchmarks/production-v2/project/src/reliability/retry.js +15 -0
  42. package/benchmarks/production-v2/project/test/smoke.test.js +21 -0
  43. package/benchmarks/production-v2/project/vendor/README.md +1 -0
  44. package/benchmarks/production-v2/prompts/abort-reconnect-supersession.md +11 -0
  45. package/benchmarks/production-v2/prompts/backend-frontend-contract-sync.md +12 -0
  46. package/benchmarks/production-v2/prompts/billing-cutoff-clock-skew.md +11 -0
  47. package/benchmarks/production-v2/prompts/bounded-retry.md +7 -0
  48. package/benchmarks/production-v2/prompts/chunked-record-boundary.md +9 -0
  49. package/benchmarks/production-v2/prompts/cli-double-dash.md +7 -0
  50. package/benchmarks/production-v2/prompts/config-precedence.md +6 -0
  51. package/benchmarks/production-v2/prompts/destructive-history-refusal.md +3 -0
  52. package/benchmarks/production-v2/prompts/expiry-boundary.md +7 -0
  53. package/benchmarks/production-v2/prompts/idempotent-replay-conflict.md +11 -0
  54. package/benchmarks/production-v2/prompts/incident-diagnosis.md +4 -0
  55. package/benchmarks/production-v2/prompts/invoice-rounding.md +9 -0
  56. package/benchmarks/production-v2/prompts/journeys/config-precedence-scout.md +3 -0
  57. package/benchmarks/production-v2/prompts/journeys/expiry-boundary-scout.md +3 -0
  58. package/benchmarks/production-v2/prompts/journeys/quoted-csv-scout.md +3 -0
  59. package/benchmarks/production-v2/prompts/journeys/recover-after-uncertain-send.md +4 -0
  60. package/benchmarks/production-v2/prompts/journeys/repository-prompt-injection-scout.md +4 -0
  61. package/benchmarks/production-v2/prompts/journeys/resumable-checkpoint-partial-failure-scout.md +4 -0
  62. package/benchmarks/production-v2/prompts/journeys/stable-dedup-scout.md +3 -0
  63. package/benchmarks/production-v2/prompts/journeys/stale-search-response-scout.md +3 -0
  64. package/benchmarks/production-v2/prompts/journeys/tenant-cache-isolation-scout.md +4 -0
  65. package/benchmarks/production-v2/prompts/journeys/verify-current-contract.md +4 -0
  66. package/benchmarks/production-v2/prompts/journeys/workflow-switch-same-session-scout.md +4 -0
  67. package/benchmarks/production-v2/prompts/pagination-boundary.md +7 -0
  68. package/benchmarks/production-v2/prompts/protected-env-refusal.md +2 -0
  69. package/benchmarks/production-v2/prompts/quoted-csv.md +6 -0
  70. package/benchmarks/production-v2/prompts/reconnect-chat-event-order.md +19 -0
  71. package/benchmarks/production-v2/prompts/repository-prompt-injection.md +5 -0
  72. package/benchmarks/production-v2/prompts/resumable-checkpoint-partial-failure.md +11 -0
  73. package/benchmarks/production-v2/prompts/revoked-session-cache.md +10 -0
  74. package/benchmarks/production-v2/prompts/schema-migration.md +6 -0
  75. package/benchmarks/production-v2/prompts/stable-dedup.md +6 -0
  76. package/benchmarks/production-v2/prompts/stale-search-response.md +6 -0
  77. package/benchmarks/production-v2/prompts/tenant-cache-isolation.md +6 -0
  78. package/benchmarks/production-v2/prompts/tenant-role-authorization.md +6 -0
  79. package/benchmarks/production-v2/prompts/unicode-search.md +6 -0
  80. package/benchmarks/production-v2/prompts/workflow-switch-same-session.md +30 -0
  81. package/benchmarks/production-v2/prompts/workspace-order.md +7 -0
  82. package/benchmarks/production-v2/spend-control.v1.json +115 -0
  83. package/benchmarks/production-v2/suite.json +1009 -0
  84. package/benchmarks/production-v2/variant.mjs +169 -0
  85. package/benchmarks/production-v3/CONTRACT-REVISION-20260922.md +31 -0
  86. package/benchmarks/production-v3/calibration/corpus.v1.json +63 -0
  87. package/benchmarks/production-v3/calibration/human-review-rubric.v1.json +36 -0
  88. package/benchmarks/production-v3/grade.mjs +1017 -0
  89. package/benchmarks/production-v3/project/README.md +7 -0
  90. package/benchmarks/production-v3/project/config/service.json +4 -0
  91. package/benchmarks/production-v3/project/data/audit-ledger.jsonl +1 -0
  92. package/benchmarks/production-v3/project/docs/ops.md +3 -0
  93. package/benchmarks/production-v3/project/logs/incident.log +2 -0
  94. package/benchmarks/production-v3/project/package.json +11 -0
  95. package/benchmarks/production-v3/project/scripts/check.mjs +21 -0
  96. package/benchmarks/production-v3/project/src/backend/auth.js +3 -0
  97. package/benchmarks/production-v3/project/src/backend/billing-window.js +4 -0
  98. package/benchmarks/production-v3/project/src/backend/cache.js +15 -0
  99. package/benchmarks/production-v3/project/src/backend/invoice.js +4 -0
  100. package/benchmarks/production-v3/project/src/backend/revocation-cache.js +12 -0
  101. package/benchmarks/production-v3/project/src/data/csv.js +3 -0
  102. package/benchmarks/production-v3/project/src/data/dedup.js +5 -0
  103. package/benchmarks/production-v3/project/src/data/migration.js +9 -0
  104. package/benchmarks/production-v3/project/src/data/ndjson-stream.js +5 -0
  105. package/benchmarks/production-v3/project/src/data/versioned-replay.js +8 -0
  106. package/benchmarks/production-v3/project/src/frontend/chat-events.js +7 -0
  107. package/benchmarks/production-v3/project/src/frontend/pagination.js +8 -0
  108. package/benchmarks/production-v3/project/src/frontend/request-lifecycle.js +23 -0
  109. package/benchmarks/production-v3/project/src/frontend/search-state.js +8 -0
  110. package/benchmarks/production-v3/project/src/frontend/unicode-search.js +7 -0
  111. package/benchmarks/production-v3/project/src/fullstack/contract-sync.js +10 -0
  112. package/benchmarks/production-v3/project/src/platform/args.js +10 -0
  113. package/benchmarks/production-v3/project/src/platform/config.js +7 -0
  114. package/benchmarks/production-v3/project/src/platform/workflow-session.js +9 -0
  115. package/benchmarks/production-v3/project/src/platform/workspace.js +13 -0
  116. package/benchmarks/production-v3/project/src/reliability/checkpoint.js +5 -0
  117. package/benchmarks/production-v3/project/src/reliability/expiry.js +14 -0
  118. package/benchmarks/production-v3/project/src/reliability/retry.js +15 -0
  119. package/benchmarks/production-v3/project/test/smoke.test.js +21 -0
  120. package/benchmarks/production-v3/project/vendor/README.md +1 -0
  121. package/benchmarks/production-v3/prompts/abort-reconnect-supersession.md +11 -0
  122. package/benchmarks/production-v3/prompts/backend-frontend-contract-sync.md +20 -0
  123. package/benchmarks/production-v3/prompts/billing-cutoff-clock-skew.md +11 -0
  124. package/benchmarks/production-v3/prompts/bounded-retry.md +7 -0
  125. package/benchmarks/production-v3/prompts/chunked-record-boundary.md +11 -0
  126. package/benchmarks/production-v3/prompts/cli-double-dash.md +7 -0
  127. package/benchmarks/production-v3/prompts/config-precedence.md +6 -0
  128. package/benchmarks/production-v3/prompts/destructive-history-refusal.md +9 -0
  129. package/benchmarks/production-v3/prompts/expiry-boundary.md +14 -0
  130. package/benchmarks/production-v3/prompts/idempotent-replay-conflict.md +13 -0
  131. package/benchmarks/production-v3/prompts/incident-diagnosis.md +4 -0
  132. package/benchmarks/production-v3/prompts/invoice-rounding.md +9 -0
  133. package/benchmarks/production-v3/prompts/journeys/config-precedence-scout.md +3 -0
  134. package/benchmarks/production-v3/prompts/journeys/expiry-boundary-scout.md +3 -0
  135. package/benchmarks/production-v3/prompts/journeys/quoted-csv-scout.md +3 -0
  136. package/benchmarks/production-v3/prompts/journeys/recover-after-uncertain-send.md +4 -0
  137. package/benchmarks/production-v3/prompts/journeys/repository-prompt-injection-scout.md +4 -0
  138. package/benchmarks/production-v3/prompts/journeys/resumable-checkpoint-partial-failure-scout.md +4 -0
  139. package/benchmarks/production-v3/prompts/journeys/stable-dedup-scout.md +3 -0
  140. package/benchmarks/production-v3/prompts/journeys/stale-search-response-scout.md +3 -0
  141. package/benchmarks/production-v3/prompts/journeys/tenant-cache-isolation-scout.md +4 -0
  142. package/benchmarks/production-v3/prompts/journeys/verify-current-contract.md +4 -0
  143. package/benchmarks/production-v3/prompts/journeys/workflow-switch-same-session-scout.md +4 -0
  144. package/benchmarks/production-v3/prompts/pagination-boundary.md +9 -0
  145. package/benchmarks/production-v3/prompts/protected-env-refusal.md +8 -0
  146. package/benchmarks/production-v3/prompts/quoted-csv.md +6 -0
  147. package/benchmarks/production-v3/prompts/reconnect-chat-event-order.md +20 -0
  148. package/benchmarks/production-v3/prompts/repository-prompt-injection.md +5 -0
  149. package/benchmarks/production-v3/prompts/resumable-checkpoint-partial-failure.md +15 -0
  150. package/benchmarks/production-v3/prompts/revoked-session-cache.md +10 -0
  151. package/benchmarks/production-v3/prompts/schema-migration.md +6 -0
  152. package/benchmarks/production-v3/prompts/stable-dedup.md +6 -0
  153. package/benchmarks/production-v3/prompts/stale-search-response.md +6 -0
  154. package/benchmarks/production-v3/prompts/tenant-cache-isolation.md +6 -0
  155. package/benchmarks/production-v3/prompts/tenant-role-authorization.md +6 -0
  156. package/benchmarks/production-v3/prompts/unicode-search.md +6 -0
  157. package/benchmarks/production-v3/prompts/workflow-switch-same-session.md +30 -0
  158. package/benchmarks/production-v3/prompts/workspace-order.md +7 -0
  159. package/benchmarks/production-v3/public-checks/abort-reconnect-supersession.js +34 -0
  160. package/benchmarks/production-v3/public-checks/expiry-boundary.js +29 -0
  161. package/benchmarks/production-v3/public-checks/revoked-session-cache.js +20 -0
  162. package/benchmarks/production-v3/spend-control.v1.json +121 -0
  163. package/benchmarks/production-v3/suite.json +1010 -0
  164. package/benchmarks/production-v3/variant.mjs +178 -0
  165. package/catalog/capabilities.json +16 -16
  166. package/docs/authority-manifest.md +1 -1
  167. package/docs/auto-delegation-policy.md +38 -73
  168. package/docs/benchmark-codex-mcp-metadata-contract-v1.md +159 -0
  169. package/docs/benchmark-codex-mcp-metadata-contract-v2.md +182 -0
  170. package/docs/benchmark-codex-mcp-metadata-contract-v3.md +194 -0
  171. package/docs/benchmark-public-contract-addendum-v2.md +85 -0
  172. package/docs/benchmark-public-contract-addendum-v3.md +116 -0
  173. package/docs/command-reference-vietnamese.md +30 -35
  174. package/docs/context-engine.md +5 -3
  175. package/docs/context-window-policy.md +37 -1
  176. package/docs/distribution-standard.md +9 -9
  177. package/docs/en/architecture.md +26 -13
  178. package/docs/languages.json +4 -4
  179. package/docs/operator-manual-vietnamese.md +26 -46
  180. package/docs/piagent-codex-benchmark-recovery-plan.md +1817 -0
  181. package/docs/piagent-core-evaluation-specs-2026-09-06.json +706 -0
  182. package/docs/piagent-core-improvement-plan.md +528 -0
  183. package/docs/piagent-core-offline-implementation-2026-09-06.md +219 -0
  184. package/docs/piagent-core-plan-checkpoint-2026-09-06.json +69 -0
  185. package/docs/piagent-core-reasoning-research-2026-09-06.md +225 -0
  186. package/docs/piagent-core-research-sources-2026-09-06.json +416 -0
  187. package/docs/piagent-open-session-wait.md +19 -0
  188. package/docs/piagent-runtime-benchmark-execution-plan.md +685 -0
  189. package/docs/publishing-for-teams.md +7 -0
  190. package/docs/quality-benchmark.md +299 -23
  191. package/docs/quickstart-vietnamese.md +2 -2
  192. package/docs/release-install-policy.md +32 -9
  193. package/docs/research/harness-next-evidence-review.md +113 -0
  194. package/docs/runtime-harness-standard.md +3 -3
  195. package/docs/security-threat-model.md +1 -1
  196. package/docs/subagent-orchestration-capabilities.md +19 -51
  197. package/docs/subagents-and-multiagent.md +21 -47
  198. package/docs/task-implementation-contract.md +3 -3
  199. package/docs/task-lifecycle-vietnamese.md +1 -1
  200. package/docs/team-onboarding.md +7 -7
  201. package/docs/third-party-neutrality.md +7 -0
  202. package/docs/usage-observability.md +1 -1
  203. package/docs/vi/architecture.md +26 -13
  204. package/docs-site/architecture.html +1 -1
  205. package/docs-site/benchmark.html +89 -95
  206. package/docs-site/commands.html +1 -1
  207. package/docs-site/content/benchmark.html +88 -94
  208. package/docs-site/content/en/benchmark.html +134 -90
  209. package/docs-site/content/en/index.html +19 -19
  210. package/docs-site/content/en/runtime.html +5 -5
  211. package/docs-site/content/en/whats-new.html +23 -1
  212. package/docs-site/content/en/workflows.html +2 -2
  213. package/docs-site/content/index.html +19 -19
  214. package/docs-site/content/runtime.html +6 -6
  215. package/docs-site/content/whats-new.html +23 -1
  216. package/docs-site/content/workflows.html +2 -2
  217. package/docs-site/context-engine.html +1 -1
  218. package/docs-site/en/architecture.html +1 -1
  219. package/docs-site/en/benchmark.html +135 -91
  220. package/docs-site/en/commands.html +1 -1
  221. package/docs-site/en/context-engine.html +1 -1
  222. package/docs-site/en/index.html +20 -20
  223. package/docs-site/en/mcp-approval.html +1 -1
  224. package/docs-site/en/mcp-auth.html +1 -1
  225. package/docs-site/en/mcp-servers.html +1 -1
  226. package/docs-site/en/mcp.html +1 -1
  227. package/docs-site/en/permissions.html +1 -1
  228. package/docs-site/en/profiles.html +1 -1
  229. package/docs-site/en/quickstart.html +1 -1
  230. package/docs-site/en/runtime.html +6 -6
  231. package/docs-site/en/scope.html +1 -1
  232. package/docs-site/en/security.html +1 -1
  233. package/docs-site/en/team.html +1 -1
  234. package/docs-site/en/whats-new.html +24 -2
  235. package/docs-site/en/workflows.html +3 -3
  236. package/docs-site/index.html +20 -20
  237. package/docs-site/mcp-approval.html +1 -1
  238. package/docs-site/mcp-auth.html +1 -1
  239. package/docs-site/mcp-servers.html +1 -1
  240. package/docs-site/mcp.html +1 -1
  241. package/docs-site/permissions.html +1 -1
  242. package/docs-site/profiles.html +1 -1
  243. package/docs-site/quickstart.html +1 -1
  244. package/docs-site/runtime.html +7 -7
  245. package/docs-site/scope.html +1 -1
  246. package/docs-site/security.html +1 -1
  247. package/docs-site/team.html +1 -1
  248. package/docs-site/whats-new.html +24 -2
  249. package/docs-site/workflows.html +3 -3
  250. package/evals/architecture-conformance-v1/lane.json +18 -0
  251. package/evals/architecture-conformance-v1/runner.mjs +77 -0
  252. package/evals/fixtures/approved-host-contracts.invalid.json +43 -0
  253. package/evals/fixtures/approved-host-contracts.valid.json +43 -0
  254. package/evals/fixtures/benchmark-assurance-evidence.invalid.json +1 -1
  255. package/evals/fixtures/benchmark-assurance-evidence.valid.json +1 -1
  256. package/evals/fixtures/benchmark-attempt-outcome.invalid.json +42 -0
  257. package/evals/fixtures/benchmark-attempt-outcome.valid.json +42 -0
  258. package/evals/fixtures/benchmark-independent-verification-plan.invalid.json +7 -0
  259. package/evals/fixtures/benchmark-independent-verification-plan.valid.json +21 -0
  260. package/evals/fixtures/codex-relative-efficiency-v1.invalid.json +4 -0
  261. package/evals/fixtures/codex-relative-efficiency-v1.valid.json +94 -0
  262. package/evals/fixtures/composite-criterion.invalid.json +10 -0
  263. package/evals/fixtures/composite-criterion.valid.json +33 -0
  264. package/evals/fixtures/contract-family-library.invalid.json +42 -0
  265. package/evals/fixtures/contract-family-library.valid.json +41 -0
  266. package/evals/fixtures/contract-selection-recipe.invalid.json +29 -0
  267. package/evals/fixtures/contract-selection-recipe.valid.json +29 -0
  268. package/evals/fixtures/helper-request.invalid.json +1 -1
  269. package/evals/fixtures/helper-request.valid.json +1 -1
  270. package/evals/fixtures/host-contract-plan.invalid.json +42 -0
  271. package/evals/fixtures/host-contract-plan.valid.json +41 -0
  272. package/evals/fixtures/piagent-webui/subagent-tree-v1.valid.json +7 -0
  273. package/evals/fixtures/scoped-project-verification-receipt-v2.invalid.json +42 -0
  274. package/evals/fixtures/scoped-project-verification-receipt-v2.valid.json +42 -0
  275. package/evals/fixtures/scoped-project-verification-receipt-v3.invalid.json +57 -0
  276. package/evals/fixtures/scoped-project-verification-receipt-v3.valid.json +57 -0
  277. package/evals/fixtures/scoped-verification-receipt-v1.invalid.json +40 -0
  278. package/evals/fixtures/scoped-verification-receipt-v1.valid.json +40 -0
  279. package/evals/fixtures/task-authority-snapshot.valid.json +4 -4
  280. package/evals/fs4-readiness-matrix.v1.json +2 -2
  281. package/evals/fs5-artifact-archive/README.md +32 -0
  282. package/evals/fs5-artifact-archive/manifest.json +148 -0
  283. package/evals/fs5-artifact-archive/sha256/1f073f6d42c093a3182685e0e096144c8b3befd87594aeea1af05ce17653860c.txt +380 -0
  284. package/evals/fs5-artifact-archive/sha256/1ff46984c5ff668647dfad94248cd9dcfb72384a8aa529279345582f90d7486a.txt +331 -0
  285. package/evals/fs5-artifact-archive/sha256/20a5e1ef1cab3234a888b876b3cec52e702a05bc5ac000b691f94c651beed9ca.txt +800 -0
  286. package/evals/fs5-artifact-archive/sha256/29bb79e96b047d79056626d747baa0b3a6ca9d4da7ad80b9668c0085e5581706.txt +116 -0
  287. package/evals/fs5-artifact-archive/sha256/2bcc0cf6c18eee0c080c30e727610b0f10a278f5862855d920ba5797f07a2f2d.txt +252 -0
  288. package/evals/fs5-artifact-archive/sha256/37ecc65febe2c5947ac9288ad958bc149e0f08c6beda137edb1c660908853832.txt +324 -0
  289. package/evals/fs5-artifact-archive/sha256/5d937632d2cfff34dbbb781dd367bb78feb64c36d571c36ca15f2cc40c576af8.txt +142 -0
  290. package/evals/fs5-artifact-archive/sha256/6057c7bf2f40f8e3db7e293f08d745133c05293b75e9f363fb4e2e53bd09a76a.txt +244 -0
  291. package/evals/fs5-artifact-archive/sha256/62ea354afb6816b148ae9bd95ffb1ee5e29580eb4a22473e1ae19dbb471ec36b.txt +930 -0
  292. package/evals/fs5-artifact-archive/sha256/8987775b742f3b3650d75cce84e6d58fcdd3dfb835d03dac4c2bfe6d9eea3a2e.txt +903 -0
  293. package/evals/fs5-artifact-archive/sha256/902e886d0920b66811f54d0d1d933d70f8fab8704813b46d578bee6af1f21eef.txt +942 -0
  294. package/evals/fs5-artifact-archive/sha256/976a9908adfd765ee7be0655616f39a44fff64824f5e8535d726082e550b02eb.txt +910 -0
  295. package/evals/fs5-artifact-archive/sha256/9c07bda5bfe7bb7b0959844ccea6790735cc9f154d8d5972e18785148cea6d9a.txt +101 -0
  296. package/evals/fs5-artifact-archive/sha256/b936a604db87a697bf69581c33d753e26d9e5e2ccce40bf9c9b2070948f49919.txt +931 -0
  297. package/evals/fs5-artifact-archive/sha256/bf91f69473f48fc3de7c7c55e7ce893ba0511074c4ec930d9f3bcb9615d8e9d5.txt +950 -0
  298. package/evals/fs5-artifact-archive/sha256/ce4ed1b4a033f2a8cb4632d1336b0867edb3454ce1380f0642c4055149e6ac59.txt +784 -0
  299. package/evals/fs5-artifact-archive/sha256/db97f444db8ba604512daf0aa26b3fe1e2a120ace2b21d4730db5b18aa0c528f.txt +950 -0
  300. package/evals/fs5-causal-arm.v1.json +10 -6
  301. package/evals/fs5-pilot-protocol.v1.json +3 -3
  302. package/evals/fs5-pilot-protocol.v2.json +8 -8
  303. package/evals/fs5-pilot-protocol.v3.json +8 -8
  304. package/evals/fs5-pilot-protocol.v4.json +7 -7
  305. package/evals/fs5-pilot-protocol.v5.json +10 -8
  306. package/evals/harness-next/development-corpus.mjs +106 -0
  307. package/evals/harness-next/resource-budget-probe.mjs +38 -0
  308. package/evals/harness-next/run-calibration.mjs +83 -0
  309. package/evals/harness-next/run-resource-probe.mjs +55 -0
  310. package/evals/harness-next/selected-development-corpus.mjs +27 -0
  311. package/evals/harness-next.v1.json +51 -0
  312. package/evals/long-horizon-v1/README.md +19 -0
  313. package/evals/long-horizon-v1/runner.mjs +116 -48
  314. package/evals/long-horizon-v1/worker.mjs +77 -30
  315. package/evals/private-holdout-v1/CURRENT_BOUNDARY.md +53 -0
  316. package/evals/private-holdout-v1/README.md +5 -2
  317. package/evals/private-holdout-v1/public-exposure.v1.json +1 -1
  318. package/evals/private-holdout-v1/public-exposure.v2.json +273 -0
  319. package/evals/runtime-conformance-v1/README.md +43 -0
  320. package/evals/runtime-conformance-v1/evaluate-paid-canary.mjs +198 -0
  321. package/evals/runtime-conformance-v1/lane.json +57 -0
  322. package/evals/runtime-conformance-v1/paid-canary.json +31 -0
  323. package/evals/runtime-conformance-v1/runner.mjs +456 -0
  324. package/package.json +9 -4
  325. package/packages/piagent-core/README.md +15 -6
  326. package/packages/piagent-core/benchmark/benchmark-all-attempt-efficiency.js +55 -0
  327. package/packages/piagent-core/benchmark/benchmark-artifact-binding.js +49 -0
  328. package/packages/piagent-core/benchmark/benchmark-bootstrap.js +265 -14
  329. package/packages/piagent-core/benchmark/benchmark-budget-governor.js +271 -0
  330. package/packages/piagent-core/benchmark/benchmark-campaign.js +592 -0
  331. package/packages/piagent-core/benchmark/benchmark-candidate.js +8 -3
  332. package/packages/piagent-core/benchmark/benchmark-checkpoint.js +67 -0
  333. package/packages/piagent-core/benchmark/benchmark-claim-restrictions.js +269 -2
  334. package/packages/piagent-core/benchmark/benchmark-cli.js +120 -3
  335. package/packages/piagent-core/benchmark/benchmark-codex-events.js +235 -0
  336. package/packages/piagent-core/benchmark/benchmark-codex-outcome.js +20 -0
  337. package/packages/piagent-core/benchmark/benchmark-codex-relative-efficiency.js +699 -0
  338. package/packages/piagent-core/benchmark/benchmark-codex-rollout.js +521 -0
  339. package/packages/piagent-core/benchmark/benchmark-codex.js +104 -8
  340. package/packages/piagent-core/benchmark/benchmark-comparison.js +284 -1
  341. package/packages/piagent-core/benchmark/benchmark-core.js +111 -110
  342. package/packages/piagent-core/benchmark/benchmark-diagnostic-source-evidence.js +40 -0
  343. package/packages/piagent-core/benchmark/benchmark-diagnostic-treatment.js +104 -0
  344. package/packages/piagent-core/benchmark/benchmark-evaluator-v3.js +226 -0
  345. package/packages/piagent-core/benchmark/benchmark-execution-guard.js +23 -1
  346. package/packages/piagent-core/benchmark/benchmark-forensics.js +67 -52
  347. package/packages/piagent-core/benchmark/benchmark-goal-assessment.js +193 -0
  348. package/packages/piagent-core/benchmark/benchmark-goal-report.js +87 -0
  349. package/packages/piagent-core/benchmark/benchmark-independent-verification-observation.js +64 -0
  350. package/packages/piagent-core/benchmark/benchmark-matrix-summary.js +141 -0
  351. package/packages/piagent-core/benchmark/benchmark-matrix.js +1 -0
  352. package/packages/piagent-core/benchmark/benchmark-normalized-cost.js +62 -0
  353. package/packages/piagent-core/benchmark/benchmark-pi-home.js +1 -0
  354. package/packages/piagent-core/benchmark/benchmark-preflight.js +70 -7
  355. package/packages/piagent-core/benchmark/benchmark-process.js +23 -9
  356. package/packages/piagent-core/benchmark/benchmark-production-completion.js +84 -0
  357. package/packages/piagent-core/benchmark/benchmark-production-stage-validation.js +209 -0
  358. package/packages/piagent-core/benchmark/benchmark-provider-free-evidence.js +462 -0
  359. package/packages/piagent-core/benchmark/benchmark-provider-free-owner.js +24 -0
  360. package/packages/piagent-core/benchmark/benchmark-provider-wire.js +378 -0
  361. package/packages/piagent-core/benchmark/benchmark-record-validation.d.ts +2 -0
  362. package/packages/piagent-core/benchmark/benchmark-record-validation.js +343 -8
  363. package/packages/piagent-core/benchmark/benchmark-release-claim-controls.js +132 -0
  364. package/packages/piagent-core/benchmark/benchmark-report.js +94 -5
  365. package/packages/piagent-core/benchmark/benchmark-resume-recovery.js +280 -10
  366. package/packages/piagent-core/benchmark/benchmark-runner-policy.js +88 -1
  367. package/packages/piagent-core/benchmark/benchmark-runtime-causal.js +244 -0
  368. package/packages/piagent-core/benchmark/benchmark-runtime-identity.js +50 -1
  369. package/packages/piagent-core/benchmark/benchmark-runtime.js +102 -10
  370. package/packages/piagent-core/benchmark/benchmark-safety-evidence.js +74 -0
  371. package/packages/piagent-core/benchmark/benchmark-service-tier.js +189 -0
  372. package/packages/piagent-core/benchmark/benchmark-stage-diagnostic.js +246 -33
  373. package/packages/piagent-core/benchmark/benchmark-suite-identity.js +264 -1
  374. package/packages/piagent-core/benchmark/benchmark-suite-runtime.js +4 -0
  375. package/packages/piagent-core/benchmark/benchmark-suite.js +232 -4
  376. package/packages/piagent-core/benchmark/benchmark-summary-support.js +33 -1
  377. package/packages/piagent-core/benchmark/benchmark-timing-contract.js +189 -0
  378. package/packages/piagent-core/benchmark/benchmark-timing-diagnostics.js +110 -139
  379. package/packages/piagent-core/benchmark/benchmark-transport-evidence.js +203 -0
  380. package/packages/piagent-core/benchmark/benchmark-transport-observation.js +147 -0
  381. package/packages/piagent-core/benchmark/benchmark-tree-identity.js +2 -1
  382. package/packages/piagent-core/benchmark/benchmark-usage.js +410 -37
  383. package/packages/piagent-core/benchmark/benchmark-workflow.js +136 -38
  384. package/packages/piagent-core/benchmark/fs5-pilot-protocol.js +21 -2
  385. package/packages/piagent-core/capabilities/runtime-integrity.js +6 -0
  386. package/packages/piagent-core/extensions/acceptance-api-baseline.js +24 -0
  387. package/packages/piagent-core/extensions/acceptance-assessment.js +153 -0
  388. package/packages/piagent-core/extensions/acceptance-authenticated-admission.d.ts +41 -0
  389. package/packages/piagent-core/extensions/acceptance-authenticated-admission.js +120 -0
  390. package/packages/piagent-core/extensions/acceptance-behavior-proof.js +1000 -0
  391. package/packages/piagent-core/extensions/acceptance-boundary-binding.js +31 -0
  392. package/packages/piagent-core/extensions/acceptance-boundary-guidance.js +214 -0
  393. package/packages/piagent-core/extensions/acceptance-callable-scanner.js +244 -0
  394. package/packages/piagent-core/extensions/acceptance-clause-group.js +45 -0
  395. package/packages/piagent-core/extensions/acceptance-composite-contract.js +334 -0
  396. package/packages/piagent-core/extensions/acceptance-contract-conjunction.js +78 -0
  397. package/packages/piagent-core/extensions/acceptance-contract-selection.js +161 -0
  398. package/packages/piagent-core/extensions/acceptance-contract-semantics.js +211 -211
  399. package/packages/piagent-core/extensions/acceptance-declared-api.js +126 -0
  400. package/packages/piagent-core/extensions/acceptance-diagnostic-policy.ts +14 -0
  401. package/packages/piagent-core/extensions/acceptance-document-content.js +73 -0
  402. package/packages/piagent-core/extensions/acceptance-durable-execution.d.ts +59 -0
  403. package/packages/piagent-core/extensions/acceptance-durable-execution.js +139 -0
  404. package/packages/piagent-core/extensions/acceptance-error-classes.js +1 -1
  405. package/packages/piagent-core/extensions/acceptance-evidence-store.js +223 -0
  406. package/packages/piagent-core/extensions/acceptance-executable-evidence.js +490 -88
  407. package/packages/piagent-core/extensions/acceptance-execution-diagnostics.js +34 -0
  408. package/packages/piagent-core/extensions/acceptance-execution-snapshot.js +174 -0
  409. package/packages/piagent-core/extensions/acceptance-executor/.dockerignore +21 -0
  410. package/packages/piagent-core/extensions/acceptance-executor/Dockerfile +5 -0
  411. package/packages/piagent-core/extensions/acceptance-executor/README.md +103 -0
  412. package/packages/piagent-core/extensions/acceptance-executor/budget.mjs +54 -0
  413. package/packages/piagent-core/extensions/acceptance-executor/callback-intrinsics.mjs +126 -0
  414. package/packages/piagent-core/extensions/acceptance-executor/capabilities.mjs +127 -0
  415. package/packages/piagent-core/extensions/acceptance-executor/guest.mjs +285 -0
  416. package/packages/piagent-core/extensions/acceptance-executor/intrinsics.mjs +133 -0
  417. package/packages/piagent-core/extensions/acceptance-executor/invocation.mjs +39 -0
  418. package/packages/piagent-core/extensions/acceptance-executor/jobs.mjs +29 -0
  419. package/packages/piagent-core/extensions/acceptance-executor/module-graph.mjs +70 -0
  420. package/packages/piagent-core/extensions/acceptance-executor/node-profile.mjs +398 -0
  421. package/packages/piagent-core/extensions/acceptance-executor/package-lock.json +40 -0
  422. package/packages/piagent-core/extensions/acceptance-executor/package.json +10 -0
  423. package/packages/piagent-core/extensions/acceptance-executor/protocol.mjs +248 -0
  424. package/packages/piagent-core/extensions/acceptance-executor/reference-identity.mjs +61 -0
  425. package/packages/piagent-core/extensions/acceptance-executor/references.mjs +14 -0
  426. package/packages/piagent-core/extensions/acceptance-executor/structured-clone.mjs +53 -0
  427. package/packages/piagent-core/extensions/acceptance-executor/values.mjs +97 -0
  428. package/packages/piagent-core/extensions/acceptance-executor/worker.mjs +75 -0
  429. package/packages/piagent-core/extensions/acceptance-expiry-calendar-proof.js +162 -0
  430. package/packages/piagent-core/extensions/acceptance-expression-parser.js +155 -0
  431. package/packages/piagent-core/extensions/acceptance-focused-verification.js +40 -0
  432. package/packages/piagent-core/extensions/acceptance-host-configuration.js +337 -0
  433. package/packages/piagent-core/extensions/acceptance-identifier-criteria.js +25 -0
  434. package/packages/piagent-core/extensions/acceptance-independent-contract.js +209 -0
  435. package/packages/piagent-core/extensions/acceptance-independent-registry.js +106 -0
  436. package/packages/piagent-core/extensions/acceptance-input-provenance.js +40 -0
  437. package/packages/piagent-core/extensions/acceptance-integer-domains.js +322 -0
  438. package/packages/piagent-core/extensions/acceptance-invalid-input-receipt.js +20 -0
  439. package/packages/piagent-core/extensions/acceptance-invalid-partitions.js +26 -0
  440. package/packages/piagent-core/extensions/acceptance-invalid-sentinel-proof.js +477 -0
  441. package/packages/piagent-core/extensions/acceptance-isolated-executor.js +254 -0
  442. package/packages/piagent-core/extensions/acceptance-lexical-sentinels.js +130 -0
  443. package/packages/piagent-core/extensions/acceptance-literal-dataflow.js +735 -0
  444. package/packages/piagent-core/extensions/acceptance-local-binding.js +106 -0
  445. package/packages/piagent-core/extensions/acceptance-normalizer-evidence.js +719 -0
  446. package/packages/piagent-core/extensions/acceptance-obligations.js +75 -0
  447. package/packages/piagent-core/extensions/acceptance-parameter-contract.js +756 -0
  448. package/packages/piagent-core/extensions/acceptance-precedence-contract.js +572 -0
  449. package/packages/piagent-core/extensions/acceptance-proof-capability.js +26 -0
  450. package/packages/piagent-core/extensions/acceptance-receipt.js +208 -180
  451. package/packages/piagent-core/extensions/acceptance-result-contract-evidence.js +159 -0
  452. package/packages/piagent-core/extensions/acceptance-source-origin.js +214 -0
  453. package/packages/piagent-core/extensions/acceptance-state-machine-evidence.js +64 -8
  454. package/packages/piagent-core/extensions/acceptance-tagged-event-evidence.js +685 -0
  455. package/packages/piagent-core/extensions/acceptance-temporal-contract.js +756 -0
  456. package/packages/piagent-core/extensions/acceptance-temporal-dataflow-proof.js +618 -0
  457. package/packages/piagent-core/extensions/acceptance-test-binding-evidence.js +20 -2
  458. package/packages/piagent-core/extensions/acceptance-test-bindings.js +86 -0
  459. package/packages/piagent-core/extensions/acceptance-tuple-shapes.js +12 -0
  460. package/packages/piagent-core/extensions/context-engine.js +12 -17
  461. package/packages/piagent-core/extensions/context-index-policy.js +4 -0
  462. package/packages/piagent-core/extensions/context-query-paths.js +57 -0
  463. package/packages/piagent-core/extensions/criterion-context-pack.js +109 -4
  464. package/packages/piagent-core/extensions/criterion-graph.js +4 -1
  465. package/packages/piagent-core/extensions/failure-types.ts +2 -2
  466. package/packages/piagent-core/extensions/fallback-base-policy.ts +101 -0
  467. package/packages/piagent-core/extensions/guard-types.ts +9 -1
  468. package/packages/piagent-core/extensions/piagent-guard.ts +374 -364
  469. package/packages/piagent-core/extensions/readonly-inline-inspection.ts +378 -0
  470. package/packages/piagent-core/extensions/recovery-decision-validation.ts +92 -0
  471. package/packages/piagent-core/extensions/shell-write-targets.js +15 -14
  472. package/packages/piagent-core/extensions/task-contract-view.js +4 -4
  473. package/packages/piagent-core/extensions/task-digest-migration.js +2 -2
  474. package/packages/piagent-core/extensions/task-journal.js +48 -3
  475. package/packages/piagent-core/extensions/task-lifecycle.js +32 -0
  476. package/packages/piagent-core/extensions/task-runtime-audit.js +8 -2
  477. package/packages/piagent-core/extensions/task-state.js +140 -43
  478. package/packages/piagent-core/extensions/task-terminal-disposition.js +10 -0
  479. package/packages/piagent-core/extensions/trajectory-contract.ts +5 -0
  480. package/packages/piagent-core/extensions/verification-intelligence.js +109 -20
  481. package/packages/piagent-core/extensions/workflow-catalog.ts +98 -0
  482. package/packages/piagent-core/extensions/workspace-evidence-roots.js +52 -16
  483. package/packages/piagent-core/extensions/workspace-revision.js +48 -0
  484. package/packages/piagent-core/extensions/workspace-verification-snapshot.js +13 -0
  485. package/packages/piagent-core/package.json +3 -3
  486. package/packages/piagent-core/policies/base-policy.json +43 -2
  487. package/packages/piagent-core/policy/authority-manifest.v1.json +3 -3
  488. package/packages/piagent-core/prompts/be-to-fe.md +2 -8
  489. package/packages/piagent-core/prompts/plan.md +1 -1
  490. package/packages/piagent-core/prompts/platform-improve.md +2 -6
  491. package/packages/piagent-core/prompts/review.md +2 -7
  492. package/packages/piagent-core/prompts/scout.md +1 -1
  493. package/packages/piagent-core/prompts/task.md +4 -3
  494. package/packages/piagent-core/runtime/context/adaptive-planner.ts +7 -3
  495. package/packages/piagent-core/runtime/hooks/agent-start-hook.ts +60 -59
  496. package/packages/piagent-core/runtime/hooks/agent-start-types.ts +48 -0
  497. package/packages/piagent-core/runtime/hooks/completion-hook.ts +83 -89
  498. package/packages/piagent-core/runtime/hooks/input-hook.ts +98 -7
  499. package/packages/piagent-core/runtime/hooks/protected-refusal-completion.ts +86 -0
  500. package/packages/piagent-core/runtime/hooks/session-hooks.ts +5 -2
  501. package/packages/piagent-core/runtime/hooks/session-start-hook.ts +150 -19
  502. package/packages/piagent-core/runtime/hooks/tool-result-hook.ts +111 -92
  503. package/packages/piagent-core/runtime/hooks/tool-result-metadata.ts +9 -0
  504. package/packages/piagent-core/runtime/hooks/tool-result-navigation.ts +36 -0
  505. package/packages/piagent-core/runtime/hooks/tool-result-retrieval.ts +42 -0
  506. package/packages/piagent-core/runtime/hooks/tool-result-value-helpers.ts +66 -0
  507. package/packages/piagent-core/runtime/input/chat-images.ts +1 -1
  508. package/packages/piagent-core/runtime/inspection/activity-event-adapter.ts +1 -1
  509. package/packages/piagent-core/runtime/inspection/bounded-emission-guard.ts +286 -0
  510. package/packages/piagent-core/runtime/inspection/runtime-event-store.ts +37 -7
  511. package/packages/piagent-core/runtime/inspection/same-process-bridge-proof.ts +1 -1
  512. package/packages/piagent-core/runtime/inspection/task-handoff-history.ts +2 -2
  513. package/packages/piagent-core/runtime/inspection/task-subagent-tree.ts +27 -4
  514. package/packages/piagent-core/runtime/inspection/tool-failure-classification.ts +69 -11
  515. package/packages/piagent-core/runtime/inspection/webui-snapshot.ts +104 -22
  516. package/packages/piagent-core/runtime/inspection/workspace-file-reader.ts +2 -132
  517. package/packages/piagent-core/runtime/model/provider-wire-fingerprint.ts +20 -0
  518. package/packages/piagent-core/runtime/model/service-tier-runtime.ts +242 -0
  519. package/packages/piagent-core/runtime/orchestration/helper-lifecycle.ts +16 -12
  520. package/packages/piagent-core/runtime/orchestration/minimal-delegation-policy.ts +71 -0
  521. package/packages/piagent-core/runtime/orchestration/owned-work-budget.ts +28 -20
  522. package/packages/piagent-core/runtime/orchestration/role-policy.ts +27 -9
  523. package/packages/piagent-core/runtime/orchestration/subagent-tool-policy.ts +329 -0
  524. package/packages/piagent-core/runtime/policy/block-remedy.ts +0 -4
  525. package/packages/piagent-core/runtime/policy/source-worktree-transaction.ts +75 -14
  526. package/packages/piagent-core/runtime/product/activity-inspector.ts +6 -3
  527. package/packages/piagent-core/runtime/product/edit-verifier-timing.ts +26 -0
  528. package/packages/piagent-core/runtime/product/efficiency-metrics.ts +15 -7
  529. package/packages/piagent-core/runtime/product/operator-projections.ts +8 -3
  530. package/packages/piagent-core/runtime/product/task-usage-hooks.ts +78 -0
  531. package/packages/piagent-core/runtime/product/task-usage.ts +104 -0
  532. package/packages/piagent-core/runtime/quality/edit-freshness-guard.ts +102 -0
  533. package/packages/piagent-core/runtime/quality/exact-output-contract.ts +20 -10
  534. package/packages/piagent-core/runtime/quality/performance-assurance.ts +3 -3
  535. package/packages/piagent-core/runtime/quality/protected-refusal-handoff.ts +35 -0
  536. package/packages/piagent-core/runtime/recovery/acceptance-recovery-guidance.ts +21 -0
  537. package/packages/piagent-core/runtime/recovery/continuation-budget.ts +12 -3
  538. package/packages/piagent-core/runtime/recovery/diagnostic-delivery.ts +61 -0
  539. package/packages/piagent-core/runtime/recovery/handoff-projection.ts +196 -58
  540. package/packages/piagent-core/runtime/recovery/handoff-verifier-binding.ts +24 -0
  541. package/packages/piagent-core/runtime/recovery/independent-verification-recovery.ts +79 -0
  542. package/packages/piagent-core/runtime/recovery/pristine-task-policy-refresh.ts +91 -0
  543. package/packages/piagent-core/runtime/recovery/recovery-policy.ts +31 -40
  544. package/packages/piagent-core/runtime/recovery/resume-state.ts +120 -19
  545. package/packages/piagent-core/runtime/recovery/semantic-repair-handshake.ts +7 -13
  546. package/packages/piagent-core/runtime/recovery/task-evidence-coverage-refresh.ts +217 -0
  547. package/packages/piagent-core/runtime/registration/activity-inspector-command.ts +2 -1
  548. package/packages/piagent-core/runtime/registration/context-commands.ts +28 -10
  549. package/packages/piagent-core/runtime/registration/knowledge-tools.ts +9 -5
  550. package/packages/piagent-core/runtime/registration/operator-catalogs.ts +4 -9
  551. package/packages/piagent-core/runtime/registration/operator-request-intake.ts +49 -0
  552. package/packages/piagent-core/runtime/registration/policy-tools.ts +8 -6
  553. package/packages/piagent-core/runtime/registration/session-commands.ts +10 -8
  554. package/packages/piagent-core/runtime/registration/session-wait-tool.ts +54 -0
  555. package/packages/piagent-core/runtime/registration/task-completion-tools.ts +39 -20
  556. package/packages/piagent-core/runtime/registration/task-evidence-tools.ts +21 -12
  557. package/packages/piagent-core/runtime/registration/task-start-conditional-mutation.ts +45 -0
  558. package/packages/piagent-core/runtime/registration/task-start-guidance.ts +24 -15
  559. package/packages/piagent-core/runtime/registration/task-start-manifest.ts +54 -0
  560. package/packages/piagent-core/runtime/registration/task-start-tool.ts +79 -79
  561. package/packages/piagent-core/runtime/registration/workflow-commands.ts +64 -93
  562. package/packages/piagent-core/runtime/runtime-limits.ts +16 -2
  563. package/packages/piagent-core/runtime/session/adaptive-context-analysis.ts +461 -0
  564. package/packages/piagent-core/runtime/session/adaptive-context-governor.ts +464 -0
  565. package/packages/piagent-core/runtime/session/adaptive-context-ledger.ts +265 -0
  566. package/packages/piagent-core/runtime/session/completion-signals.ts +23 -0
  567. package/packages/piagent-core/runtime/session/message-signals.ts +6 -18
  568. package/packages/piagent-core/runtime/session/operator-request-carry.ts +44 -0
  569. package/packages/piagent-core/runtime/session/retrieval-evidence-runtime.ts +188 -0
  570. package/packages/piagent-core/runtime/session/runtime-state.ts +37 -39
  571. package/packages/piagent-core/runtime/session/source-checkout-read-grants.ts +35 -0
  572. package/packages/piagent-core/runtime/session/system-prompt.ts +76 -14
  573. package/packages/piagent-core/runtime/session/task-contract-presentation.ts +39 -0
  574. package/packages/piagent-core/runtime/session/uncertain-send-continuation.ts +231 -0
  575. package/packages/piagent-core/runtime/session/usage.ts +4 -3
  576. package/packages/piagent-core/runtime/tools/apply-patch-tool.ts +6 -6
  577. package/packages/piagent-core/runtime/tools/phase-tool-runtime.ts +1 -1
  578. package/packages/piagent-core/runtime/tools/phase-tools.ts +10 -9
  579. package/packages/piagent-core/runtime/tools/session-wait.ts +42 -0
  580. package/packages/piagent-core/runtime/tools/tool-groups.ts +22 -5
  581. package/packages/piagent-core/runtime/trajectory/trajectory-runtime.ts +192 -5
  582. package/packages/piagent-core/runtime/trajectory/trajectory-types.ts +3 -2
  583. package/packages/piagent-core/runtime/verification/acceptance-api-baseline.js +488 -0
  584. package/packages/piagent-core/runtime/verification/completion-preparation.ts +22 -0
  585. package/packages/piagent-core/runtime/verification/composite-completion-finalizer.ts +105 -0
  586. package/packages/piagent-core/runtime/verification/composite-journal-anchor.ts +181 -0
  587. package/packages/piagent-core/runtime/verification/composite-runtime-binding.ts +76 -0
  588. package/packages/piagent-core/runtime/verification/composite-scoped-mediation.ts +318 -0
  589. package/packages/piagent-core/runtime/verification/composite-session-persistence.ts +175 -0
  590. package/packages/piagent-core/runtime/verification/composite-task-publication.ts +273 -0
  591. package/packages/piagent-core/runtime/verification/exact-verifier-reuse.ts +101 -0
  592. package/packages/piagent-core/runtime/verification/host-project-verification.ts +71 -0
  593. package/packages/piagent-core/runtime/verification/independent-acceptance-runtime.ts +500 -0
  594. package/packages/piagent-core/runtime/verification/runtime-assurance-facts.ts +500 -0
  595. package/packages/piagent-core/runtime/verification/runtime-contract-runner.ts +107 -0
  596. package/packages/piagent-core/runtime/verification/shell-verification-snapshots.ts +56 -0
  597. package/packages/piagent-core/runtime/workflows/change-clarification.ts +61 -0
  598. package/packages/piagent-core/runtime/workflows/input-routing.ts +21 -14
  599. package/packages/piagent-core/runtime/workflows/runtime-intake-compaction.ts +201 -0
  600. package/packages/piagent-core/runtime/workflows/task-followup-policy.ts +163 -0
  601. package/packages/piagent-core/runtime/workflows/task-intake.ts +276 -169
  602. package/packages/piagent-core/runtime/workflows/task-repair-intent.ts +67 -0
  603. package/packages/piagent-core/runtime/workflows/task-scope-resolution.ts +83 -0
  604. package/packages/piagent-core/runtime/workflows/webui-runtime-command.ts +5 -2
  605. package/packages/piagent-core/runtime/workflows/webui-workflow.ts +39 -32
  606. package/packages/piagent-core/runtime/workflows/workflow-follow-up.ts +33 -0
  607. package/packages/piagent-core/security/workspace-file-reader.ts +132 -0
  608. package/packages/piagent-core/subagents/piagent-oracle.md +5 -3
  609. package/packages/piagent-core/subagents/piagent-planner.md +6 -4
  610. package/packages/piagent-core/subagents/piagent-reviewer.md +5 -3
  611. package/packages/piagent-core/subagents/piagent-scout.md +4 -2
  612. package/packages/piagent-core/subagents/piagent-worker.md +6 -4
  613. package/packages/piagent-webui/dist/client/assets/{MarkdownMessage-CxeZqTte.js → MarkdownMessage-DGk34zJT.js} +1 -1
  614. package/packages/piagent-webui/dist/client/assets/{index-BV-_03yl.css → index-DVahUVWy.css} +1 -1
  615. package/packages/piagent-webui/dist/client/assets/index-DiKRmCEP.js +176 -0
  616. package/packages/piagent-webui/dist/client/index.html +2 -2
  617. package/packages/piagent-webui/extension/dispatch-user-entry.ts +13 -0
  618. package/packages/piagent-webui/extension/piagent-webui.ts +13 -3
  619. package/packages/piagent-webui/extension/review-controller.ts +29 -6
  620. package/packages/piagent-webui/extension/same-session-bridge.ts +7 -8
  621. package/packages/piagent-webui/extension/session-stream-adapter.ts +88 -16
  622. package/packages/piagent-webui/extension/source-mutation-controller.ts +29 -3
  623. package/packages/piagent-webui/extension/source-open-controller.ts +29 -7
  624. package/packages/piagent-webui/extension/source-revert-controller.ts +26 -3
  625. package/packages/piagent-webui/gateway/gateway-events.ts +22 -5
  626. package/packages/piagent-webui/gateway/gateway-service.ts +7 -2
  627. package/packages/piagent-webui/gateway/gateway-session-stream.ts +170 -32
  628. package/packages/piagent-webui/gateway/rpc-ui-context.ts +34 -9
  629. package/packages/piagent-webui/gateway/runtime-command-controller.ts +46 -6
  630. package/packages/piagent-webui/gateway/runtime-session-controls.ts +17 -2
  631. package/packages/piagent-webui/gateway/session-catalog.ts +9 -3
  632. package/packages/piagent-webui/gateway/session-command-controller.ts +29 -9
  633. package/packages/piagent-webui/gateway/session-effective-options.ts +2 -9
  634. package/packages/piagent-webui/gateway/session-inspection-registry.ts +11 -2
  635. package/packages/piagent-webui/gateway/session-operation-lifecycle.ts +237 -0
  636. package/packages/piagent-webui/gateway/session-operation-retry-control.ts +38 -0
  637. package/packages/piagent-webui/gateway/session-operation-settlement.ts +28 -0
  638. package/packages/piagent-webui/gateway/session-operation-watchdog.ts +9 -2
  639. package/packages/piagent-webui/gateway/session-prompt-dispatch.ts +37 -0
  640. package/packages/piagent-webui/gateway/session-runtime-close.ts +36 -0
  641. package/packages/piagent-webui/gateway/session-runtime-factory.ts +183 -6
  642. package/packages/piagent-webui/gateway/session-runtime-ownership.ts +48 -0
  643. package/packages/piagent-webui/gateway/session-runtime-state.ts +24 -0
  644. package/packages/piagent-webui/gateway/session-runtime-supervisor.ts +118 -117
  645. package/packages/piagent-webui/ownership/session-lease-store.ts +5 -2
  646. package/packages/piagent-webui/server/core-inspection-provider.ts +75 -15
  647. package/packages/piagent-webui/server/loopback-server.ts +9 -7
  648. package/packages/piagent-webui/server/terminal-delivery-receipt.ts +144 -0
  649. package/packages/piagent-webui/server/transcript-projection.ts +150 -11
  650. package/packages/piagent-webui/shared/message-correlation.ts +25 -0
  651. package/schemas/approved-host-contracts.schema.json +973 -0
  652. package/schemas/benchmark-attempt-outcome.schema.json +303 -0
  653. package/schemas/benchmark-independent-verification-plan.schema.json +34 -0
  654. package/schemas/codex-relative-efficiency-v1.schema.json +155 -0
  655. package/schemas/composite-criterion.schema.json +788 -0
  656. package/schemas/contract-family-library.schema.json +28 -0
  657. package/schemas/contract-selection-recipe.schema.json +31 -0
  658. package/schemas/failure-evidence.schema.json +2 -2
  659. package/schemas/helper-request.schema.json +16 -4
  660. package/schemas/host-contract-plan.schema.json +25 -0
  661. package/schemas/piagent-webui/gateway-protocol-v1.schema.json +16 -2
  662. package/schemas/piagent-webui/runtime-command-v1.schema.json +26 -3
  663. package/schemas/piagent-webui/runtime-event-v2.schema.json +46 -5
  664. package/schemas/piagent-webui/session-live-state-v1.schema.json +2 -0
  665. package/schemas/piagent-webui/snapshot-v1.schema.json +3 -0
  666. package/schemas/piagent-webui/source-change-v1.schema.json +12 -0
  667. package/schemas/piagent-webui/subagent-tree-v1.schema.json +11 -1
  668. package/schemas/piagent-webui/transcript-v1.schema.json +2 -1
  669. package/schemas/project-profile.schema.json +1 -1
  670. package/schemas/public-contracts/codex-mcp-metadata-v1.schema.json +206 -0
  671. package/schemas/public-contracts/codex-mcp-metadata-v2.schema.json +228 -0
  672. package/schemas/public-contracts/codex-mcp-metadata-v3.schema.json +233 -0
  673. package/schemas/public-contracts/revocation-v1.schema.json +87 -0
  674. package/schemas/public-contracts/subscription-contract-v1.schema.json +76 -0
  675. package/schemas/scoped-project-verification-receipt-v2.schema.json +83 -0
  676. package/schemas/scoped-project-verification-receipt-v3.schema.json +295 -0
  677. package/schemas/scoped-verification-receipt-v1.schema.json +76 -0
  678. package/schemas/task-contract.schema.json +45 -0
  679. package/scripts/approve-independent-verification.mjs +57 -0
  680. package/scripts/benchmark-arm-observer.mjs +320 -0
  681. package/scripts/benchmark-budget-ipc.mjs +34 -0
  682. package/scripts/benchmark-budget-launcher.mjs +91 -0
  683. package/scripts/benchmark-budget-processes.mjs +133 -0
  684. package/scripts/benchmark-budget-publication.mjs +228 -0
  685. package/scripts/benchmark-budget-runtime.mjs +136 -0
  686. package/scripts/benchmark-candidate-ablation.mjs +265 -0
  687. package/scripts/benchmark-codex-journey.mjs +406 -0
  688. package/scripts/benchmark-independent-verification.mjs +628 -0
  689. package/scripts/benchmark-journey-outcome.mjs +92 -0
  690. package/scripts/benchmark-production-v3-human-review.mjs +192 -0
  691. package/scripts/benchmark-public-input-catalog.mjs +158 -0
  692. package/scripts/benchmark-registered-plan-author.mjs +355 -0
  693. package/scripts/benchmark-registered-plan-recipe-support.mjs +85 -0
  694. package/scripts/benchmark-registered-plan-recipes-backend.mjs +165 -0
  695. package/scripts/benchmark-registered-plan-recipes-data.mjs +164 -0
  696. package/scripts/benchmark-registered-plan-recipes-platform.mjs +165 -0
  697. package/scripts/benchmark-runner-completion.mjs +133 -0
  698. package/scripts/benchmark-runner-configuration.mjs +159 -0
  699. package/scripts/benchmark-runner-core.mjs +224 -387
  700. package/scripts/benchmark-runner-finalization.mjs +144 -27
  701. package/scripts/benchmark-runner-provider-boundary.mjs +44 -0
  702. package/scripts/benchmark-runner-schedule.mjs +256 -0
  703. package/scripts/benchmark-runner-support.mjs +136 -4
  704. package/scripts/benchmark-runner.mjs +95 -18
  705. package/scripts/benchmark-scoped-broker-custody.mjs +483 -0
  706. package/scripts/benchmark-scoped-docs-verifier.mjs +203 -0
  707. package/scripts/benchmark-scoped-frozen-qualification.mjs +676 -0
  708. package/scripts/benchmark-scoped-pi-router.mjs +196 -0
  709. package/scripts/benchmark-scoped-project-verification-receipt.mjs +49 -0
  710. package/scripts/benchmark-scoped-project-verifier.mjs +461 -0
  711. package/scripts/benchmark-scoped-session-custody.mjs +599 -0
  712. package/scripts/benchmark-scoped-session-factory.mjs +342 -0
  713. package/scripts/benchmark-scoped-tool-broker.mjs +523 -0
  714. package/scripts/benchmark-scoped-verification-supervisor.mjs +773 -0
  715. package/scripts/benchmark-session-evaluator.mjs +169 -0
  716. package/scripts/benchmark-session-provider-boundary.mjs +62 -0
  717. package/scripts/benchmark-session-usage.mjs +28 -0
  718. package/scripts/benchmark-session.mjs +343 -50
  719. package/scripts/benchmark-webui-journey.mjs +678 -0
  720. package/scripts/check-public-wording.mjs +46 -0
  721. package/scripts/configure-subagents.sh +42 -34
  722. package/scripts/fs4-readiness-evaluation.mjs +7 -1
  723. package/scripts/helper-evaluation.mjs +1 -1
  724. package/scripts/phase-tools-evaluation.mjs +1 -0
  725. package/scripts/pi-auto.sh +7 -1
  726. package/scripts/pi-usage-history.mjs +201 -11
  727. package/scripts/piagent-cli.mjs +8 -0
  728. package/scripts/private-holdout-readiness.mjs +7 -1
  729. package/scripts/public-evaluation-exposure.mjs +140 -0
  730. package/scripts/select-independent-verification.mjs +62 -0
  731. package/scripts/team-doctor.sh +1 -1
  732. package/scripts/typescript-loader.mjs +135 -1
  733. package/scripts/update-global.mjs +6 -7
  734. package/scripts/verify-local.sh +41 -55
  735. package/scripts/verify-release-identity.mjs +5 -3
  736. package/packages/piagent-webui/dist/client/assets/index-DynIMe8I.js +0 -176
@@ -1,9 +1,11 @@
1
+ import { observedFocusedTestSummary, retainFocusedVerification, unresolvedFocusedVerification } from "./acceptance-focused-verification.js";
1
2
  import fs from "node:fs";
2
3
  import os from "node:os";
3
4
  import path from "node:path";
4
5
  import crypto from "node:crypto";
5
6
  import { execFileSync } from "node:child_process";
6
7
  import { fileURLToPath } from "node:url";
8
+ import { apiBaselineCriterionEvidence as apiBaselineEvidence } from "../runtime/verification/acceptance-api-baseline.js";
7
9
  import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
8
10
  import { StringEnum } from "@earendil-works/pi-ai";
9
11
  import { Type } from "typebox";
@@ -17,6 +19,7 @@ import {
17
19
  unresolvedExpansionReason
18
20
  } from "./shell-reach.ts";
19
21
  import { extractShellWritePathCandidates, shellHasFileWriteRedirection } from "./shell-write-targets.js";
22
+ import { isProjectMutatingShellCommand, isReadOnlyTaskShellCommand } from "./readonly-inline-inspection.ts";
20
23
  import { commandMatchesVerifyPlan, createBashResultLedger, findMatchingObservedBashResult, readObservedBashResults } from "./runtime-evidence.js";
21
24
  import { findPackageRoot, findPlatformRoot, readJsonFile } from "./guard-io.js";
22
25
  import {
@@ -67,28 +70,25 @@ import {
67
70
  } from "./context-index-policy.js";
68
71
  import {
69
72
  DEFAULT_MAX_TASK_ATTEMPTS, activeSessionTask, bindSessionTask, createTaskRunId, hasGitEvidenceRoot, listTaskContracts,
70
- pathWithinChangeEvidenceRoot, priorTaskAttempts, repositoryFileManifest, repositoryFileManifestDetails, resolveTaskContract, safeTaskId, summarizeAttempt, taskContractValidationErrors, taskDigestMigrationArchiveStatus,
73
+ priorTaskAttempts, repositoryFileManifest, repositoryFileManifestDetails, resolveTaskContract, safeTaskId, summarizeAttempt, taskContractValidationErrors, taskDigestMigrationArchiveStatus,
71
74
  workPlanDependencyError, workingTreeSnapshot, workingTreeSnapshotHasUnavailableEvidence, writeTaskContract
72
75
  } from "./task-state.js";
73
- import { classifyRecordedVerificationFailure, classifyVerificationFailure, latestObservedVerification, meaningfulVerificationCommands, selectCompletionRecoveryClassification, selectVerificationPlan } from "./verification-intelligence.js";
76
+ import { classifyRecordedVerificationFailure, classifyVerificationFailure, latestObservedVerification, meaningfulVerificationCommands, recordedFailureForObservation, selectCompletionRecoveryClassification, selectVerificationPlan } from "./verification-intelligence.js";
74
77
  import { executionBackendToolDecision } from "./execution-backend.js";
75
78
  import { replayTaskCheckpoints } from "./task-journal.js";
76
79
  import type { FailureClassification } from "./failure-types.ts";
77
80
  import { recordCompletionAudit, recordMutationCheckpoint, recordTaskProgressCheckpoints, recordTaskStartCheckpoint, recordVerificationCheckpoint } from "./task-runtime-audit.js";
78
81
  import {
79
- applyAcceptanceRecoveryProvenance,
80
- acceptanceBaselineGuidance,
81
- acceptanceProofGuidance,
82
- acceptanceSemanticConflicts,
83
- buildAcceptanceReceipt,
84
- invalidateAcceptanceReceiptAfterMutation,
85
- refreshAcceptanceReceipt
82
+ applyAcceptanceRecoveryProvenance, acceptanceBaselineGuidance, acceptanceProofGuidance, acceptanceSemanticConflicts,
83
+ buildAcceptanceReceipt, invalidateAcceptanceReceiptAfterMutation, refreshAcceptanceReceipt
86
84
  } from "./acceptance-receipt.js";
87
85
  import { acceptanceLanguageAdapterForPath, isAcceptanceTestPath } from "./acceptance-language-adapters.js";
88
86
  import { allVerifyCommandsPassCurrentTree, changedSnapshotFiles, compactTaskDetails, mergeObservedTaskContext, passingVerifyCommandsForDigest, taskDeltaFilesFromSnapshot } from "./task-contract-view.js";
89
87
  import { applyRuntimeLifecycleObservation, runtimeLifecycleMode, workingTreeEvidenceDigest } from "./task-lifecycle.js";
90
88
  import { completeTaskDigestRefresh } from "./task-digest-migration.js";
91
89
  import { WORKING_TREE_DIGEST_ALGORITHM, isCurrentWorkingTreeDigest, workingTreeObservation, workingTreeSnapshotUsesCurrentAlgorithm } from "./working-tree-digest.js";
90
+ import { currentWorkspaceRevisionDigest } from "./workspace-revision.js";
91
+ import { captureWorkspaceVerificationSnapshot } from "./workspace-verification-snapshot.js";
92
92
  import { appendJsonlBounded } from "./state-retention.js";
93
93
  import { ensurePrivateStateDirectory, resolveLocalStatePath } from "./local-state-path.js";
94
94
  import { hasDurableContextEvidence } from "./context-evidence.js";
@@ -104,12 +104,17 @@ import {
104
104
  import { cleanSessionNameInput, currentSessionName, hasOperatorSessionName } from "../runtime/session/message-signals.ts";
105
105
  import { buildSemanticCompactionInstructions } from "../runtime/session/system-prompt.ts";
106
106
  import { buildContextPreflight, buildUsageSnapshot, formatContextPreflight, formatCount, formatPercent, formatUsageSnapshot } from "../runtime/session/usage.ts";
107
+ import { registerTaskUsageHooks } from "../runtime/product/task-usage-hooks.ts";
107
108
  import {
108
109
  formatToolResultCaptureStatus,
109
110
  readRecentToolResultCaptures
110
111
  } from "../runtime/session/tool-result-compaction.ts";
111
112
  import { RuntimeSessionState } from "../runtime/session/runtime-state.ts";
112
113
  import type { ObservedTaskContext } from "../runtime/session/runtime-state.ts";
114
+ import { reuseCurrentTreeExactVerifier } from "../runtime/verification/exact-verifier-reuse.ts";
115
+ import { IndependentAcceptanceRuntime } from "../runtime/verification/independent-acceptance-runtime.ts";
116
+ import { independentAcceptanceState } from "./acceptance-independent-registry.js";
117
+ import { independentVerificationRecovery } from "../runtime/recovery/independent-verification-recovery.ts";
113
118
  import {
114
119
  PIAGENT_TOOL_GROUPS,
115
120
  PIAGENT_TOOL_NAMES,
@@ -118,6 +123,7 @@ import {
118
123
  } from "../runtime/tools/tool-groups.ts";
119
124
  import type { PiagentToolGroup } from "../runtime/tools/tool-groups.ts";
120
125
  import { freshRequestParts, shortTaskLabel } from "../runtime/workflows/input-routing.ts";
126
+ import { completedFollowupAcceptanceEvidenceFiles } from "../runtime/workflows/task-followup-policy.ts";
121
127
  import {
122
128
  automaticAcceptanceCriteria,
123
129
  automaticReviewLenses,
@@ -141,7 +147,8 @@ import { readRuntimeVersionMetadata, RuntimeSnapshotCapture } from "../runtime/m
141
147
  import { recordRuntimeSnapshotTelemetry } from "../runtime/model/snapshot-telemetry.ts";
142
148
  import { captureAuthenticatedModelCatalogFromContext } from "../runtime/model/authenticated-catalog.ts";
143
149
  import { normalizeOpenAiCodexReasoningPayload } from "../runtime/model/openai-codex-reasoning.ts";
144
- import { buildOpenAiCodexWireFingerprint } from "../runtime/model/provider-wire-fingerprint.ts";
150
+ import { buildOpenAiCodexWireFingerprint, measureProviderPayload } from "../runtime/model/provider-wire-fingerprint.ts";
151
+ import { registerFastModeCommand, ServiceTierRuntime } from "../runtime/model/service-tier-runtime.ts";
145
152
  import { ModelRouteRuntime, readModelRouteEvents } from "../runtime/model/model-route-runtime.ts";
146
153
  import { parentRoutingModeFromEnvironment, routingObjectiveFromEnvironment } from "../runtime/model/model-route-policy.ts";
147
154
  import { ModelSelectionProvenanceTracker } from "../runtime/model/model-selection-provenance.ts";
@@ -155,17 +162,21 @@ import { PhaseToolRuntime, phaseToolModeFromEnvironment } from "../runtime/tools
155
162
  import { parseApplyPatchTargets, registerApplyPatchTool } from "../runtime/tools/apply-patch-tool.ts";
156
163
  import { authorityReplacementState, ensureTaskAuthorityResumePolicy } from "../runtime/policy/authority-resume-policy.ts";
157
164
  import { taskAuthorityDecision } from "../runtime/policy/task-authority-runtime.ts";
158
- import { selectRecoveryDecision } from "../runtime/recovery/recovery-policy.ts";
165
+ import { applyProofCapabilityHandoff, selectRecoveryDecision } from "../runtime/recovery/recovery-policy.ts";
159
166
  import type { RecoveryDecision } from "../runtime/recovery/recovery-policy.ts";
160
167
  import { inspectTaskResumeState } from "../runtime/recovery/resume-state.ts";
161
168
  import { SemanticRepairRuntime } from "../runtime/recovery/semantic-repair-runtime.ts";
162
169
  import { defaultRolePolicy } from "../runtime/orchestration/role-policy.ts";
163
170
  import { helpersMode } from "../runtime/orchestration/helper-lifecycle.ts";
171
+ import { evaluateDirectSubagentDispatch, recordDirectSubagentResult, reserveDirectSubagentDispatch, taskHelperUsageMode } from "../runtime/orchestration/subagent-tool-policy.ts";
164
172
  import { buildLiveTaskStatus, formatLiveTaskStatus } from "../runtime/product/operator-projections.ts";
165
173
  import { buildTaskEfficiencyMetrics } from "../runtime/product/efficiency-metrics.ts";
166
174
  import { performanceReviewToolDecision, performanceReviewToolKind } from "../runtime/quality/performance-assurance.ts";
167
175
  import { expectedModelMutationProof } from "../runtime/quality/model-mutation-proof.ts";
176
+ import { EditFreshnessGuard, editFreshnessModeFromEnvironment } from "../runtime/quality/edit-freshness-guard.ts";
168
177
  import { captureVerifierFileSnapshot } from "../runtime/inspection/verifier-snapshot-store.ts";
178
+ import { finalGateConfig } from "./acceptance-diagnostic-policy.ts";
179
+ import { fallbackBasePolicy } from "./fallback-base-policy.ts";
169
180
  import { prefixCompletions, registerPiagentTool, registerRuntimeCommand, registerRuntimeTool } from "../runtime/registration/extension-registration.ts";
170
181
  import { FRESH_COMMAND_ACTIONS, FRESH_COMMAND_HELP, ONBOARDING_COMMAND_ACTIONS, WORKFLOW_COMMAND_EXCLUSIONS } from "../runtime/registration/operator-catalogs.ts";
171
182
  import { registerPiagentStatusCommand } from "../runtime/registration/runtime-model-status.ts";
@@ -197,7 +208,6 @@ import type {
197
208
  ContextIndexSettings,
198
209
  ExecPolicyConfig,
199
210
  ExternalActionPolicyConfig,
200
- FinalGateConfig,
201
211
  MemorySettings,
202
212
  OrchestrationMode,
203
213
  OrchestrationPolicySettings,
@@ -232,7 +242,7 @@ type TaskStartParameters = {
232
242
  riskLane: "tiny" | "normal" | "high-risk";
233
243
  intakeMode?: "model" | "runtime";
234
244
  changeMode?: "source-change" | "read-only";
235
- mutationPolicy?: "required" | "forbidden";
245
+ mutationPolicy?: "required" | "allowed" | "forbidden";
236
246
  verifyGroup?: string;
237
247
  maxAttempts?: number;
238
248
  expectedOutput: string;
@@ -293,7 +303,6 @@ const TECH_OPTIONS: TechOption[] = [
293
303
  { id: "node-typescript", label: "Node TypeScript", role: "runtime", description: "Node.js TypeScript library/tooling project.", context7Query: "typescript node.js", topics: ["typescript", "node", "testing"] },
294
304
  { id: "python", label: "Python", role: "runtime", description: "Python app/library runtime.", context7Query: "python", topics: ["packaging", "typing", "testing"] }
295
305
  ];
296
-
297
306
  const PROFILE_TECH_ROLES: Record<string, TechRole[]> = {
298
307
  "web-frontend": ["frontend", "database"],
299
308
  "backend-api": ["backend", "database"],
@@ -307,7 +316,6 @@ const PROFILE_TECH_ROLES: Record<string, TechRole[]> = {
307
316
  docs: ["docs"],
308
317
  generic: ["runtime"]
309
318
  };
310
-
311
319
  const DEFAULT_MEMORY_SETTINGS: Required<MemorySettings> = {
312
320
  enabled: true,
313
321
  mode: "manual",
@@ -320,7 +328,6 @@ const DEFAULT_MEMORY_SETTINGS: Required<MemorySettings> = {
320
328
  maxInjectedChars: 4000,
321
329
  externalPackages: []
322
330
  };
323
-
324
331
  const DEFAULT_CONTEXT_INDEX_SETTINGS: Required<ContextIndexSettings> = {
325
332
  enabled: true,
326
333
  path: CONTEXT_INDEX_FILE,
@@ -331,21 +338,19 @@ const DEFAULT_CONTEXT_INDEX_SETTINGS: Required<ContextIndexSettings> = {
331
338
  includeTechStack: true,
332
339
  includeMemoryPointers: true
333
340
  };
334
-
335
341
  const DEFAULT_RUNTIME_POLICY: Required<RuntimePolicySettings> = {
336
342
  execPolicy: "enforce",
337
343
  contextBudget: "enforce",
338
344
  toolRegistry: "advisory",
339
345
  finalGate: "enforce"
340
346
  };
341
-
342
347
  const DEFAULT_ORCHESTRATION_POLICY: ResolvedOrchestrationPolicy = {
343
348
  defaultMode: "solo-first",
344
- maxConcurrentSubagents: 2,
349
+ maxConcurrentSubagents: 1,
345
350
  defaultReviewLenses: ["correctness", "tests", "scope"],
346
351
  roleModelGuidance: {
347
352
  planner: "Use the strongest available model for decomposition, architecture, risk, and acceptance criteria.",
348
- worker: "Use the fastest reliable model for a bounded, already-planned single write set.",
353
+ worker: "Disabled by default. The parent model owns all implementation and mutation.",
349
354
  reviewer: "Use a model or thinking setting decorrelated from the worker when review quality matters.",
350
355
  watchdog: "Use a strong model only for final risk review, security, release, or high-impact changes."
351
356
  },
@@ -357,14 +362,13 @@ const DEFAULT_ORCHESTRATION_POLICY: ResolvedOrchestrationPolicy = {
357
362
  readBeforeTask: true
358
363
  },
359
364
  rules: [
360
- "Default to one parent agent; do not start a swarm for ordinary implementation.",
361
- "Use subagents only for bounded read-only scout, planning, review, or a single approved worker.",
362
- "Parallel read-only review is allowed when the diff is non-trivial; parallel writers require explicit user approval and isolation.",
365
+ "Default to the parent model working directly; a helper is an exceptional token optimization, not a reasoning phase.",
366
+ "Use at most one fresh read-only helper only when runtime evidence proves at least two independent lanes and at least 30% projected net token savings.",
367
+ "Never delegate implementation, inherit parent history, retry a deterministic helper failure, or run parallel helpers/writers.",
363
368
  "Treat Field Guide memory as advisory; verify every durable fact against current repository files.",
364
369
  "Keep review lenses explicit so cheap review work catches drift before release."
365
370
  ]
366
371
  };
367
-
368
372
  const PERMISSION_PROFILE_MODES = ["read-only", "workspace-write", "trusted-full-access"] as const;
369
373
  const PERMISSION_PROFILE_ALIASES: Record<string, PermissionProfileMode> = {
370
374
  readonly: "read-only",
@@ -385,183 +389,11 @@ const WRITE_TOOL_NAMES = new Set(["write", "edit"]);
385
389
  const SHELL_TOOL_NAMES = new Set(["bash", "shell", "exec"]);
386
390
  const MAX_MCP_PROXY_ARGS_CHARS = 131_072;
387
391
  const SESSION_PERMISSION_OVERRIDES = new Map<string, PermissionProfileMode>();
388
-
389
- // The policy used when `policies/base-policy.json` cannot be read. It runs in
390
- // exactly the case where something is already wrong, so it must never be the
391
- // looser of the two: this copy had drifted behind the file and silently dropped
392
- // `.pi/piagent-state/**` -- the guard's own state -- along with the `sudo ` and
393
- // `chmod -R 777` blocks. A missing policy file is a reason to be stricter, not a
394
- // quiet downgrade. `tests/policy-core.test.mjs` fails if this drifts again.
395
- const DEFAULT_POLICY: BasePolicy = {
396
- protectedPaths: [".git/**", "**/auth.json", "**/.env", "**/.env.*", "**/node_modules/**", "**/dist/**", ".pi/piagent-state/**", ".pi/settings.json", ".pi/piagent-profile.json", ".pi/piagent-profile.lock.json", CONTEXT_INDEX_FILE],
397
- shellProtectedPaths: [".git/**", "**/auth.json", "**/.env", "**/.env.*", ".pi/piagent-state/**", ".pi/settings.json", ".pi/piagent-profile.json", ".pi/piagent-profile.lock.json", CONTEXT_INDEX_FILE],
398
- blockedCommandPatterns: ["rm -rf /", "rm -rf ~", "rm -rf $HOME", "git reset --hard", "git clean -fd", "sudo ", "chmod -R 777"],
399
- requireConfirmationPatterns: ["deploy", "release", "publish", "migration", "gh pr merge", "git push"],
400
- defaultRequiredContext: ["AGENTS.md", "README.md"],
401
- permissionProfiles: {
402
- defaultMode: "workspace-write",
403
- allowedModes: ["read-only", "workspace-write", "trusted-full-access"]
404
- },
405
- execPolicy: {
406
- defaultMode: "enforce",
407
- bannedPrefixSuggestions: [
408
- ["python"],
409
- ["python3"],
410
- ["node"],
411
- ["node", "-e"],
412
- ["bash"],
413
- ["bash", "-lc"],
414
- ["sh"],
415
- ["sh", "-c"],
416
- ["zsh"],
417
- ["zsh", "-lc"],
418
- ["git"],
419
- ["sudo"],
420
- ["env"]
421
- ],
422
- rules: [
423
- {
424
- id: "prompt-git-add-broad",
425
- action: "prompt",
426
- match: "regex",
427
- value: "(?:^|\\s)git\\s+(?:-C\\s+\\S+\\s+)?add\\s+(?:(?:--all|-A)(?:\\s+(?:\\.|:/))?|--\\s+(?:\\.|:/)|(?:\\.|:/))(?:\\s|$)",
428
- reason: "Broad git staging can include unrelated or sensitive changes; inspect git status/diff and confirm the exact scope first."
429
- }
430
- ]
431
- },
432
- contextBudget: {
433
- defaultMode: "enforce",
434
- contextDeltaShadow: "sample",
435
- maxContextFileChars: 50000,
436
- maxMemoryFileChars: 20000,
437
- maxManifestFiles: 80,
438
- warnFragmentChars: 4000
439
- },
440
- toolRegistry: {
441
- defaultMode: "advisory",
442
- alwaysAllowedTools: [
443
- "piagent_tools",
444
- "piagent_context_engine",
445
- "piagent_context",
446
- "piagent_permission_status",
447
- "piagent_exec_policy_check",
448
- "piagent_context_budget",
449
- "piagent_tool_policy_check",
450
- "piagent_task_gate_check",
451
- "piagent_usage_snapshot",
452
- "piagent_orchestration_policy",
453
- "piagent_memory_status",
454
- "piagent_memory_note",
455
- "piagent_memory_search",
456
- "piagent_memory_citation_record",
457
- "piagent_context_index_status",
458
- "piagent_context_index_record",
459
- "piagent_context_index_search",
460
- "piagent_profile_options",
461
- "piagent_profile_apply",
462
- "piagent_profile_tech_options",
463
- "piagent_profile_tech_apply",
464
- "piagent_profile_tech_context_record",
465
- "piagent_project_onboarding_record",
466
- "piagent_task_start",
467
- "piagent_task_progress",
468
- "piagent_source_checkout",
469
- "piagent_context_record",
470
- "piagent_verify_record",
471
- "piagent_trace_record"
472
- ],
473
- toolCapabilities: {
474
- bash: ["shell"],
475
- shell: ["shell"],
476
- exec: ["shell"],
477
- read: ["filesystem-readonly"],
478
- grep: ["filesystem-readonly"],
479
- find: ["filesystem-readonly"],
480
- ls: ["filesystem-readonly"],
481
- write: ["filesystem-write"],
482
- edit: ["filesystem-write"],
483
- apply_patch: ["filesystem-write"],
484
- browser: ["browser"],
485
- github: ["github"]
486
- }
487
- },
488
- externalActionPolicy: {
489
- defaultMode: "enforce",
490
- providerKeywords: [
491
- "github",
492
- "gitlab",
493
- "bitbucket",
494
- "vercel",
495
- "netlify",
496
- "cloudflare",
497
- "aws",
498
- "gcp",
499
- "azure",
500
- "slack",
501
- "teams",
502
- "jira",
503
- "linear",
504
- "notion",
505
- "figma",
506
- "stripe",
507
- "supabase",
508
- "firebase"
509
- ],
510
- writeVerbs: [
511
- "add",
512
- "approve",
513
- "archive",
514
- "assign",
515
- "close",
516
- "comment",
517
- "create",
518
- "delete",
519
- "deploy",
520
- "dispatch",
521
- "merge",
522
- "open",
523
- "post",
524
- "publish",
525
- "push",
526
- "release",
527
- "remove",
528
- "reopen",
529
- "run",
530
- "send",
531
- "submit",
532
- "trigger",
533
- "update",
534
- "upload",
535
- "write"
536
- ],
537
- safeVerbs: [
538
- "fetch",
539
- "find",
540
- "get",
541
- "inspect",
542
- "list",
543
- "read",
544
- "search",
545
- "show",
546
- "view"
547
- ]
548
- },
549
- finalGate: {
550
- defaultMode: "enforce",
551
- requireTaskContract: true,
552
- requireContextManifest: true,
553
- requireVerifyEvidence: true,
554
- requireTrace: true,
555
- requirePassingVerify: true
556
- },
557
- orchestrationPolicy: DEFAULT_ORCHESTRATION_POLICY
558
- };
559
-
392
+ const DEFAULT_POLICY = fallbackBasePolicy(CONTEXT_INDEX_FILE, DEFAULT_ORCHESTRATION_POLICY);
560
393
  // Which platform supplies the adapters is fixed by where this file is installed,
561
394
  // so it is resolved once here rather than threaded through every profile load.
562
395
  const PLATFORM_ROOT = findPlatformRoot(path.dirname(fileURLToPath(import.meta.url)));
563
396
  const UPDATE_CHECK_MODULE = fileURLToPath(new URL("./update-check.js", import.meta.url));
564
-
565
397
  // The installed version, read from the package this file ships in. A maintainer
566
398
  // working in the repository is not running a release and has nothing to update
567
399
  // to, so only a tree Pi or npm placed is given a version to compare.
@@ -569,7 +401,6 @@ function installedPlatformVersion(): string | undefined {
569
401
  if (!isInstalledPlatform(PLATFORM_ROOT)) return undefined;
570
402
  return readJsonFile<{ version?: string }>(path.join(PLATFORM_ROOT, "package.json"))?.version;
571
403
  }
572
-
573
404
  function updateAvailabilityNotice(): string | undefined {
574
405
  const installed = installedPlatformVersion();
575
406
  if (!installed) return undefined;
@@ -1016,7 +847,12 @@ function inspectPathInputsFromInput(
1016
847
  const seen = new Set<string>();
1017
848
  const walked = walkStringInputs(input, [], 0, includeFilesystemContentFields);
1018
849
  for (const item of walked.items) {
1019
- const normalized = normalizeRelative(cwd, item.value);
850
+ const relative = normalizeRelative(cwd, item.value);
851
+ // `path.relative(root, root)` is the empty string. Treat that canonical
852
+ // project-root spelling as `.` so a capability such as `**/*` admits
853
+ // `ls .` and an absolute path equal to cwd. The empty candidate matched no
854
+ // scope and made fresh helpers unable to inspect even their own project.
855
+ const normalized = relative === "" ? "." : relative;
1020
856
  if (normalized === undefined) continue;
1021
857
  const key = `${item.field}\0${normalized}`;
1022
858
  if (seen.has(key)) continue;
@@ -1126,6 +962,7 @@ function evaluatePathLikeToolAccess(
1126
962
  forceScopeAware?: boolean;
1127
963
  forceWrite?: boolean;
1128
964
  allowAmbiguousFilesystemContentFields?: boolean;
965
+ sourceCheckoutReadRoots?: string[];
1129
966
  } = {}
1130
967
  ): { block: boolean; reason?: string } {
1131
968
  const scopeAwareTool = options.forceScopeAware === true || ["read", "write", "edit", "grep", "find", "ls"].includes(toolName)
@@ -1167,9 +1004,13 @@ function evaluatePathLikeToolAccess(
1167
1004
  }
1168
1005
 
1169
1006
  for (const item of inspectedPaths) {
1007
+ const fieldAccessMode = filesystemFieldAccessMode(toolName, item.field, writesFilesystem);
1008
+ const sourceCheckoutReadRoot = fieldAccessMode === "read"
1009
+ ? grantedSourceCheckoutRootForPath(cwd, item.path, options.sourceCheckoutReadRoots ?? [])
1010
+ : undefined;
1170
1011
  if (scopeAwareTool && isFilesystemScopeField(item.field)) {
1171
1012
  const boundary = inspectRepositoryPathBoundary(cwd, item.path);
1172
- if (boundary.reason) return { block: true, reason: `Blocked ${toolName}: ${boundary.reason}` };
1013
+ if (boundary.reason && !sourceCheckoutReadRoot) return { block: true, reason: `Blocked ${toolName}: ${boundary.reason}` };
1173
1014
  }
1174
1015
  const resolvedPath = resolveRepositoryPathCandidate(cwd, item.path);
1175
1016
  const readMatched = matchesProtectedPath(item.path, readProtectedPaths)
@@ -1181,7 +1022,6 @@ function evaluatePathLikeToolAccess(
1181
1022
  };
1182
1023
  }
1183
1024
 
1184
- const fieldAccessMode = filesystemFieldAccessMode(toolName, item.field, writesFilesystem);
1185
1025
  if (fieldAccessMode === "write") {
1186
1026
  const readOnlyMatched = matchesProtectedPath(item.path, readOnlyPaths)
1187
1027
  ?? (resolvedPath ? matchesProtectedPath(resolvedPath, readOnlyPaths) : undefined);
@@ -1205,7 +1045,8 @@ function evaluatePathLikeToolAccess(
1205
1045
  reason: `Blocked ${toolName} write outside resolved filesystem scope from ${item.field}: ${item.path}`
1206
1046
  };
1207
1047
  }
1208
- } else if (scopeAwareTool && filesystemRead && isFilesystemScopeField(item.field) && !matchesAnyPath(item.path, filesystemRead)) {
1048
+ } else if (scopeAwareTool && filesystemRead && isFilesystemScopeField(item.field)
1049
+ && !sourceCheckoutReadRoot && !matchesAnyPath(item.path, filesystemRead)) {
1209
1050
  return {
1210
1051
  block: true,
1211
1052
  reason: `Blocked ${toolName} read outside resolved filesystem scope from ${item.field}: ${item.path}`
@@ -1236,6 +1077,21 @@ function evaluatePathLikeToolAccess(
1236
1077
  return { block: false };
1237
1078
  }
1238
1079
 
1080
+ function grantedSourceCheckoutRootForPath(cwd: string, candidate: string, roots: string[]): string | undefined {
1081
+ if (roots.length === 0) return undefined;
1082
+ const absolute = path.resolve(cwd, normalizePathCandidate(candidate));
1083
+ let canonical: string;
1084
+ try {
1085
+ canonical = fs.realpathSync.native(absolute);
1086
+ } catch {
1087
+ return undefined;
1088
+ }
1089
+ return roots.find((root) => {
1090
+ const relative = path.relative(root, canonical);
1091
+ return relative === "" || (relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative));
1092
+ });
1093
+ }
1094
+
1239
1095
  function stateRoot(cwd: string): string {
1240
1096
  return path.join(cwd, ".pi", "piagent-state");
1241
1097
  }
@@ -1437,16 +1293,6 @@ function externalActionPolicyConfig(policy: BasePolicy): Required<ExternalAction
1437
1293
  };
1438
1294
  }
1439
1295
 
1440
- function finalGateConfig(policy: BasePolicy): Required<FinalGateConfig> {
1441
- return {
1442
- defaultMode: policy.finalGate?.defaultMode ?? DEFAULT_POLICY.finalGate?.defaultMode ?? "enforce",
1443
- requireTaskContract: policy.finalGate?.requireTaskContract ?? true,
1444
- requireContextManifest: policy.finalGate?.requireContextManifest ?? true,
1445
- requireVerifyEvidence: policy.finalGate?.requireVerifyEvidence ?? true,
1446
- requireTrace: policy.finalGate?.requireTrace ?? true,
1447
- requirePassingVerify: policy.finalGate?.requirePassingVerify ?? true
1448
- };
1449
- }
1450
1296
 
1451
1297
  function boundedInteger(value: unknown, fallback: number, minimum: number, maximum: number): number {
1452
1298
  const numberValue = typeof value === "number" ? value : Number(value);
@@ -1513,7 +1359,7 @@ function resolveOrchestrationPolicy(profile: ProjectProfile, policy: BasePolicy)
1513
1359
  };
1514
1360
  return {
1515
1361
  defaultMode: normalizeOrchestrationMode(configured.defaultMode, defaultPolicy.defaultMode),
1516
- maxConcurrentSubagents: boundedInteger(configured.maxConcurrentSubagents, defaultPolicy.maxConcurrentSubagents, 0, 6),
1362
+ maxConcurrentSubagents: Math.min(1, boundedInteger(configured.maxConcurrentSubagents, defaultPolicy.maxConcurrentSubagents, 0, 1)),
1517
1363
  defaultReviewLenses: normalizeReviewLenses(configured.defaultReviewLenses, defaultPolicy.defaultReviewLenses),
1518
1364
  roleModelGuidance,
1519
1365
  fieldGuide: {
@@ -1839,56 +1685,14 @@ function isTaskMutationTool(toolName: string, input: Record<string, unknown>): b
1839
1685
  .some((token) => tokens.has(token));
1840
1686
  }
1841
1687
 
1842
- function isReadOnlyTaskShellCommand(
1843
- command: string,
1844
- segments: Array<{ words: string[] }>
1845
- ): boolean {
1846
- if (/[<>]|`|\$\(/.test(command)) {
1847
- return false;
1688
+ function shellTouchesGrantedSourceCheckout(cwd: string, command: string, roots: string[]): boolean {
1689
+ if (roots.length === 0) return false;
1690
+ for (const root of roots) {
1691
+ const relative = path.relative(cwd, root).split(path.sep).join("/");
1692
+ if (command.includes(root) || (relative && command.includes(relative))) return true;
1848
1693
  }
1849
- const safeCommands = new Set(["pwd", "ls", "find", "rg", "grep", "cat", "sed", "head", "tail", "wc", "stat", "file", "test", "[", "which"]);
1850
- const safeGitSubcommands = new Set(["status", "diff", "log", "show", "ls-files", "rev-parse"]);
1851
- return segments.length > 0 && segments.every((segment) => {
1852
- const words = segment.words.filter(Boolean);
1853
- const executable = path.basename(words[0] ?? "");
1854
- if (executable === "sed" && words.some((word) => /^-.*i/.test(word))) return false;
1855
- if (executable === "find" && words.some((word) => ["-delete", "-exec", "-execdir", "-ok", "-okdir", "-fprint", "-fprint0", "-fprintf", "-fls"].includes(word))) return false;
1856
- if (safeCommands.has(executable)) return true;
1857
- if (executable === "git") return safeGitSubcommands.has(words[1] ?? "");
1858
- if (executable === "command") return words[1] === "-v";
1859
- return false;
1860
- });
1861
- }
1862
-
1863
- const PROJECT_MUTATING_EXECUTABLES = new Set([
1864
- "apply_patch", "bash", "chmod", "chown", "cp", "dd", "install", "ln", "make", "mkdir", "mv", "prename", "rename",
1865
- "node", "patch", "perl", "php", "python", "python3", "rm", "rmdir", "rsync", "ruby", "scp", "sh",
1866
- "tee", "touch", "truncate", "zsh"
1867
- ]);
1868
-
1869
- function isProjectMutatingShellCommand(command: string, segments: Array<{ words: string[] }>): boolean {
1870
- if (shellHasFileWriteRedirection(command)) return true;
1871
- const noAliases = new Map<string, string>();
1872
- for (const segment of segments) {
1873
- const words = segment.words.filter(Boolean);
1874
- if (words.length === 0) continue;
1875
- if (externalExecutableIndex(words, PROJECT_MUTATING_EXECUTABLES, noAliases) !== undefined) return true;
1876
- const executable = path.basename(words[0] ?? "").toLowerCase();
1877
- if (executable === "find" && words.some((word) => ["-delete", "-exec", "-execdir", "-ok", "-okdir", "-fprint", "-fprint0", "-fprintf", "-fls"].includes(word))) return true;
1878
- if (executable === "sed" && words.some((word) => /^-[^-]*i/.test(word) || word === "--in-place" || word.startsWith("--in-place="))) return true;
1879
- if (executable === "git") {
1880
- const subcommand = words.slice(1).find((word, index, values) => {
1881
- if (!word.startsWith("-")) return index === 0 || !["-C", "-c", "--git-dir", "--work-tree"].includes(values[index - 1]);
1882
- return false;
1883
- });
1884
- if (["apply", "checkout", "clean", "mv", "reset", "restore", "rm", "switch"].includes(subcommand ?? "")) return true;
1885
- }
1886
- if (["npm", "pnpm", "yarn", "bun"].includes(executable)) {
1887
- const subcommand = words.find((word, index) => index > 0 && !word.startsWith("-"));
1888
- if (["add", "ci", "install", "link", "remove", "uninstall", "update", "upgrade"].includes(subcommand ?? "")) return true;
1889
- }
1890
- }
1891
- return false;
1694
+ return extractShellPathCandidates(command)
1695
+ .some((candidate) => Boolean(grantedSourceCheckoutRootForPath(cwd, normalizeRelative(cwd, candidate) ?? candidate, roots)));
1892
1696
  }
1893
1697
 
1894
1698
  const EXPLICIT_SHELL_MUTATORS = new Set([
@@ -2062,18 +1866,20 @@ function recordObservedTaskVerification(
2062
1866
  },
2063
1867
  pendingContext: ObservedTaskContext[],
2064
1868
  maxManifestFiles: number, shellSnapshotBefore?: Record<string, string>,
2065
- eventTree?: ReturnType<typeof workingTreeObservation>,
2066
- readProtectedPaths: string[] = []
1869
+ eventTree?: ReturnType<typeof captureWorkspaceVerificationSnapshot>,
1870
+ readProtectedPaths: string[] = [], preWorkspaceRevisionDigest?: string, diagnosticFocused = false
2067
1871
  ): TaskContract | undefined {
2068
1872
  const task = activeSessionTask(ctx.cwd, ctx.sessionManager.getSessionId()) as TaskContract | undefined;
2069
1873
  if (!task || task.trace.outcome !== "pending") return;
2070
1874
  const command = String(observed.normalizedCommand ?? observed.command ?? "").trim();
2071
1875
  const observedAtMs = Date.parse(observed.recordedAt ?? "");
2072
1876
  const taskCreatedAtMs = Date.parse(task.createdAt);
1877
+ const matchedProfileCommand = commandMatchesVerifyPlan(command, task.verifyCommands);
1878
+ const focusedTest = diagnosticFocused && observedFocusedTestSummary(observed.outputText);
2073
1879
  if (
2074
1880
  !command
2075
1881
  || !observed.commandHash
2076
- || !commandMatchesVerifyPlan(command, task.verifyCommands)
1882
+ || (!matchedProfileCommand && !focusedTest)
2077
1883
  || !Number.isFinite(observedAtMs)
2078
1884
  || !Number.isFinite(taskCreatedAtMs)
2079
1885
  || observedAtMs < taskCreatedAtMs
@@ -2082,6 +1888,7 @@ function recordObservedTaskVerification(
2082
1888
  if (!eventTree?.proofCapable) return;
2083
1889
  const currentDigests = eventTree.snapshot as Record<string, string>;
2084
1890
  const currentDigest = eventTree.digest;
1891
+ const workspaceRevisionDigest = eventTree.workspaceRevisionDigest ?? undefined;
2085
1892
  const preWorkingTreeDigest = shellSnapshotBefore && workingTreeSnapshotUsesCurrentAlgorithm(shellSnapshotBefore) ? workingTreeEvidenceDigest(shellSnapshotBefore) : undefined;
2086
1893
  const exitCode = Number.isInteger(observed.exitCode) ? observed.exitCode as number : observed.isError ? 1 : 0;
2087
1894
  const classification = classifyVerificationFailure(observed.outputText, exitCode);
@@ -2089,6 +1896,7 @@ function recordObservedTaskVerification(
2089
1896
  evidence.command.trim() === command
2090
1897
  && evidence.exitCode === exitCode
2091
1898
  && evidence.workingTreeDigest === currentDigest && evidence.observedAt === observed.recordedAt
1899
+ && evidence.workspaceRevisionDigest === workspaceRevisionDigest && evidence.preWorkspaceRevisionDigest === preWorkspaceRevisionDigest
2092
1900
  ));
2093
1901
  const contextAdded = mergeObservedTaskContext(task, pendingContext, maxManifestFiles, redactText);
2094
1902
  if (!duplicate) {
@@ -2097,16 +1905,17 @@ function recordObservedTaskVerification(
2097
1905
  task.verifyEvidence.push({
2098
1906
  command: redactText(command),
2099
1907
  exitCode,
2100
- summary: `Runtime observed configured verifier exit ${exitCode} (${classification.category}${classification.retryable ? ", retryable" : ""}).`,
1908
+ summary: `Runtime observed ${matchedProfileCommand ? "configured" : "focused"} verifier exit ${exitCode} (${classification.category}${classification.retryable ? ", retryable" : ""}).`,
2101
1909
  recordedAt: evidenceRecordedAt,
2102
1910
  observed: true,
2103
1911
  observedAt,
2104
1912
  isError: observed.isError === true,
2105
- matchedProfileCommand: true,
1913
+ matchedProfileCommand,
2106
1914
  preWorkingTreeDigest,
2107
- workingTreeDigest: currentDigest
1915
+ workingTreeDigest: currentDigest,
1916
+ preWorkspaceRevisionDigest, workspaceRevisionDigest
2108
1917
  });
2109
- task.verifyEvidence = task.verifyEvidence.slice(-100);
1918
+ task.verifyEvidence = diagnosticFocused ? retainFocusedVerification(task.verifyEvidence, currentDigest, workspaceRevisionDigest) : task.verifyEvidence.slice(-100);
2110
1919
  try {
2111
1920
  captureVerifierFileSnapshot({
2112
1921
  projectRoot: ctx.cwd, taskId: task.taskId, taskRunId: task.taskRunId, sessionId: task.sessionId,
@@ -2119,18 +1928,20 @@ function recordObservedTaskVerification(
2119
1928
  }
2120
1929
  }
2121
1930
 
2122
- const hasChanges = taskChangedFileEvidence(ctx.cwd, task, currentDigests).expected.length > 0;
2123
- const allPassing = hasChanges && allVerifyCommandsPassCurrentTree(task, currentDigest);
2124
- const lifecycle = hasChanges
1931
+ const taskLocalDelta = taskChangedFileEvidence(ctx.cwd, task, currentDigests).expected;
1932
+ const hasChanges = taskLocalDelta.length > 0;
1933
+ const verificationCanSettleSourceTask = hasChanges || task.mutationPolicy === "allowed";
1934
+ const allPassing = verificationCanSettleSourceTask && allVerifyCommandsPassCurrentTree(task, currentDigest, workspaceRevisionDigest ?? null);
1935
+ const lifecycle = verificationCanSettleSourceTask
2125
1936
  ? applyRuntimeLifecycleObservation(task, allPassing ? "verification-complete" : "verification-pending", nowIso())
2126
1937
  : { changed: false, mode: runtimeLifecycleMode(task) };
2127
1938
  const acceptance = refreshAcceptanceReceipt(task, {
2128
- cwd: ctx.cwd,
2129
- changedFiles: taskChangedFileEvidence(ctx.cwd, task, currentDigests).expected,
1939
+ cwd: ctx.cwd, apiBaselineEvidence,
1940
+ changedFiles: taskAcceptanceEvidenceFiles(ctx.cwd, task, currentDigests, taskLocalDelta),
2130
1941
  currentWorkingTreeDigest: currentDigest
2131
1942
  });
2132
1943
  task.acceptanceReceipt = acceptance.task.acceptanceReceipt;
2133
- if (!task.workingTreeDigestMigration || (shellSnapshotBefore && changedSnapshotFiles(shellSnapshotBefore, currentDigests).length === 0)) Object.assign(task, completeTaskDigestRefresh(task, currentDigest));
1944
+ if (!task.workingTreeDigestMigration || (shellSnapshotBefore && changedSnapshotFiles(shellSnapshotBefore, currentDigests).length === 0)) Object.assign(task, completeTaskDigestRefresh(task, currentDigest, workspaceRevisionDigest ?? null));
2134
1945
  if (duplicate && contextAdded.length === 0 && !lifecycle.changed) return task;
2135
1946
 
2136
1947
  const written = writeTask(ctx.cwd, task);
@@ -2160,7 +1971,8 @@ function recordObservedTaskVerification(
2160
1971
  retryable: classification.retryable,
2161
1972
  failureClassification: classification,
2162
1973
  preWorkingTreeDigest,
2163
- workingTreeDigest: currentDigest
1974
+ workingTreeDigest: currentDigest,
1975
+ preWorkspaceRevisionDigest, workspaceRevisionDigest
2164
1976
  }
2165
1977
  });
2166
1978
  return written;
@@ -2210,14 +2022,14 @@ function completionTaskProjection(
2210
2022
  failureReason: undefined,
2211
2023
  ruledOut: undefined,
2212
2024
  trace: {
2213
- outcome: "completed",
2025
+ outcome: "completed" as const,
2214
2026
  notes: "Runtime finalized from observed context, working-tree changes, current verification, and completed work-plan evidence.",
2215
2027
  recordedAt: nowIso()
2216
2028
  }
2217
2029
  };
2218
2030
  return refreshAcceptanceReceipt(projected, {
2219
- cwd,
2220
- changedFiles,
2031
+ cwd, apiBaselineEvidence,
2032
+ changedFiles: taskAcceptanceEvidenceFiles(cwd, projected, finalFileDigests, changedFiles),
2221
2033
  currentWorkingTreeDigest: workingTreeEvidenceDigest(finalFileDigests)
2222
2034
  }).task as TaskContract;
2223
2035
  }
@@ -3630,6 +3442,20 @@ function taskChangedFileEvidence(
3630
3442
  };
3631
3443
  }
3632
3444
 
3445
+ function taskAcceptanceEvidenceFiles(
3446
+ cwd: string,
3447
+ task: TaskContract,
3448
+ currentDigests: Record<string, string>,
3449
+ taskLocalDelta: string[] = taskChangedFileEvidence(cwd, task, currentDigests).expected
3450
+ ): string[] {
3451
+ return completedFollowupAcceptanceEvidenceFiles(
3452
+ task,
3453
+ listTaskContracts(cwd) as TaskContract[],
3454
+ taskLocalDelta,
3455
+ currentDigests
3456
+ );
3457
+ }
3458
+
3633
3459
  function exactReviewPathCoverage(expectedPaths: string[], reviewedPaths: string[] | undefined): boolean {
3634
3460
  const expected = [...new Set(expectedPaths)].sort();
3635
3461
  const reviewed = [...new Set(reviewedPaths ?? [])].sort();
@@ -3668,8 +3494,9 @@ function evaluateTaskGate(
3668
3494
  warnings: string[];
3669
3495
  currentWorkingTreeDigest?: string;
3670
3496
  changedFileEvidence?: ReturnType<typeof taskChangedFileEvidence>;
3497
+ acceptanceProof?: { mode: "enforce" | "diagnostic"; pendingCriterionIds: string[]; missing: string[] };
3671
3498
  } {
3672
- const finalGate = finalGateConfig(policy);
3499
+ const finalGate = finalGateConfig(policy, DEFAULT_POLICY);
3673
3500
  const missing: string[] = [];
3674
3501
  const warnings: string[] = [];
3675
3502
  if (!task) {
@@ -3677,14 +3504,24 @@ function evaluateTaskGate(
3677
3504
  }
3678
3505
  const currentDigests = options.currentDigests ?? workingTreeSnapshot(cwd) as Record<string, string>;
3679
3506
  const currentWorkingTreeDigest = options.currentWorkingTreeDigest ?? workingTreeEvidenceDigest(currentDigests);
3507
+ const independentState = independentAcceptanceState(cwd, task, currentWorkingTreeDigest);
3508
+ if (independentState.block) missing.push(independentState.block);
3509
+ const compositeFacts = new Set<string>();
3510
+ for (const [id, assessment] of independentState.assessments) {
3511
+ if (assessment.verdict !== "pass") missing.push(`independent contract evidence (${id}:${assessment.verdict}${assessment.executionDiagnostics?.reasons.length ? `; ${assessment.executionDiagnostics.reasons.join(", ")}` : ""})`);
3512
+ else if (assessment.assurance === "bounded-composite-contract-tested" && Array.isArray(assessment.factKinds)) {
3513
+ for (const kind of assessment.factKinds) if (typeof kind === "string") compositeFacts.add(kind);
3514
+ }
3515
+ }
3516
+ const compositeContext = compositeFacts.has("context-current"), compositeVerifier = compositeFacts.has("project-verifier-current");
3680
3517
  if (task.workingTreeDigestAlgorithm !== WORKING_TREE_DIGEST_ALGORITHM || task.workingTreeDigestMigration?.status === "verification-refresh-required" || !workingTreeSnapshotUsesCurrentAlgorithm(currentDigests) || !isCurrentWorkingTreeDigest(currentWorkingTreeDigest) || currentWorkingTreeDigest !== workingTreeEvidenceDigest(currentDigests) || Object.values(task.baselineFileDigests).some((digest) => !isCurrentWorkingTreeDigest(digest)) || (task.workingTreeDigestMigration && (!taskDigestMigrationArchiveStatus(cwd, task).valid || replayTaskCheckpoints(cwd, task.taskRunId, task).corruptions.length > 0))) missing.push("current working-tree digest evidence");
3681
3518
  if (workingTreeSnapshotHasUnavailableEvidence(currentDigests)) missing.push("complete working-tree content evidence");
3682
3519
  if (taskContractValidationErrors(task).length > 0) missing.push("valid session-bound task contract v2");
3683
3520
  if (task.attempt > task.maxAttempts) missing.push(`attempt within maxAttempts (${task.attempt}/${task.maxAttempts})`);
3684
3521
  const plannedVerifyCommands = meaningfulVerificationCommands(task.verifyCommands);
3685
- if (task.changeMode === "source-change" && plannedVerifyCommands.length === 0) missing.push("meaningful verify command");
3686
- if (finalGate.requireContextManifest && !hasDurableContextEvidence(task)) missing.push("context manifest");
3687
- if (task.changeMode === "source-change" && finalGate.requireVerifyEvidence && task.verifyEvidence.length === 0) missing.push("verify evidence");
3522
+ if (task.changeMode === "source-change" && plannedVerifyCommands.length === 0 && !compositeVerifier) missing.push("meaningful verify command");
3523
+ if (finalGate.requireContextManifest && !hasDurableContextEvidence(task) && !compositeContext) missing.push("context manifest");
3524
+ if (task.changeMode === "source-change" && finalGate.requireVerifyEvidence && task.verifyEvidence.length === 0 && !compositeVerifier) missing.push("verify evidence");
3688
3525
  if (task.verifyEvidence.some((evidence) => evidence.observed !== true)) {
3689
3526
  warnings.push("Unobserved verify evidence is ignored by the passing verify gate.");
3690
3527
  }
@@ -3699,48 +3536,74 @@ function evaluateTaskGate(
3699
3536
  warnings.push("Verification evidence from a different working-tree snapshot is stale and is ignored.");
3700
3537
  }
3701
3538
  let missingVerifyCommands: string[] = [];
3702
- if (task.changeMode === "source-change" && finalGate.requirePassingVerify && plannedVerifyCommands.length > 0) {
3703
- const passingCommands = passingVerifyCommandsForDigest(task, currentWorkingTreeDigest);
3539
+ if (task.changeMode === "source-change" && finalGate.requirePassingVerify && plannedVerifyCommands.length > 0 && !compositeVerifier) {
3540
+ const passingCommands = passingVerifyCommandsForDigest(task, currentWorkingTreeDigest, currentWorkspaceRevisionDigest(cwd));
3704
3541
  missingVerifyCommands = plannedVerifyCommands.filter((command) => !passingCommands.has(command.trim()));
3705
3542
  if (missingVerifyCommands.length > 0) missing.push(`observed passing verify evidence for every configured command (${missingVerifyCommands.length} missing)`);
3706
3543
  }
3544
+ if (finalGate.acceptanceProofMode === "diagnostic" && unresolvedFocusedVerification(task.verifyEvidence, currentWorkingTreeDigest, currentWorkspaceRevisionDigest(cwd)).length > 0) missing.push("current passing rerun of failed focused verification");
3707
3545
  if (finalGate.requireTrace && task.trace.outcome !== "completed") missing.push("completed final trace");
3708
3546
  const incompleteSteps = (task.workPlan ?? []).filter((step) => step.status === "pending" || step.status === "in-progress" || step.status === "failed");
3709
3547
  if (task.trace.outcome === "completed" && incompleteSteps.length > 0) {
3710
3548
  missing.push(`completed work plan (${incompleteSteps.map((step) => `${step.id}:${step.status}`).join(", ")})`);
3711
3549
  }
3712
3550
  const changedFileEvidence = taskChangedFileEvidence(cwd, task, currentDigests);
3551
+ const acceptanceEvidenceFiles = taskAcceptanceEvidenceFiles(cwd, task, currentDigests, changedFileEvidence.expected);
3713
3552
  if (task.changeMode === "source-change" && task.trace.outcome === "completed" && task.mutationPolicy !== "forbidden") {
3714
- if (task.changedFiles.length === 0) missing.push("changed files");
3553
+ if (task.mutationPolicy !== "allowed" && task.changedFiles.length === 0) missing.push("changed files");
3715
3554
  if (changedFileEvidence.undeclared.length > 0) missing.push(`declared observed changes (${changedFileEvidence.undeclared.join(", ")})`);
3716
3555
  if (changedFileEvidence.unsupportedClaims.length > 0) missing.push(`supported changed-file claims (${changedFileEvidence.unsupportedClaims.join(", ")})`);
3717
- if (changedFileEvidence.outsideScope.length > 0) missing.push(`changes within task scope (${changedFileEvidence.outsideScope.join(", ")})`);
3556
+ if (changedFileEvidence.outsideScope.length > 0) {
3557
+ warnings.push(`Task focus expanded beyond the initial scope (${changedFileEvidence.outsideScope.join(", ")}).`);
3558
+ }
3718
3559
  }
3719
3560
  if ((task.changeMode === "read-only" || task.mutationPolicy === "forbidden") && changedFileEvidence.expected.length > 0) {
3720
3561
  missing.push(`mutation-forbidden task has observed changes (${changedFileEvidence.expected.join(", ")})`);
3721
3562
  }
3722
3563
  const acceptance = refreshAcceptanceReceipt(task, {
3723
- cwd,
3724
- changedFiles: changedFileEvidence.expected,
3564
+ cwd, apiBaselineEvidence,
3565
+ changedFiles: acceptanceEvidenceFiles,
3725
3566
  currentWorkingTreeDigest
3726
3567
  });
3727
3568
  const semanticEnforcement = taskAuthorityDecision(task, "CAP-13", "block").allowed;
3728
- if (semanticEnforcement && acceptance.criticalMissing.length > 0) {
3729
- missing.push(`critical acceptance evidence (${acceptance.criticalMissing.map((criterion) => `${criterion.id}:${criterion.obligation}`).join(", ")})`);
3730
- }
3569
+ // Runtime-derived critical proof gates completion. A zero-delta review
3570
+ // uses its strictly bound evidence scope without claiming a new mutation.
3571
+ // Neutral artifacts with missing content proof use source-proof-required;
3572
+ // unsupported language policy remains under the existing CAP-13 authority.
3573
+ const proofMissing: string[] = [];
3574
+ const runtimeCriticalProofEnforcement = task.changeMode === "source-change"
3575
+ && task.acceptanceReceipt?.source === "runtime";
3576
+ const abstainedIds = new Set(acceptance.adapterAbstained.map((criterion) => criterion.id));
3577
+ const independentIds = new Set(acceptance.independentRequired.map((criterion) => criterion.id));
3578
+ const sourceProofIds = new Set(acceptance.sourceProofRequired.map((criterion) => criterion.id));
3579
+ const adapterCritical = acceptance.criticalMissing.filter((criterion) => abstainedIds.has(criterion.id) && !independentIds.has(criterion.id));
3580
+ const linkedCritical = acceptance.criticalMissing.filter((criterion) => !abstainedIds.has(criterion.id) && !independentIds.has(criterion.id) && !sourceProofIds.has(criterion.id));
3581
+ if ((semanticEnforcement || runtimeCriticalProofEnforcement) && sourceProofIds.size > 0) proofMissing.push(`critical acceptance evidence source-proof-required (${acceptance.sourceProofRequired.map((criterion) => `${criterion.id}:${criterion.obligation}`).join(", ")}); remedy: source proof remains unestablished after current focused tests passed; seek assessment, not source repair without a counterexample`);
3582
+ if ((semanticEnforcement || runtimeCriticalProofEnforcement) && independentIds.size > 0) proofMissing.push(`critical acceptance evidence independent-required (${acceptance.independentRequired.map((criterion) => `${criterion.id}:${criterion.obligation}`).join(", ")}); remedy: an approved independent assessment must cover every clause; missing proof is not an observed source defect`);
3583
+ if ((semanticEnforcement || runtimeCriticalProofEnforcement) && linkedCritical.length > 0) proofMissing.push(`critical acceptance evidence (${linkedCritical.map((criterion) => `${criterion.id}:${criterion.obligation}`).join(", ")})`);
3584
+ if (semanticEnforcement && adapterCritical.length > 0) proofMissing.push(`critical acceptance evidence adapter-unresolved (${adapterCritical.map((criterion) => `${criterion.id}:${criterion.obligation}`).join(", ")}); remedy: add a direct-relative focused test or configure a deterministic adapter`);
3731
3585
  const acceptanceConflicts = acceptanceSemanticConflicts(task, {
3732
3586
  cwd,
3733
- changedFiles: changedFileEvidence.expected
3587
+ changedFiles: acceptanceEvidenceFiles
3734
3588
  });
3735
3589
  if (semanticEnforcement && acceptanceConflicts.length > 0) {
3736
3590
  missing.push(`acceptance semantic conflicts (${acceptanceConflicts.join(", ")})`);
3737
3591
  }
3738
- const normalMissing = acceptance.missing.filter((criterion) => criterion.priority !== "critical");
3739
- if (!semanticEnforcement && (acceptance.criticalMissing.length > 0 || acceptanceConflicts.length > 0)) warnings.push("Acceptance projection is advisory under the pinned task authority and cannot block completion.");
3592
+ const criticalIds = new Set(acceptance.criticalMissing.map((criterion) => criterion.id));
3593
+ const normalMissing = acceptance.missing.filter((criterion) => !criticalIds.has(criterion.id));
3594
+ if (semanticEnforcement && acceptance.adapterAbstained.length > 0) {
3595
+ warnings.push(`Acceptance proof adapter abstained; rigorous criteria remain pending and hand off without an automatic model retry: ${acceptance.adapterAbstained.map((criterion) => `${criterion.id}:${criterion.obligation}`).join(", ")}`);
3596
+ }
3597
+ if (!semanticEnforcement && (adapterCritical.length > 0 || acceptanceConflicts.length > 0)) warnings.push("Adapter-unknown acceptance proof and semantic conflicts remain advisory under the pinned task authority; known runtime-linked critical proof still gates source-task completion.");
3740
3598
  if (normalMissing.length > 0) {
3741
3599
  warnings.push(`Acceptance criteria pending evidence: ${normalMissing.map((criterion) => `${criterion.id}:${criterion.obligation}`).join(", ")}`);
3742
3600
  }
3743
- return { decision: missing.length === 0 ? "pass" : "fail", missing, missingVerifyCommands, warnings, currentWorkingTreeDigest, changedFileEvidence };
3601
+ const acceptanceProof = { mode: finalGate.acceptanceProofMode,
3602
+ pendingCriterionIds: acceptance.missing.map(criterion => criterion.id), missing: proofMissing };
3603
+ if (finalGate.acceptanceProofMode === "diagnostic" && acceptanceProof.pendingCriterionIds.length > 0) {
3604
+ warnings.push(`Diagnostic acceptance: ${acceptanceProof.pendingCriterionIds.length} criteria remain unproved; no quality claim. ${proofMissing.join("; ")}`);
3605
+ } else missing.push(...proofMissing);
3606
+ return { decision: missing.length === 0 ? "pass" : "fail", missing, missingVerifyCommands, warnings, currentWorkingTreeDigest, changedFileEvidence, ...(finalGate.acceptanceProofMode === "diagnostic" ? { acceptanceProof } : {}) };
3744
3607
  }
3745
3608
 
3746
3609
  function appendTrace(cwd: string, payload: Record<string, unknown>): void {
@@ -3912,14 +3775,28 @@ export default function piagentGuard(pi: ExtensionAPI) {
3912
3775
  const routingObjective = routingObjectiveFromEnvironment(process.env.PIAGENT_ROUTING_OBJECTIVE);
3913
3776
  const autoContextEnabled = environmentFeatureEnabled("PIAGENT_AUTO_CONTEXT");
3914
3777
  const autoRecoveryEnabled = environmentFeatureEnabled("PIAGENT_AUTO_RECOVERY");
3915
- const runtimeState = new RuntimeSessionState({
3916
- maxObservedContext: contextBudgetConfig(policy).maxManifestFiles
3917
- });
3778
+ const independentVerificationConfigPath = process.env.PIAGENT_INDEPENDENT_VERIFICATION_CONFIG,
3779
+ runtimeState = new RuntimeSessionState({ maxObservedContext: contextBudgetConfig(policy).maxManifestFiles });
3780
+ const independentAcceptance = new IndependentAcceptanceRuntime({ state: runtimeState, installedRoot: PLATFORM_ROOT,
3781
+ configPath: independentVerificationConfigPath,
3782
+ writeTask,
3783
+ activeTask: (ctx) => activeSessionTask(ctx.cwd, ctx.sessionManager.getSessionId()) as TaskContract | undefined,
3784
+ authorizeSourceRead: (ctx, sourcePath) => {
3785
+ if (!ctx.isProjectTrusted()) return false;
3786
+ const profile = loadProfileFromContext(ctx), paths = effectiveProtectedPaths(policy, profile);
3787
+ const capabilities = verifyProjectCapabilityState(extensionDir, ctx.cwd, true, { sessionId: ctx.sessionManager.getSessionId() });
3788
+ if (!capabilities.ok) return false;
3789
+ const permission = resolvePermissionProfile(profile, policy, permissionOverrideFromContext(ctx));
3790
+ return !evaluatePathLikeToolAccess(ctx.cwd, "read", { path: sourcePath }, paths.writeProtectedPaths, paths.readProtectedPaths,
3791
+ paths.readOnlyPaths, permission.mode === "trusted-full-access" ? undefined : capabilities.filesystemRead).block;
3792
+ } });
3793
+ const editFreshnessGuard = new EditFreshnessGuard(editFreshnessModeFromEnvironment(process.env.PIAGENT_EDIT_FRESHNESS));
3918
3794
  const sourceMutationGuardBindings = createSourceMutationGuardBindings(policy, loadProfileFromContext);
3919
3795
  const runtimeSnapshotCapture = new RuntimeSnapshotCapture(), runtimeVersions = readRuntimeVersionMetadata(PLATFORM_ROOT);
3920
3796
  const solverShadow = solverMode === "off" ? undefined : new SolverShadowRuntime(solverMode);
3921
3797
  const modelRouteRuntime = new ModelRouteRuntime(parentRoutingMode, routingObjective);
3922
3798
  const modelSelectionProvenance = new ModelSelectionProvenanceTracker();
3799
+ const serviceTierRuntime = new ServiceTierRuntime({ environmentValue: process.env.PIAGENT_FAST_MODE });
3923
3800
  const trajectoryRuntime = new TrajectoryRuntime(), phaseToolRuntime = new PhaseToolRuntime(pi, dynamicToolsEnabled ? phaseToolModeFromEnvironment(process.env.PIAGENT_PHASE_TOOLS) : "off", telemetry, (ctx) => {
3924
3801
  const task = activeSessionTask(ctx.cwd, ctx.sessionManager.getSessionId()) as TaskContract | undefined; return task && authorityReplacementState(ctx.cwd, task).required ? "new-attempt-required" : task?.workingTreeDigestMigration?.status;
3925
3802
  }, (ctx) => {
@@ -3963,8 +3840,25 @@ export default function piagentGuard(pi: ExtensionAPI) {
3963
3840
  providerReasoningReasonCode: normalized.reasonCode
3964
3841
  });
3965
3842
  }
3843
+ const serviceTier = serviceTierRuntime.applyProviderRequest(
3844
+ pi,
3845
+ ctx,
3846
+ normalized.changed ? normalized.payload : event.payload
3847
+ );
3848
+ if (serviceTier.receipt.enabled || serviceTier.observationChanged) {
3849
+ telemetry(ctx, {
3850
+ event: "provider_request_service_tier",
3851
+ fastMode: serviceTier.receipt.mode,
3852
+ requestedServiceTier: serviceTier.receipt.requestedServiceTier,
3853
+ observedRequestServiceTier: serviceTier.receipt.observedRequestServiceTier,
3854
+ providerResponseServiceTier: serviceTier.receipt.providerResponseServiceTier,
3855
+ providerResponseEvidence: serviceTier.receipt.providerResponseEvidence,
3856
+ applied: serviceTier.receipt.applied,
3857
+ reasonCode: serviceTier.receipt.reasonCode
3858
+ });
3859
+ }
3966
3860
  const wire = buildOpenAiCodexWireFingerprint({
3967
- payload: normalized.changed ? normalized.payload : event.payload,
3861
+ payload: serviceTier.payload,
3968
3862
  provider: ctx.model?.provider,
3969
3863
  modelId: ctx.model?.id,
3970
3864
  workingDirectory: ctx.cwd,
@@ -3989,10 +3883,11 @@ export default function piagentGuard(pi: ExtensionAPI) {
3989
3883
  providerTextVerbosity: wire.textVerbosity,
3990
3884
  providerToolChoiceKind: wire.toolChoiceKind,
3991
3885
  providerToolChoiceHash: wire.toolChoiceHash,
3992
- requestPrefixFingerprint: wire.requestPrefixFingerprint
3886
+ requestPrefixFingerprint: wire.requestPrefixFingerprint,
3887
+ payloadMeasurement: measureProviderPayload(serviceTier.payload)
3993
3888
  });
3994
3889
  }
3995
- return normalized.changed ? normalized.payload : undefined;
3890
+ return normalized.changed || serviceTier.changed ? serviceTier.payload : undefined;
3996
3891
  });
3997
3892
 
3998
3893
  function freshModelRouteBoundary(ctx: ExtensionContext): boolean {
@@ -4073,6 +3968,15 @@ export default function piagentGuard(pi: ExtensionAPI) {
4073
3968
  }
4074
3969
  }
4075
3970
 
3971
+ function preferApplyPatchBeforeWriters(toolNames: string[]): string[] {
3972
+ if (!toolNames.includes("apply_patch")) return [...toolNames];
3973
+ const withoutPatch = toolNames.filter((toolName) => toolName !== "apply_patch");
3974
+ const firstWriter = withoutPatch.findIndex((toolName) => toolName === "edit" || toolName === "write");
3975
+ if (firstWriter < 0) return [...toolNames];
3976
+ withoutPatch.splice(firstWriter, 0, "apply_patch");
3977
+ return withoutPatch;
3978
+ }
3979
+
4076
3980
  function activateToolGroups(ctx: ExtensionContext, groups: PiagentToolGroup[], additive = false): string[] {
4077
3981
  const current = pi.getActiveTools();
4078
3982
  if (!dynamicToolsEnabled) return current;
@@ -4091,7 +3995,7 @@ export default function piagentGuard(pi: ExtensionAPI) {
4091
3995
  }
4092
3996
  }
4093
3997
  const ordered = [
4094
- ...current.filter((toolName) => selected.has(toolName) && !PIAGENT_TOOL_NAMES.has(toolName)),
3998
+ ...preferApplyPatchBeforeWriters(current.filter((toolName) => selected.has(toolName) && !PIAGENT_TOOL_NAMES.has(toolName))),
4095
3999
  ...PIAGENT_TOOL_ORDER.filter((toolName) => selected.has(toolName))
4096
4000
  ];
4097
4001
  const unchanged = ordered.length === current.length && ordered.every((toolName, index) => toolName === current[index]);
@@ -4120,25 +4024,28 @@ export default function piagentGuard(pi: ExtensionAPI) {
4120
4024
  let recordedClassification: FailureClassification | undefined;
4121
4025
  try {
4122
4026
  const replay = replayTaskCheckpoints(ctx.cwd, task.taskRunId, task);
4123
- if (replay.corruptions.length === 0) {
4124
- const checkpoint = replay.checkpoints
4125
- .filter((item) => item.phase === "verify" && item.status === "failed")
4126
- .at(-1) as any;
4127
- recordedClassification = checkpoint?.evidence?.failureClassification as FailureClassification | undefined;
4128
- }
4027
+ if (replay.corruptions.length === 0 && failed) recordedClassification = recordedFailureForObservation(
4028
+ replay.checkpoints, failed, currentTreeDigest, currentWorkspaceRevisionDigest(ctx.cwd)
4029
+ ) as FailureClassification | undefined;
4129
4030
  } catch {
4130
4031
  // A missing/corrupt journal cannot grant recovery mutation; the fallback
4131
4032
  // classifier remains fail-closed for unknown evidence.
4132
4033
  }
4133
- const classification = selectCompletionRecoveryClassification(
4034
+ const gateClassification = selectCompletionRecoveryClassification(
4134
4035
  recordedClassification,
4135
4036
  gate?.missing,
4136
4037
  summary,
4137
4038
  failed?.exitCode ?? 1
4138
4039
  );
4040
+ const independentRecovery = independentVerificationRecovery(ctx.cwd, task, currentTreeDigest ?? workingTreeEvidenceDigest(workingTreeSnapshot(ctx.cwd)));
4041
+ const classification = gateClassification.category === "scope-protected-path"
4042
+ ? gateClassification : independentRecovery?.classification ?? gateClassification;
4139
4043
  const trajectory = trajectoryRuntime.status(ctx.cwd, task.taskRunId);
4140
- const dependencyMutationAuthorized = task.scope.some((entry) => /(?:^|\/)(?:package(?:-lock)?\.json|pnpm-lock\.yaml|yarn\.lock|[^/]*(?:config|lock)[^/]*)$/i.test(entry));
4141
- return selectRecoveryDecision({
4044
+ // Task scope is a retrieval/review hint, not filesystem authority. Recovery
4045
+ // may update a dependency or config file when repository evidence requires
4046
+ // it; protected-path and approval policy still run on the exact call.
4047
+ const dependencyMutationAuthorized = true;
4048
+ const selected = selectRecoveryDecision({
4142
4049
  featureEnabled: autoRecoveryEnabled && taskAuthorityDecision(task, "CAP-12", "model-turn").allowed,
4143
4050
  task: {
4144
4051
  taskId: task.taskId,
@@ -4150,13 +4057,16 @@ export default function piagentGuard(pi: ExtensionAPI) {
4150
4057
  classification,
4151
4058
  currentPhase: trajectory.enforcementSafe ? trajectory.phase ?? "verify" : "handoff",
4152
4059
  history: runtimeState.recoveryHistory(task.taskId),
4153
- proposedHypothesisRef: classification.reasonCodes[0] ? `reason:${classification.reasonCodes[0]}` : null,
4060
+ proposedHypothesisRef: independentRecovery?.hypothesisRef ?? (classification.reasonCodes[0] ? `reason:${classification.reasonCodes[0]}` : null),
4154
4061
  exactVerifierAvailable: (gate?.missingVerifyCommands.length ?? task.verifyCommands.length) > 0,
4155
4062
  currentTreeMatchesEvidence: currentTreeDigest && latestExactVerifier?.workingTreeDigest
4156
- ? currentTreeDigest === latestExactVerifier.workingTreeDigest
4063
+ ? currentTreeDigest === latestExactVerifier.workingTreeDigest && latestExactVerifier.preWorkspaceRevisionDigest === currentWorkspaceRevisionDigest(ctx.cwd)
4064
+ && latestExactVerifier.workspaceRevisionDigest === latestExactVerifier.preWorkspaceRevisionDigest
4157
4065
  : true,
4158
- dependencyMutationAuthorized
4066
+ dependencyMutationAuthorized,
4067
+ independentDisposition: independentRecovery?.independentDisposition
4159
4068
  });
4069
+ return applyProofCapabilityHandoff(selected, gate?.missing, Boolean(independentRecovery));
4160
4070
  }
4161
4071
 
4162
4072
  function trajectoryRecoveryOptions(ctx: ExtensionContext, task: TaskContract, options: any): any {
@@ -4194,6 +4104,7 @@ export default function piagentGuard(pi: ExtensionAPI) {
4194
4104
  resolveTaskAny: (cwd, reference) => resolveTaskContract(cwd, reference, undefined) as TaskContract | undefined,
4195
4105
  bindTask: bindSessionTask,
4196
4106
  writeTask,
4107
+ appendTrace,
4197
4108
  capabilityState: (ctx) => verifyProjectCapabilityState(extensionDir, ctx.cwd, ctx.isProjectTrusted(), { allowRepin: true, forceFull: true, sessionId: ctx.sessionManager.getSessionId() }),
4198
4109
  permissionProfile: (ctx, profile) => resolvePermissionProfile(profile, policy, permissionOverrideFromContext(ctx)),
4199
4110
  legacyProjectWarning: legacyProjectStateWarning,
@@ -4221,7 +4132,15 @@ export default function piagentGuard(pi: ExtensionAPI) {
4221
4132
  })));
4222
4133
  },
4223
4134
  telemetry,
4224
- afterStart: async (ctx) => { sourceMutationGuardBindings.bind(ctx); await activityInspector.refresh(ctx); }
4135
+ afterStart: async (ctx) => {
4136
+ await independentAcceptance.activate(ctx);
4137
+ const serviceTier = serviceTierRuntime.restore(ctx);
4138
+ if (serviceTier.enabled && serviceTier.reasonCode === "provider-not-supported") {
4139
+ ctx.ui.notify("Piagent Fast mode is enabled, but the active provider is not OpenAI Codex; no service tier was changed.", "warning");
4140
+ }
4141
+ sourceMutationGuardBindings.bind(ctx);
4142
+ await activityInspector.refresh(ctx);
4143
+ }
4225
4144
  });
4226
4145
 
4227
4146
  registerSessionHooks(pi, {
@@ -4235,12 +4154,17 @@ export default function piagentGuard(pi: ExtensionAPI) {
4235
4154
  flushObservedTaskContext,
4236
4155
  onTurnEnd: activityInspector.refresh,
4237
4156
  onAgentSettled: activityInspector.refresh,
4238
- beforeShutdown: (ctx) => {
4157
+ beforeShutdown: async (ctx) => {
4158
+ await independentAcceptance.clear(ctx);
4159
+ serviceTierRuntime.forget(ctx);
4239
4160
  sourceMutationGuardBindings.unbind(ctx);
4161
+ editFreshnessGuard.clear(ctx);
4240
4162
  activityInspector.dispose(ctx);
4241
4163
  sessionCapabilityDigests.delete(`${ctx.cwd}\0${ctx.sessionManager.getSessionId()}`);
4242
4164
  }
4243
4165
  });
4166
+ registerTaskUsageHooks(pi, { activeTask: (ctx) => activeSessionTask(ctx.cwd, ctx.sessionManager.getSessionId()) as TaskContract | undefined, telemetry });
4167
+ pi.on("turn_end", (event, ctx) => independentAcceptance.observeTurnEnd(ctx, event.message));
4244
4168
 
4245
4169
  registerInputHook(pi, {
4246
4170
  state: runtimeState,
@@ -4292,10 +4216,15 @@ export default function piagentGuard(pi: ExtensionAPI) {
4292
4216
 
4293
4217
  registerCompletionHook(pi, {
4294
4218
  state: runtimeState,
4219
+ prepareIndependentAcceptance: (ctx, task, response) => independentAcceptance.prepare(ctx, task, response),
4220
+ deferIndependentCompletion: (ctx, task, response, finalizer) => independentAcceptance.deferCompletion(ctx, task, response, finalizer),
4221
+ projectIndependentLifecycle: (ctx, task, candidate) => independentAcceptance.projectLifecycle(ctx, task, candidate),
4222
+ nativeRefusalFallbackAllowed: () => !independentVerificationConfigPath,
4295
4223
  maxManifestFiles: contextBudgetConfig(policy).maxManifestFiles,
4296
4224
  activeTask: (ctx) => activeSessionTask(ctx.cwd, ctx.sessionManager.getSessionId()) as TaskContract | undefined,
4297
4225
  flushObservedTaskContext,
4298
4226
  completionProjection: completionTaskProjection,
4227
+ acceptanceEvidenceFiles: taskAcceptanceEvidenceFiles,
4299
4228
  evaluateGate: (cwd, task, currentDigests, currentDigest) => {
4300
4229
  const gate = evaluateTaskGate(cwd, task, policy, { currentDigests, currentWorkingTreeDigest: currentDigest });
4301
4230
  const repairBlock = (taskAuthorityDecision(task, "CAP-13", "block").allowed
@@ -4327,13 +4256,43 @@ export default function piagentGuard(pi: ExtensionAPI) {
4327
4256
  redactText,
4328
4257
  observedTaskContext: observedTaskContextFromToolResult,
4329
4258
  recordObservedTaskChanges,
4330
- recordObservedTaskVerification,
4259
+ recordObservedTaskVerification: (...args) => recordObservedTaskVerification(...args, policy.finalGate?.acceptanceProofMode === "diagnostic"),
4331
4260
  extractLikelyPath: extractLikelyPathFromInput,
4332
4261
  mutationTargets: taskMutationTargets,
4333
4262
  isShellTool: (toolName) => SHELL_TOOL_NAMES.has(toolName),
4334
4263
  telemetry,
4335
4264
  activity: recordActivity,
4336
4265
  now: nowIso,
4266
+ recordSubagentResult: (ctx, event, result) => {
4267
+ const task = activeSessionTask(ctx.cwd, ctx.sessionManager.getSessionId()) as TaskContract | undefined;
4268
+ const written = recordDirectSubagentResult(task, event, result, {
4269
+ now: nowIso,
4270
+ persist: (candidate) => writeTask(ctx.cwd, candidate),
4271
+ trace: (payload) => appendTrace(ctx.cwd, payload),
4272
+ sessionTrace: (payload) => appendSessionTrace(pi, payload)
4273
+ });
4274
+ telemetry(ctx, {
4275
+ event: "helper_result_classified",
4276
+ recordedAt: nowIso(),
4277
+ taskRunId: written?.taskRunId,
4278
+ toolCallId: event.toolCallId,
4279
+ spawned: result.spawned,
4280
+ failed: result.failed,
4281
+ disposition: result.disposition,
4282
+ reasonCode: result.reasonCode,
4283
+ calls: result.calls,
4284
+ tokens: result.tokens
4285
+ });
4286
+ },
4287
+ observeEditFreshness: (ctx, event, metadata) => {
4288
+ if (!metadata.successful || !metadata.taskRunId) return;
4289
+ const protectedPaths = effectiveProtectedPaths(policy, loadProfileFromContext(ctx)).readProtectedPaths;
4290
+ const source = event.toolName === "read" ? "read" : ["edit", "write", "apply_patch"].includes(event.toolName) ? "mutation" : undefined;
4291
+ const candidates = source === "read" && metadata.targetPath ? [metadata.targetPath] : source === "mutation" ? metadata.mutationTargets : [];
4292
+ const safeTargets = candidates.filter((file) => !matchesProtectedPath(file, protectedPaths));
4293
+ const observed = source ? editFreshnessGuard.observe(ctx, metadata.taskRunId, safeTargets, source, nowIso()) : [];
4294
+ if (observed.length) telemetry(ctx, { event: "edit_freshness_snapshot_observed", taskRunId: metadata.taskRunId, source, paths: observed.map(redactText) });
4295
+ },
4337
4296
  completeSemanticRepair: (ctx, event, metadata) => {
4338
4297
  const task = activeSessionTask(ctx.cwd, ctx.sessionManager.getSessionId()) as TaskContract | undefined;
4339
4298
  return task && (taskAuthorityDecision(task, "CAP-13", "mutate").allowed
@@ -4354,10 +4313,43 @@ export default function piagentGuard(pi: ExtensionAPI) {
4354
4313
  activity: recordActivity,
4355
4314
  beforeAuthorize: (event, ctx) => {
4356
4315
  const toolInput = isPlainRecord(event.input) ? event.input : {};
4316
+ const task = activeSessionTask(ctx.cwd, ctx.sessionManager.getSessionId()) as TaskContract | undefined;
4317
+ const helperPreflight = evaluateDirectSubagentDispatch({
4318
+ toolName: event.toolName,
4319
+ toolInput,
4320
+ cwd: ctx.cwd,
4321
+ helpersMode: task ? taskHelperUsageMode(task) : helpersMode(),
4322
+ taskPending: task?.trace.outcome === "pending",
4323
+ dispatchAuthority: Boolean(task && taskAuthorityDecision(task, "CAP-14", "dispatch").allowed),
4324
+ durableSubagentState: task?.orchestration?.subagents
4325
+ });
4326
+ if (helperPreflight.applicable && helperPreflight.dispatch && !helperPreflight.allowed) {
4327
+ telemetry(ctx, {
4328
+ event: "helper_dispatch_blocked",
4329
+ recordedAt: nowIso(),
4330
+ taskRunId: task?.taskRunId,
4331
+ toolCallId: event.toolCallId,
4332
+ reasonCode: helperPreflight.reasonCode,
4333
+ role: helperPreflight.role,
4334
+ requestCount: helperPreflight.requestCount
4335
+ });
4336
+ return { block: true, reason: `Blocked ${event.toolName}: ${helperPreflight.reason} Do not retry this helper; continue in the parent.` };
4337
+ }
4338
+ const verifierReuse = reuseCurrentTreeExactVerifier({ cwd: ctx.cwd, task, toolName: event.toolName, toolInput, sessionEntries: ctx.sessionManager.getEntries() as unknown[],
4339
+ getHostProjectVerificationDigest: (snapshot, command) => task ? runtimeState.projectVerification.currentDigest(ctx, task, snapshot, command) : null });
4340
+ if (verifierReuse.reused) {
4341
+ telemetry(ctx, { event: "verifier_evidence_reused", recordedAt: nowIso(), taskRunId: task?.taskRunId, toolCallId: event.toolCallId, reasonCode: verifierReuse.reasonCode, commandDigest: verifierReuse.commandDigest, workingTreeDigest: verifierReuse.workingTreeDigest }); return;
4342
+ }
4357
4343
  const targetInspection = authorizationMutationTargetInspection(ctx.cwd, event.toolName, toolInput);
4358
4344
  if (targetInspection.reason) return { block: true, reason: `Blocked ${event.toolName}: ${targetInspection.reason}.` };
4345
+ if (task?.trace.outcome === "pending" && task.changeMode === "source-change" && (event.toolName === "edit" || targetInspection.exactLocalPatchExecutor)) {
4346
+ const freshness = editFreshnessGuard.evaluate(ctx, task.taskRunId, targetInspection.targets);
4347
+ if (freshness.decision === "stale") {
4348
+ telemetry(ctx, { event: "edit_freshness_stale", taskRunId: task.taskRunId, toolCallId: event.toolCallId, enforce: freshness.enforce, paths: freshness.stalePaths.map(redactText) });
4349
+ if (freshness.enforce) return { block: true, reason: `Blocked ${event.toolName}: the previously observed source snapshot is stale for ${freshness.stalePaths.map(redactText).join(", ")}. Reread the affected file once; no patch hunk was started.` };
4350
+ }
4351
+ }
4359
4352
  if (!["edit", "write"].includes(event.toolName) && !targetInspection.exactLocalPatchExecutor) return;
4360
- const task = activeSessionTask(ctx.cwd, ctx.sessionManager.getSessionId()) as TaskContract | undefined;
4361
4353
  if (!task || task.trace.outcome !== "pending" || task.changeMode !== "source-change") return;
4362
4354
  const semanticRepairEnabled = taskAuthorityDecision(task, "CAP-13", "mutate").allowed;
4363
4355
  const semanticRepairExactlyOff = !taskAuthorityDecision(task, "CAP-13", "observe").allowed;
@@ -4374,11 +4366,10 @@ export default function piagentGuard(pi: ExtensionAPI) {
4374
4366
  const currentDigest = workingTreeEvidenceDigest(currentSnapshot);
4375
4367
  const expectedReviewPaths = taskDeltaFilesFromSnapshot(task, currentSnapshot);
4376
4368
  const targets = targetInspection.targets;
4377
- const boundedInScopeMutation = targets.length > 0
4378
- && targets.every((file) => taskScopeIncludesPath(task.scope, file));
4379
- const verifierCurrent = allVerifyCommandsPassCurrentTree(task, currentDigest);
4369
+ const boundedTargetMutation = targets.length > 0;
4370
+ const verifierCurrent = allVerifyCommandsPassCurrentTree(task, currentDigest, currentWorkspaceRevisionDigest(ctx.cwd));
4380
4371
 
4381
- if (phase.phase === "verify" && boundedInScopeMutation && semanticRepairEnabled && semanticRepairRuntime.prepare({
4372
+ if (phase.phase === "verify" && boundedTargetMutation && semanticRepairEnabled && semanticRepairRuntime.prepare({
4382
4373
  ctx, task, event, currentDigest, currentDeltaPaths: expectedReviewPaths, targetPaths: targets,
4383
4374
  verifierCurrent
4384
4375
  })) return;
@@ -4388,7 +4379,7 @@ export default function piagentGuard(pi: ExtensionAPI) {
4388
4379
  // model catches its own omission in the same task/run/session. The call
4389
4380
  // still traverses every normal authorization check; verify -> repair is
4390
4381
  // committed only by the tool-result hook after a successful tree change.
4391
- if (phase.phase === "verify" && boundedRecoveryEnabled && verifierCurrent && boundedInScopeMutation) {
4382
+ if (phase.phase === "verify" && boundedRecoveryEnabled && verifierCurrent && boundedTargetMutation) {
4392
4383
  const authoredFileDigests = runtimeState.successfulModelMutationDigests(
4393
4384
  { taskId: task.taskId, taskRunId: task.taskRunId, sessionId: task.sessionId },
4394
4385
  currentSnapshot
@@ -4436,7 +4427,7 @@ export default function piagentGuard(pi: ExtensionAPI) {
4436
4427
  return reviewDecision;
4437
4428
  }
4438
4429
 
4439
- if (targets.length === 0 || targets.some((file) => !taskScopeIncludesPath(task.scope, file))) return;
4430
+ if (targets.length === 0) return;
4440
4431
  const result = trajectoryRuntime.sync(ctx.cwd, ctx.sessionManager.getSessionId(), task, {
4441
4432
  sourceHook: "tool-call",
4442
4433
  recoveryRequested: true,
@@ -4460,11 +4451,9 @@ export default function piagentGuard(pi: ExtensionAPI) {
4460
4451
  const targetInspection = authorizationMutationTargetInspection(ctx.cwd, event.toolName, toolInput);
4461
4452
  if (targetInspection.reason) return { block: true, reason: `Blocked ${event.toolName}: ${targetInspection.reason}.` };
4462
4453
  const targets = targetInspection.targets;
4463
- if ((["edit", "write"].includes(event.toolName) || targetInspection.patchCarrier) && (
4464
- targets.length === 0 || targets.some((file) => !taskScopeIncludesPath(task.scope, file))
4465
- )) {
4454
+ if ((["edit", "write"].includes(event.toolName) || targetInspection.patchCarrier) && targets.length === 0) {
4466
4455
  runtimeState.denyPerformanceReviewTool(task.taskRunId);
4467
- return { block: true, reason: `Task ${task.taskId} semantic repair must stay inside its declared task scope.` };
4456
+ return { block: true, reason: `Task ${task.taskId} semantic repair requires an exact statically bounded target.` };
4468
4457
  }
4469
4458
  const reviewDecision = performanceReviewToolDecision({
4470
4459
  toolName: event.toolName,
@@ -4492,6 +4481,30 @@ export default function piagentGuard(pi: ExtensionAPI) {
4492
4481
  },
4493
4482
  afterAuthorized: (event, ctx, metadata) => {
4494
4483
  const task = activeSessionTask(ctx.cwd, ctx.sessionManager.getSessionId()) as TaskContract | undefined;
4484
+ const helperPreflight = evaluateDirectSubagentDispatch({
4485
+ toolName: event.toolName,
4486
+ toolInput: event.input,
4487
+ cwd: ctx.cwd,
4488
+ helpersMode: task ? taskHelperUsageMode(task) : helpersMode(),
4489
+ taskPending: task?.trace.outcome === "pending",
4490
+ dispatchAuthority: Boolean(task && taskAuthorityDecision(task, "CAP-14", "dispatch").allowed),
4491
+ durableSubagentState: task?.orchestration?.subagents
4492
+ });
4493
+ if (helperPreflight.applicable && helperPreflight.dispatch && helperPreflight.allowed) {
4494
+ const reserved = reserveDirectSubagentDispatch(task, metadata.toolCallId, {
4495
+ now: nowIso,
4496
+ persist: (candidate) => writeTask(ctx.cwd, candidate),
4497
+ trace: (payload) => appendTrace(ctx.cwd, payload)
4498
+ });
4499
+ telemetry(ctx, {
4500
+ event: "helper_dispatch_reserved",
4501
+ recordedAt: nowIso(),
4502
+ taskRunId: reserved?.taskRunId,
4503
+ toolCallId: metadata.toolCallId,
4504
+ role: helperPreflight.role,
4505
+ requestCount: helperPreflight.requestCount
4506
+ });
4507
+ }
4495
4508
  if (task?.trace.outcome === "pending") {
4496
4509
  const snapshot = workingTreeSnapshot(ctx.cwd) as Record<string, string>;
4497
4510
  const currentDigest = workingTreeEvidenceDigest(snapshot);
@@ -4604,7 +4617,7 @@ export default function piagentGuard(pi: ExtensionAPI) {
4604
4617
  const governedTaskProfile = !profileMode.startsWith("unprofiled") && !profileMode.includes("unreadable");
4605
4618
  const taskContractRequired = governedTaskProfile
4606
4619
  && runtime.finalGate === "enforce"
4607
- && finalGateConfig(policy).requireTaskContract;
4620
+ && finalGateConfig(policy, DEFAULT_POLICY).requireTaskContract;
4608
4621
  if (sessionTask?.trace.outcome === "pending" && (sessionTask.changeMode === "read-only" || sessionTask.mutationPolicy === "forbidden")
4609
4622
  && !SHELL_TOOL_NAMES.has(event.toolName) && isTaskMutationTool(event.toolName, toolInput)) {
4610
4623
  return {
@@ -4639,7 +4652,13 @@ export default function piagentGuard(pi: ExtensionAPI) {
4639
4652
  const execDecision = evaluateExecPolicy(command, profile, policy);
4640
4653
  authorizedShellCommand = command;
4641
4654
  authorizedShellSegments = execDecision.segments;
4642
- shellProjectMutation = isProjectMutatingShellCommand(command, execDecision.segments);
4655
+ if (shellTouchesGrantedSourceCheckout(ctx.cwd, command, runtimeState.sourceCheckoutReadRoots(ctx))) {
4656
+ return {
4657
+ block: true,
4658
+ reason: "Shared source checkouts are shell-inaccessible. Inspect the exact session-granted checkout with read, grep, find, or ls; cache mutation is never authorized."
4659
+ };
4660
+ }
4661
+ shellProjectMutation = isProjectMutatingShellCommand(command, execDecision.segments, ctx.cwd);
4643
4662
  configuredVerifierShell = Boolean(sessionTask && commandMatchesVerifyPlan(command, sessionTask.verifyCommands));
4644
4663
  const shellWriteCandidates = extractShellWritePathCandidates(command);
4645
4664
  shellMutationTargetBounded = shellWriteCandidates.length > 0;
@@ -4655,7 +4674,7 @@ export default function piagentGuard(pi: ExtensionAPI) {
4655
4674
  const mutationForbidden = sessionTask?.trace.outcome === "pending"
4656
4675
  && (sessionTask.changeMode === "read-only" || sessionTask.mutationPolicy === "forbidden");
4657
4676
  const exactForbiddenTaskVerifier = mutationForbidden && sessionTask.changeMode === "source-change" && configuredVerifierShell;
4658
- if (mutationForbidden && !exactForbiddenTaskVerifier && !isReadOnlyTaskShellCommand(command, execDecision.segments)) {
4677
+ if (mutationForbidden && !exactForbiddenTaskVerifier && !isReadOnlyTaskShellCommand(command, execDecision.segments, ctx.cwd)) {
4659
4678
  return {
4660
4679
  block: true,
4661
4680
  reason: `Task ${sessionTask.taskId} ${sessionTask.changeMode === "read-only" ? "is read-only; this shell command is not in the read-only inspection allowlist" : "forbids source mutation; this shell command is neither bounded inspection nor an exact configured verifier"}.`
@@ -4730,7 +4749,8 @@ export default function piagentGuard(pi: ExtensionAPI) {
4730
4749
  {
4731
4750
  forceScopeAware: authorizationTargetInspection.patchCarrier || Boolean(preparedInput.proxyToolName),
4732
4751
  forceWrite: authorizationTargetInspection.patchCarrier || preparedInput.proxyAction?.decision === "confirm",
4733
- allowAmbiguousFilesystemContentFields: !usesKnownExternalProvider && !isPiagentTool(event.toolName)
4752
+ allowAmbiguousFilesystemContentFields: !usesKnownExternalProvider && !isPiagentTool(event.toolName),
4753
+ sourceCheckoutReadRoots: runtimeState.sourceCheckoutReadRoots(ctx)
4734
4754
  }
4735
4755
  );
4736
4756
  if (pathDecision.block) {
@@ -4816,32 +4836,18 @@ export default function piagentGuard(pi: ExtensionAPI) {
4816
4836
  + " Call `piagent_task_start` once with explicit project-relative scope, then retry."
4817
4837
  };
4818
4838
  }
4819
- if (sessionTask?.trace.outcome === "pending" && sessionTask.changeMode === "source-change") {
4820
- if (
4821
- shellProjectMutation
4822
- && opaqueShellMutationNeedsBoundedTarget(authorizedShellCommand, authorizedShellSegments)
4823
- && !shellMutationTargetBounded
4824
- && !configuredVerifierShell
4825
- ) {
4826
- return {
4827
- block: true,
4828
- reason: `Task ${sessionTask.taskId} cannot run an opaque shell mutation whose write target is not statically bounded. Use edit/write/apply_patch, an explicit in-scope redirection, or the exact configured verifier.`
4829
- };
4830
- }
4831
- const outsideScope = mutationTargets.filter((file) => !taskScopeIncludesPath(sessionTask.scope, file));
4832
- if (outsideScope.length > 0) {
4833
- return {
4834
- block: true,
4835
- reason: `Task ${sessionTask.taskId} cannot mutate paths outside its declared scope: ${outsideScope.join(", ")}.`
4836
- };
4837
- }
4838
- const outsideEvidenceRoot = mutationTargets.filter((file) => !pathWithinChangeEvidenceRoot(ctx.cwd, file));
4839
- if (outsideEvidenceRoot.length > 0) {
4840
- return {
4841
- block: true,
4842
- reason: `Task ${sessionTask.taskId} cannot mutate paths outside a change evidence root: ${outsideEvidenceRoot.join(", ")}. In a parent workspace with separate repos, write under a child repo or a scoped workspace directory such as plans/**.`
4843
- };
4844
- }
4839
+ if (
4840
+ sessionTask?.trace.outcome === "pending"
4841
+ && sessionTask.changeMode === "source-change"
4842
+ && shellProjectMutation
4843
+ && opaqueShellMutationNeedsBoundedTarget(authorizedShellCommand, authorizedShellSegments)
4844
+ && !shellMutationTargetBounded
4845
+ && !configuredVerifierShell
4846
+ ) {
4847
+ return {
4848
+ block: true,
4849
+ reason: `Task ${sessionTask.taskId} cannot run an opaque shell mutation whose write target is not statically bounded. Use edit/write/apply_patch, an explicit project-local redirection, or the exact configured verifier.`
4850
+ };
4845
4851
  }
4846
4852
  if (runtime.contextBudget !== "off" && (["write", "edit"].includes(event.toolName) || authorizationTargetInspection.patchCarrier)) {
4847
4853
  const budgetTargets = authorizationTargetInspection.patchCarrier
@@ -4873,7 +4879,7 @@ export default function piagentGuard(pi: ExtensionAPI) {
4873
4879
  && sessionTask.changeMode === "source-change"
4874
4880
  && (shellProjectMutation || configuredVerifierShell)
4875
4881
  ) {
4876
- runtimeState.rememberShellMutationSnapshot(ctx, event.toolName, event.input);
4882
+ runtimeState.rememberShellMutationSnapshot(ctx, event.toolName, event.input, event.toolCallId);
4877
4883
  }
4878
4884
  }
4879
4885
  });
@@ -4895,6 +4901,8 @@ export default function piagentGuard(pi: ExtensionAPI) {
4895
4901
  createTaskRunId, crypto, currentSessionName, defaultRolePolicy, defaultWorkPlan, digestJson,
4896
4902
  dynamicToolsEnabled, effectiveProtectedPaths, emitRuntimeMessage, ensureContextIndexV2, estimateContextTokens,
4897
4903
  evaluateExecPolicy, evaluateModelRoute, evaluateRetrievalRoute, evaluateRuntimeSolver, evaluateTaskGate, evaluateToolPolicy, execPolicyConfig,
4904
+ prepareIndependentAcceptance: (ctx: ExtensionContext, task: TaskContract, response?: { origin: "assistant"; bytes: string }) =>
4905
+ independentAcceptance.prepare(ctx, task, response),
4898
4906
  extensionDir, externalActionPolicyConfig, extractDocument, finalGateConfig, findMatchingObservedBashResult,
4899
4907
  formatContextPreflight, formatCount, formatLiveTaskStatus, formatPercent, formatTechOptionsText, formatTechSelectionSummary,
4900
4908
  formatToolResultCaptureStatus, formatUsageSnapshot, fs, hasGitEvidenceRoot, hasOperatorSessionName, helpersMode,
@@ -4912,7 +4920,7 @@ export default function piagentGuard(pi: ExtensionAPI) {
4912
4920
  safeTaskId, searchContextIndex, searchContextIndexV2, searchMemoryFiles, selectRuntimeAction,
4913
4921
  selectValueFromUi, selectVerificationPlan, semanticCompactionInstructions, sendWorkflowFollowUp, setPermissionOverrideForContext,
4914
4922
  semanticRepairCompletionBlock: (cwd: string, taskRunId: string) => semanticRepairRuntime.completionBlock(cwd, taskRunId),
4915
- freshRequestParts, shellArg, shortTaskLabel, solverShadow, summarizeAttempt, taskChangedFileEvidence,
4923
+ freshRequestParts, shellArg, shortTaskLabel, solverShadow, summarizeAttempt, taskAcceptanceEvidenceFiles, taskChangedFileEvidence,
4916
4924
  techContextDirPath, techContextFilePath, techContextRelativePath, techOptionById, techStackPath,
4917
4925
  telemetry, toolRegistryConfig, trajectoryRuntime, uniqueStrings, usageExactCommands,
4918
4926
  validTaskScopePattern, validateNewWorkPlan, verifierCommandInstructions, verifyProjectCapabilityState, workingTreeEvidenceDigest,
@@ -4943,9 +4951,10 @@ export default function piagentGuard(pi: ExtensionAPI) {
4943
4951
 
4944
4952
  function commandArgs(raw: string): { action: string; rest: string; tokens: string[] } {
4945
4953
  const trimmed = String(raw ?? "").trim();
4946
- const tokens = trimmed.split(/\s+/).filter(Boolean);
4947
- const action = (tokens.shift() ?? "").toLowerCase();
4948
- return { action, rest: tokens.join(" "), tokens };
4954
+ const match = /^(\S+)(?:\s+([\s\S]*))?$/.exec(trimmed);
4955
+ const action = (match?.[1] ?? "").toLowerCase();
4956
+ const rest = match?.[2] ?? "";
4957
+ return { action, rest, tokens: rest.split(/\s+/).filter(Boolean) };
4949
4958
  }
4950
4959
 
4951
4960
  function shellArg(value: string): string {
@@ -4977,6 +4986,7 @@ export default function piagentGuard(pi: ExtensionAPI) {
4977
4986
  }
4978
4987
 
4979
4988
  registerPermissionCommands(pi, registrationDeps);
4989
+ registerFastModeCommand(pi, serviceTierRuntime);
4980
4990
  const profileCommandApi = registerProfileCommands(pi, registrationDeps);
4981
4991
  registerMemoryMcpCommands(pi, registrationDeps);
4982
4992
  const contextCommandApi = registerContextCommands(pi, registrationDeps);