@piagent/platform 1.3.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (301) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +3 -3
  3. package/architecture/layers.json +96 -1
  4. package/docs/README.md +1 -0
  5. package/docs/architecture.md +1 -0
  6. package/docs/authority-manifest.md +1 -0
  7. package/docs/auto-delegation-policy.md +1 -0
  8. package/docs/capability-packs.md +1 -0
  9. package/docs/command-reference-vietnamese.md +5 -4
  10. package/docs/context-engine.md +1 -0
  11. package/docs/context-window-policy.md +1 -0
  12. package/docs/distribution-standard.md +8 -7
  13. package/docs/herdr-workflow.md +1 -0
  14. package/docs/mcp-and-tools.md +14 -9
  15. package/docs/memory-policy.md +1 -0
  16. package/docs/model-options.md +1 -0
  17. package/docs/oauth-providers.md +1 -0
  18. package/docs/operator-manual-vietnamese.md +15 -12
  19. package/docs/package-architecture-notes.md +1 -0
  20. package/docs/project-adapters.md +1 -0
  21. package/docs/project-onboarding.md +1 -0
  22. package/docs/publishing-for-teams.md +1 -0
  23. package/docs/quality-benchmark.md +1 -0
  24. package/docs/quickstart-vietnamese.md +3 -2
  25. package/docs/release-install-policy.md +7 -6
  26. package/docs/runtime-harness-standard.md +1 -0
  27. package/docs/runtime-policy-design.md +1 -0
  28. package/docs/runtime-quality-baseline.md +1 -0
  29. package/docs/security-redaction-benchmark.md +1 -0
  30. package/docs/security-threat-model.md +2 -1
  31. package/docs/subagent-orchestration-capabilities.md +1 -0
  32. package/docs/subagents-and-multiagent.md +1 -0
  33. package/docs/task-implementation-contract.md +1 -0
  34. package/docs/task-lifecycle-vietnamese.md +1 -0
  35. package/docs/team-onboarding.md +3 -2
  36. package/docs/third-party-neutrality.md +26 -0
  37. package/docs/usage-observability.md +1 -0
  38. package/docs/vercel-docs-site.md +1 -0
  39. package/docs/workflow-recipes.md +1 -0
  40. package/docs-site/architecture.html +1 -1
  41. package/docs-site/benchmark.html +1 -1
  42. package/docs-site/commands.html +1 -1
  43. package/docs-site/context-engine.html +1 -1
  44. package/docs-site/en/architecture.html +1 -1
  45. package/docs-site/en/benchmark.html +1 -1
  46. package/docs-site/en/commands.html +1 -1
  47. package/docs-site/en/context-engine.html +1 -1
  48. package/docs-site/en/index.html +1 -1
  49. package/docs-site/en/mcp-approval.html +1 -1
  50. package/docs-site/en/mcp-auth.html +1 -1
  51. package/docs-site/en/mcp-servers.html +1 -1
  52. package/docs-site/en/mcp.html +1 -1
  53. package/docs-site/en/permissions.html +1 -1
  54. package/docs-site/en/profiles.html +1 -1
  55. package/docs-site/en/quickstart.html +1 -1
  56. package/docs-site/en/runtime.html +1 -1
  57. package/docs-site/en/scope.html +1 -1
  58. package/docs-site/en/security.html +1 -1
  59. package/docs-site/en/team.html +1 -1
  60. package/docs-site/en/whats-new.html +1 -1
  61. package/docs-site/en/workflows.html +1 -1
  62. package/docs-site/index.html +1 -1
  63. package/docs-site/mcp-approval.html +1 -1
  64. package/docs-site/mcp-auth.html +1 -1
  65. package/docs-site/mcp-servers.html +1 -1
  66. package/docs-site/mcp.html +1 -1
  67. package/docs-site/permissions.html +1 -1
  68. package/docs-site/profiles.html +1 -1
  69. package/docs-site/quickstart.html +1 -1
  70. package/docs-site/runtime.html +1 -1
  71. package/docs-site/scope.html +1 -1
  72. package/docs-site/security.html +1 -1
  73. package/docs-site/team.html +1 -1
  74. package/docs-site/whats-new.html +1 -1
  75. package/docs-site/workflows.html +1 -1
  76. package/evals/fixtures/mutation-provenance-record.invalid.json +17 -0
  77. package/evals/fixtures/mutation-provenance-record.valid.json +27 -0
  78. package/evals/fixtures/piagent-webui/approval-v1.invalid.json +54 -0
  79. package/evals/fixtures/piagent-webui/approval-v1.valid.json +58 -0
  80. package/evals/fixtures/piagent-webui/attachment-v1.invalid.json +25 -0
  81. package/evals/fixtures/piagent-webui/attachment-v1.valid.json +25 -0
  82. package/evals/fixtures/piagent-webui/capabilities-v1.invalid.json +51 -0
  83. package/evals/fixtures/piagent-webui/capabilities-v1.valid.json +122 -0
  84. package/evals/fixtures/piagent-webui/commit-summary-v1.invalid.json +10 -0
  85. package/evals/fixtures/piagent-webui/commit-summary-v1.valid.json +25 -0
  86. package/evals/fixtures/piagent-webui/control-command-v1.invalid.json +37 -0
  87. package/evals/fixtures/piagent-webui/control-command-v1.valid.json +35 -0
  88. package/evals/fixtures/piagent-webui/diff-v1.invalid.json +13 -0
  89. package/evals/fixtures/piagent-webui/diff-v1.valid.json +141 -0
  90. package/evals/fixtures/piagent-webui/gateway-capabilities-v1.invalid.json +35 -0
  91. package/evals/fixtures/piagent-webui/gateway-capabilities-v1.valid.json +35 -0
  92. package/evals/fixtures/piagent-webui/gateway-protocol-v1.invalid.json +14 -0
  93. package/evals/fixtures/piagent-webui/gateway-protocol-v1.valid.json +14 -0
  94. package/evals/fixtures/piagent-webui/handoff-history-v1.invalid.json +16 -0
  95. package/evals/fixtures/piagent-webui/handoff-history-v1.valid.json +16 -0
  96. package/evals/fixtures/piagent-webui/model-catalog-v1.invalid.json +31 -0
  97. package/evals/fixtures/piagent-webui/model-catalog-v1.valid.json +43 -0
  98. package/evals/fixtures/piagent-webui/queue-v1.invalid.json +29 -0
  99. package/evals/fixtures/piagent-webui/queue-v1.valid.json +44 -0
  100. package/evals/fixtures/piagent-webui/recovery-history-v1.invalid.json +17 -0
  101. package/evals/fixtures/piagent-webui/recovery-history-v1.valid.json +20 -0
  102. package/evals/fixtures/piagent-webui/release-monitor-v1.invalid.json +12 -0
  103. package/evals/fixtures/piagent-webui/release-monitor-v1.valid.json +29 -0
  104. package/evals/fixtures/piagent-webui/review-state-v1.invalid.json +25 -0
  105. package/evals/fixtures/piagent-webui/review-state-v1.valid.json +38 -0
  106. package/evals/fixtures/piagent-webui/runtime-event-v2.invalid.json +49 -0
  107. package/evals/fixtures/piagent-webui/runtime-event-v2.valid.json +49 -0
  108. package/evals/fixtures/piagent-webui/session-catalog-v1.invalid.json +17 -0
  109. package/evals/fixtures/piagent-webui/session-catalog-v1.valid.json +58 -0
  110. package/evals/fixtures/piagent-webui/session-command-v1.invalid.json +19 -0
  111. package/evals/fixtures/piagent-webui/session-command-v1.valid.json +19 -0
  112. package/evals/fixtures/piagent-webui/snapshot-v1.invalid.json +5 -0
  113. package/evals/fixtures/piagent-webui/snapshot-v1.valid.json +191 -0
  114. package/evals/fixtures/piagent-webui/source-change-v1.invalid.json +57 -0
  115. package/evals/fixtures/piagent-webui/source-change-v1.valid.json +98 -0
  116. package/evals/fixtures/piagent-webui/source-mutation-v1.invalid.json +19 -0
  117. package/evals/fixtures/piagent-webui/source-mutation-v1.valid.json +38 -0
  118. package/evals/fixtures/piagent-webui/source-revert-v1.invalid.json +20 -0
  119. package/evals/fixtures/piagent-webui/source-revert-v1.valid.json +62 -0
  120. package/evals/fixtures/piagent-webui/subagent-tree-v1.invalid.json +26 -0
  121. package/evals/fixtures/piagent-webui/subagent-tree-v1.valid.json +39 -0
  122. package/evals/fixtures/piagent-webui/task-index-v1.invalid.json +15 -0
  123. package/evals/fixtures/piagent-webui/task-index-v1.valid.json +15 -0
  124. package/evals/fixtures/piagent-webui/task-timeline-v1.invalid.json +14 -0
  125. package/evals/fixtures/piagent-webui/task-timeline-v1.valid.json +16 -0
  126. package/evals/fixtures/piagent-webui/transcript-v1.invalid.json +35 -0
  127. package/evals/fixtures/piagent-webui/transcript-v1.valid.json +55 -0
  128. package/evals/fixtures/task-baseline-manifest.invalid.json +16 -0
  129. package/evals/fixtures/task-baseline-manifest.valid.json +41 -0
  130. package/evals/fixtures/verifier-file-snapshot.invalid.json +21 -0
  131. package/evals/fixtures/verifier-file-snapshot.valid.json +21 -0
  132. package/package.json +30 -3
  133. package/packages/piagent-core/benchmark/benchmark-candidate.d.ts +1 -0
  134. package/packages/piagent-core/benchmark/benchmark-forensics.d.ts +1 -0
  135. package/packages/piagent-core/benchmark/benchmark-ledger.d.ts +4 -0
  136. package/packages/piagent-core/benchmark/benchmark-record-validation.d.ts +1 -0
  137. package/packages/piagent-core/benchmark/benchmark-runtime.d.ts +1 -0
  138. package/packages/piagent-core/capabilities/capability-core.js +2 -2
  139. package/packages/piagent-core/capabilities/runtime-integrity.js +143 -0
  140. package/packages/piagent-core/extensions/piagent-guard.ts +62 -37
  141. package/packages/piagent-core/extensions/redaction-core.d.ts +2 -0
  142. package/packages/piagent-core/extensions/task-journal.js +30 -1
  143. package/packages/piagent-core/extensions/task-state.js +33 -36
  144. package/packages/piagent-core/mcp/mcp-server-catalog.js +5 -5
  145. package/packages/piagent-core/package.json +1 -1
  146. package/packages/piagent-core/runtime/hooks/session-start-hook.ts +2 -2
  147. package/packages/piagent-core/runtime/hooks/tool-call-hook.ts +5 -2
  148. package/packages/piagent-core/runtime/hooks/tool-result-hook.ts +20 -19
  149. package/packages/piagent-core/runtime/hooks/tool-result-metadata.ts +13 -0
  150. package/packages/piagent-core/runtime/input/chat-images.ts +2 -2
  151. package/packages/piagent-core/runtime/inspection/activity-event-adapter.ts +94 -0
  152. package/packages/piagent-core/runtime/inspection/approval-broker.ts +318 -0
  153. package/packages/piagent-core/runtime/inspection/commit-summary-projection.ts +59 -0
  154. package/packages/piagent-core/runtime/inspection/context-telemetry-inspection.ts +37 -0
  155. package/packages/piagent-core/runtime/inspection/criteria-links.ts +295 -0
  156. package/packages/piagent-core/runtime/inspection/diff-projection.ts +499 -0
  157. package/packages/piagent-core/runtime/inspection/git-filter-safety.ts +38 -0
  158. package/packages/piagent-core/runtime/inspection/git-numstat-adapter.ts +71 -0
  159. package/packages/piagent-core/runtime/inspection/git-status-adapter.ts +493 -0
  160. package/packages/piagent-core/runtime/inspection/git-tree-adapter.ts +108 -0
  161. package/packages/piagent-core/runtime/inspection/mcp-control.ts +10 -0
  162. package/packages/piagent-core/runtime/inspection/mutation-provenance-contract.ts +131 -0
  163. package/packages/piagent-core/runtime/inspection/mutation-provenance-recorder.ts +48 -0
  164. package/packages/piagent-core/runtime/inspection/mutation-provenance-store.ts +161 -0
  165. package/packages/piagent-core/runtime/inspection/project-runtime-inspection.ts +36 -0
  166. package/packages/piagent-core/runtime/inspection/review-state-contract.ts +108 -0
  167. package/packages/piagent-core/runtime/inspection/review-state-projection.ts +93 -0
  168. package/packages/piagent-core/runtime/inspection/review-state-store.ts +112 -0
  169. package/packages/piagent-core/runtime/inspection/runtime-event-store.ts +262 -0
  170. package/packages/piagent-core/runtime/inspection/same-process-bridge-proof.ts +103 -0
  171. package/packages/piagent-core/runtime/inspection/source-change-projection.ts +471 -0
  172. package/packages/piagent-core/runtime/inspection/source-evidence-contract.ts +139 -0
  173. package/packages/piagent-core/runtime/inspection/source-evidence-store.ts +315 -0
  174. package/packages/piagent-core/runtime/inspection/source-handoff-store.ts +70 -0
  175. package/packages/piagent-core/runtime/inspection/source-inspection-plan.ts +34 -0
  176. package/packages/piagent-core/runtime/inspection/source-mutation-projection.ts +164 -0
  177. package/packages/piagent-core/runtime/inspection/source-mutation-store.ts +168 -0
  178. package/packages/piagent-core/runtime/inspection/source-open-target.ts +38 -0
  179. package/packages/piagent-core/runtime/inspection/source-revert-projection.ts +147 -0
  180. package/packages/piagent-core/runtime/inspection/task-baseline-start-capture.ts +22 -0
  181. package/packages/piagent-core/runtime/inspection/task-compaction-history.ts +160 -0
  182. package/packages/piagent-core/runtime/inspection/task-control-journal.ts +131 -0
  183. package/packages/piagent-core/runtime/inspection/task-handoff-history.ts +95 -0
  184. package/packages/piagent-core/runtime/inspection/task-provenance-projection.ts +60 -0
  185. package/packages/piagent-core/runtime/inspection/task-recovery-timeline.ts +88 -0
  186. package/packages/piagent-core/runtime/inspection/task-run-index.ts +87 -0
  187. package/packages/piagent-core/runtime/inspection/task-source-projection.ts +401 -0
  188. package/packages/piagent-core/runtime/inspection/task-subagent-tree.ts +101 -0
  189. package/packages/piagent-core/runtime/inspection/text-diff.ts +60 -0
  190. package/packages/piagent-core/runtime/inspection/verifier-snapshot-contract.ts +114 -0
  191. package/packages/piagent-core/runtime/inspection/verifier-snapshot-store.ts +189 -0
  192. package/packages/piagent-core/runtime/inspection/webui-snapshot.ts +320 -0
  193. package/packages/piagent-core/runtime/inspection/workspace-file-reader.ts +132 -0
  194. package/packages/piagent-core/runtime/inspection/workspace-source-projection.ts +96 -0
  195. package/packages/piagent-core/runtime/inspection/zero-turn-conformance.ts +175 -0
  196. package/packages/piagent-core/runtime/orchestration/owned-work-budget.ts +68 -4
  197. package/packages/piagent-core/runtime/policy/source-index-transaction.ts +173 -0
  198. package/packages/piagent-core/runtime/policy/source-mutation-guard-binding.ts +42 -0
  199. package/packages/piagent-core/runtime/policy/source-mutation-guard.ts +184 -0
  200. package/packages/piagent-core/runtime/policy/source-worktree-transaction.ts +105 -0
  201. package/packages/piagent-core/runtime/product/activity-inspector-footer.ts +5 -3
  202. package/packages/piagent-core/runtime/product/activity-inspector.ts +85 -343
  203. package/packages/piagent-core/runtime/recovery/resume-state.ts +38 -1
  204. package/packages/piagent-core/runtime/registration/activity-inspector-command.ts +68 -14
  205. package/packages/piagent-core/runtime/registration/task-start-tool.ts +13 -14
  206. package/packages/piagent-core/runtime/session/model-authorship-state.ts +31 -3
  207. package/packages/piagent-core/runtime/session/runtime-state.ts +11 -1
  208. package/packages/piagent-webui/dist/client/assets/index-DjMntaK5.js +172 -0
  209. package/packages/piagent-webui/dist/client/assets/index-DwKCWbwd.css +1 -0
  210. package/packages/piagent-webui/dist/client/index.html +16 -0
  211. package/packages/piagent-webui/extension/attachment-store.ts +323 -0
  212. package/packages/piagent-webui/extension/held-message-queue.ts +311 -0
  213. package/packages/piagent-webui/extension/lifecycle-controller.ts +408 -0
  214. package/packages/piagent-webui/extension/lifecycle-event-adapter.ts +23 -0
  215. package/packages/piagent-webui/extension/piagent-webui.ts +470 -0
  216. package/packages/piagent-webui/extension/review-controller.ts +160 -0
  217. package/packages/piagent-webui/extension/same-session-bridge.ts +500 -0
  218. package/packages/piagent-webui/extension/session-options-controller.ts +281 -0
  219. package/packages/piagent-webui/extension/session-stream-adapter.ts +249 -0
  220. package/packages/piagent-webui/extension/source-mutation-controller.ts +215 -0
  221. package/packages/piagent-webui/extension/source-open-controller.ts +136 -0
  222. package/packages/piagent-webui/extension/source-revert-controller.ts +189 -0
  223. package/packages/piagent-webui/extension/terminal-session-adapter.ts +73 -0
  224. package/packages/piagent-webui/extension/vscode-handoff.ts +51 -0
  225. package/packages/piagent-webui/gateway/control-socket.ts +92 -0
  226. package/packages/piagent-webui/gateway/gateway-events.ts +60 -0
  227. package/packages/piagent-webui/gateway/gateway-protocol-service.ts +64 -0
  228. package/packages/piagent-webui/gateway/gateway-service.ts +215 -0
  229. package/packages/piagent-webui/gateway/gateway-session-stream.ts +110 -0
  230. package/packages/piagent-webui/gateway/mcp-auth-broker.ts +158 -0
  231. package/packages/piagent-webui/gateway/native-project-picker.ts +29 -0
  232. package/packages/piagent-webui/gateway/pi-host.ts +41 -0
  233. package/packages/piagent-webui/gateway/profile-state.ts +1 -0
  234. package/packages/piagent-webui/gateway/project-registry.ts +108 -0
  235. package/packages/piagent-webui/gateway/provider-auth-broker.ts +172 -0
  236. package/packages/piagent-webui/gateway/session-catalog.ts +128 -0
  237. package/packages/piagent-webui/gateway/session-command-controller.ts +237 -0
  238. package/packages/piagent-webui/gateway/session-command-store.ts +224 -0
  239. package/packages/piagent-webui/gateway/session-inspection-registry.ts +204 -0
  240. package/packages/piagent-webui/gateway/session-lease-store.ts +1 -0
  241. package/packages/piagent-webui/gateway/session-metadata-store.ts +152 -0
  242. package/packages/piagent-webui/gateway/session-runtime-supervisor.ts +485 -0
  243. package/packages/piagent-webui/ownership/gateway-runtime-context.ts +8 -0
  244. package/packages/piagent-webui/ownership/profile-state.ts +117 -0
  245. package/packages/piagent-webui/ownership/session-lease-store.ts +329 -0
  246. package/packages/piagent-webui/ownership/session-refs.ts +8 -0
  247. package/packages/piagent-webui/package.json +33 -0
  248. package/packages/piagent-webui/server/README.md +4 -0
  249. package/packages/piagent-webui/server/benchmark-release-monitor.ts +230 -0
  250. package/packages/piagent-webui/server/core-inspection-provider.ts +403 -0
  251. package/packages/piagent-webui/server/gateway-websocket.ts +143 -0
  252. package/packages/piagent-webui/server/http-security.ts +27 -0
  253. package/packages/piagent-webui/server/ipc-read-model-client.ts +89 -0
  254. package/packages/piagent-webui/server/loopback-server.ts +368 -0
  255. package/packages/piagent-webui/server/read-model-provider.ts +37 -0
  256. package/packages/piagent-webui/server/read-only-router.ts +105 -0
  257. package/packages/piagent-webui/server/session-auth.ts +88 -0
  258. package/packages/piagent-webui/server/sidecar-main.ts +86 -0
  259. package/packages/piagent-webui/server/sse-hub.ts +76 -0
  260. package/packages/piagent-webui/server/static-bundle.ts +40 -0
  261. package/packages/piagent-webui/server/transcript-projection.ts +110 -0
  262. package/schemas/mutation-provenance-record.schema.json +100 -0
  263. package/schemas/piagent-webui/approval-v1.schema.json +654 -0
  264. package/schemas/piagent-webui/attachment-v1.schema.json +267 -0
  265. package/schemas/piagent-webui/capabilities-v1.schema.json +729 -0
  266. package/schemas/piagent-webui/catalog-v1.json +240 -0
  267. package/schemas/piagent-webui/commit-summary-v1.schema.json +63 -0
  268. package/schemas/piagent-webui/common-v1.schema.json +479 -0
  269. package/schemas/piagent-webui/control-command-v1.schema.json +1780 -0
  270. package/schemas/piagent-webui/diff-v1.schema.json +826 -0
  271. package/schemas/piagent-webui/gateway-capabilities-v1.schema.json +136 -0
  272. package/schemas/piagent-webui/gateway-protocol-v1.schema.json +456 -0
  273. package/schemas/piagent-webui/handoff-history-v1.schema.json +92 -0
  274. package/schemas/piagent-webui/model-catalog-v1.schema.json +95 -0
  275. package/schemas/piagent-webui/queue-v1.schema.json +99 -0
  276. package/schemas/piagent-webui/recovery-history-v1.schema.json +144 -0
  277. package/schemas/piagent-webui/release-monitor-v1.schema.json +173 -0
  278. package/schemas/piagent-webui/review-state-v1.schema.json +206 -0
  279. package/schemas/piagent-webui/runtime-event-v2.schema.json +5206 -0
  280. package/schemas/piagent-webui/session-catalog-v1.schema.json +222 -0
  281. package/schemas/piagent-webui/session-command-v1.schema.json +390 -0
  282. package/schemas/piagent-webui/snapshot-v1.schema.json +2622 -0
  283. package/schemas/piagent-webui/source-change-v1.schema.json +763 -0
  284. package/schemas/piagent-webui/source-mutation-v1.schema.json +96 -0
  285. package/schemas/piagent-webui/source-revert-v1.schema.json +130 -0
  286. package/schemas/piagent-webui/subagent-tree-v1.schema.json +88 -0
  287. package/schemas/piagent-webui/task-index-v1.schema.json +74 -0
  288. package/schemas/piagent-webui/task-timeline-v1.schema.json +49 -0
  289. package/schemas/piagent-webui/transcript-v1.schema.json +243 -0
  290. package/schemas/task-baseline-manifest.schema.json +122 -0
  291. package/schemas/verifier-file-snapshot.schema.json +81 -0
  292. package/scripts/check-architecture.mjs +1 -0
  293. package/scripts/check-doc-languages.mjs +19 -2
  294. package/scripts/check-third-party-neutrality.mjs +43 -0
  295. package/scripts/install-global.sh +1 -1
  296. package/scripts/piagent-cli.mjs +17 -3
  297. package/scripts/piagent-dashboard.mjs +208 -0
  298. package/scripts/piagent-webui-launcher.mjs +121 -0
  299. package/scripts/typescript-loader.mjs +26 -1
  300. package/scripts/verify-local.sh +253 -0
  301. package/scripts/verify-release-identity.mjs +4 -1
@@ -1,14 +1,18 @@
1
+ import { createHash } from "node:crypto";
2
+
1
3
  import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
2
4
 
3
5
  import type { TaskContract } from "../../extensions/guard-types.ts";
4
6
  import {
5
7
  buildActivityInspector,
6
8
  formatActivityInspector,
7
- inspectWorkingTreeFiles,
8
9
  type ActivityInspectorEvent,
9
10
  type CurrentActivity
10
11
  } from "../product/activity-inspector.ts";
11
12
  import { formatActivityFooter, formatActivityPanel } from "../product/activity-inspector-footer.ts";
13
+ import { adaptActivityTelemetryEvent, runtimeStartedEventDraft } from "../inspection/activity-event-adapter.ts";
14
+ import { RuntimeEventStore, type RuntimeEventRevision } from "../inspection/runtime-event-store.ts";
15
+ import { WEBUI_RUNTIME_INSTANCE_REF, webUiProjectRef, webUiSessionRef } from "../inspection/webui-snapshot.ts";
12
16
  import { prefixCompletions, registerRuntimeCommand } from "./extension-registration.ts";
13
17
 
14
18
  const INSPECTOR_ACTIONS = ["summary", "files", "commands", "security", "context", "toggle", "help"] as const;
@@ -25,12 +29,30 @@ type InspectorDependencies = {
25
29
  defaultValue?: string
26
30
  ) => Promise<string | undefined>;
27
31
  emit: (ctx: ExtensionContext, customType: string, content: string, details?: Record<string, unknown>) => void;
32
+ protectedPaths?: (ctx: ExtensionContext) => string[];
28
33
  };
29
34
 
30
35
  function sessionKey(ctx: ExtensionContext): string {
31
36
  return `${ctx.cwd}\u0000${ctx.sessionManager.getSessionId()}`;
32
37
  }
33
38
 
39
+ function revisionToken(prefix: string, value: unknown): string {
40
+ return `${prefix}.${createHash("sha256").update(JSON.stringify(value)).digest("hex")}`;
41
+ }
42
+
43
+ function eventRevision(ctx: ExtensionContext, task?: TaskContract): RuntimeEventRevision {
44
+ return {
45
+ runtimeRevision: revisionToken("runtime-rev", [WEBUI_RUNTIME_INSTANCE_REF, ctx.sessionManager.getSessionId()]),
46
+ taskRevision: task ? revisionToken("task-rev", [task.taskRunId, task.updatedAt, task.trace.outcome]) : null,
47
+ controlRevision: task ? revisionToken("control-rev", [task.taskRunId, task.trace.outcome]) : null,
48
+ workspaceRevision: null,
49
+ indexRevision: null,
50
+ approvalRevision: null,
51
+ sessionOptionRevision: null,
52
+ queueRevision: null
53
+ };
54
+ }
55
+
34
56
  function clipped(value: unknown, maximum = 96): string | undefined {
35
57
  if (typeof value !== "string") return undefined;
36
58
  const normalized = value.replace(/\s+/g, " ").trim();
@@ -67,7 +89,23 @@ export function registerActivityInspector(pi: ExtensionAPI, dependencies: Inspec
67
89
  const running = new Map<string, Map<string, CurrentActivity>>();
68
90
  const lastActivity = new Map<string, CurrentActivity>();
69
91
  const enabled = new Map<string, boolean>();
70
- const cached = new Map<string, { at: number; view: ReturnType<typeof buildActivityInspector> }>();
92
+ const cached = new Map<string, { at: number; view: Awaited<ReturnType<typeof buildActivityInspector>> }>();
93
+ const eventStores = new Map<string, RuntimeEventStore>();
94
+
95
+ function eventStore(ctx: ExtensionContext): RuntimeEventStore {
96
+ const key = sessionKey(ctx);
97
+ const existing = eventStores.get(key);
98
+ if (existing) return existing;
99
+ const projectRef = webUiProjectRef(ctx.cwd), sessionRef = webUiSessionRef(ctx.sessionManager.getSessionId());
100
+ const created = new RuntimeEventStore({ projectRoot: ctx.cwd, projectRef, runtimeInstanceId: WEBUI_RUNTIME_INSTANCE_REF, sessionRef });
101
+ eventStores.set(key, created);
102
+ if (!created.resyncRequired() && created.replay(null, 1).lastAvailableSequence === null) {
103
+ const now = new Date().toISOString();
104
+ created.append(runtimeStartedEventDraft({ identity: { projectRef, runtimeInstanceId: WEBUI_RUNTIME_INSTANCE_REF, sessionRef },
105
+ revision: eventRevision(ctx), sourceObservedAt: now, buildRef: "runtime-build.unavailable", capabilitySnapshotRef: "capabilities.inspect-only" }), now);
106
+ }
107
+ return created;
108
+ }
71
109
 
72
110
  function sessionEvents(ctx: ExtensionContext): ActivityInspectorEvent[] {
73
111
  let persisted: ActivityInspectorEvent[] = [];
@@ -85,14 +123,15 @@ export function registerActivityInspector(pi: ExtensionAPI, dependencies: Inspec
85
123
  return active.length > 0 ? active : lastActivity.has(key) ? [lastActivity.get(key) as CurrentActivity] : [];
86
124
  }
87
125
 
88
- function project(ctx: ExtensionContext, force = false, exactFiles = false) {
126
+ async function project(ctx: ExtensionContext, force = false) {
89
127
  const key = sessionKey(ctx);
90
128
  const previous = cached.get(key);
91
129
  const current = currentFor(ctx);
92
- if (!exactFiles && !force && previous && Date.now() - previous.at < 400) {
130
+ if (!force && previous && Date.now() - previous.at < 400) {
93
131
  return { ...previous.view, state: { ...previous.view.state, running: current.filter((activity) => activity.status === "running").length, current } };
94
132
  }
95
- const view = buildActivityInspector({
133
+ const events = eventStore(ctx);
134
+ const view = await buildActivityInspector({
96
135
  cwd: ctx.cwd,
97
136
  sessionId: ctx.sessionManager.getSessionId(),
98
137
  task: dependencies.activeTask(ctx),
@@ -100,8 +139,11 @@ export function registerActivityInspector(pi: ExtensionAPI, dependencies: Inspec
100
139
  sessionEntries: ctx.sessionManager.getBranch(),
101
140
  contextUsage: ctx.getContextUsage(),
102
141
  current,
103
- fileEvidenceMode: exactFiles ? "exact" : "observed",
104
- workingTreeFiles: exactFiles ? undefined : inspectWorkingTreeFiles(ctx.cwd)
142
+ protectedPaths: dependencies.protectedPaths?.(ctx),
143
+ runtimeInstanceId: WEBUI_RUNTIME_INSTANCE_REF,
144
+ eventCursor: events.currentCursor(),
145
+ resyncRequired: events.resyncRequired(),
146
+ eventReplay: events.retention()
105
147
  });
106
148
  cached.set(key, { at: Date.now(), view });
107
149
  return view;
@@ -112,7 +154,8 @@ export function registerActivityInspector(pi: ExtensionAPI, dependencies: Inspec
112
154
  if (typeof ctx.ui?.setWidget === "function") ctx.ui.setWidget("piagent-inspector", undefined);
113
155
  }
114
156
 
115
- function renderSurface(ctx: ExtensionContext, force = false): void {
157
+ async function renderSurface(ctx: ExtensionContext, force = false): Promise<void> {
158
+ if (ctx.mode !== "tui") return;
116
159
  const canUseStatus = typeof ctx.ui?.setStatus === "function";
117
160
  const canUseWidget = typeof ctx.ui?.setWidget === "function";
118
161
  if (ctx.hasUI === false || (!canUseStatus && !canUseWidget)) return;
@@ -122,7 +165,7 @@ export function registerActivityInspector(pi: ExtensionAPI, dependencies: Inspec
122
165
  return;
123
166
  }
124
167
  try {
125
- const view = project(ctx, force);
168
+ const view = await project(ctx, force);
126
169
  const color = process.env.NO_COLOR === undefined && process.env.TERM !== "dumb";
127
170
  if (canUseWidget) {
128
171
  ctx.ui.setWidget("piagent-inspector", formatActivityPanel(view, { color }), { placement: "belowEditor" });
@@ -148,6 +191,15 @@ export function registerActivityInspector(pi: ExtensionAPI, dependencies: Inspec
148
191
  };
149
192
  const stored = [...(memoryEvents.get(key) ?? []), event].slice(-1_000);
150
193
  memoryEvents.set(key, stored);
194
+ try {
195
+ const store = eventStore(ctx);
196
+ const draft = adaptActivityTelemetryEvent({ event, identity: { projectRef: webUiProjectRef(ctx.cwd), runtimeInstanceId: WEBUI_RUNTIME_INSTANCE_REF,
197
+ sessionRef: webUiSessionRef(ctx.sessionManager.getSessionId()), taskId: task?.taskId ?? null, taskRunId: task?.taskRunId ?? null },
198
+ revision: eventRevision(ctx, task) });
199
+ if (draft) store.append(draft);
200
+ } catch {
201
+ // Event replay is an optional projection. Terminal execution remains authoritative.
202
+ }
151
203
  let active = running.get(key);
152
204
  if (!active) {
153
205
  active = new Map();
@@ -182,7 +234,7 @@ export function registerActivityInspector(pi: ExtensionAPI, dependencies: Inspec
182
234
  }
183
235
  }
184
236
  cached.delete(key);
185
- renderSurface(ctx, event.event === "tool_result" || event.event === "tool_decision");
237
+ void renderSurface(ctx, event.event === "tool_result" || event.event === "tool_decision");
186
238
  }
187
239
 
188
240
  function emitHelp(ctx: ExtensionContext): void {
@@ -235,14 +287,14 @@ export function registerActivityInspector(pi: ExtensionAPI, dependencies: Inspec
235
287
  const key = sessionKey(ctx);
236
288
  const next = enabled.get(key) === false;
237
289
  enabled.set(key, next);
238
- renderSurface(ctx, true);
290
+ await renderSurface(ctx, true);
239
291
  ctx.ui.notify(`Piagent Inspector footer panel: ${next ? "on" : "off"}`, "info");
240
292
  return;
241
293
  }
242
- const view = project(ctx, true, action === "files" || action === "security");
294
+ const view = await project(ctx, true);
243
295
  const content = json ? JSON.stringify({ action, inspector: view }) : formatActivityInspector(view, action);
244
296
  dependencies.emit(ctx, `piagent-inspector-${action}`, content, { action, inspector: view });
245
- renderSurface(ctx);
297
+ void renderSurface(ctx);
246
298
  }
247
299
  });
248
300
 
@@ -254,12 +306,14 @@ export function registerActivityInspector(pi: ExtensionAPI, dependencies: Inspec
254
306
  lastActivity.delete(key);
255
307
  enabled.delete(key);
256
308
  cached.delete(key);
309
+ eventStores.delete(key);
257
310
  }
258
311
 
259
312
  return {
260
313
  observe,
261
314
  refresh: (ctx: ExtensionContext) => renderSurface(ctx, true),
262
- project: (ctx: ExtensionContext) => project(ctx, true, true),
315
+ project: (ctx: ExtensionContext) => project(ctx, true),
316
+ replay: (ctx: ExtensionContext, afterCursor: string | null, limit?: number) => eventStore(ctx).replay(afterCursor, limit),
263
317
  dispose
264
318
  };
265
319
  }
@@ -1,5 +1,4 @@
1
1
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
-
3
2
  import { exactFinalOutputGuidance } from "../quality/exact-output-contract.ts";
4
3
  import { taskPerformanceAssurance } from "../quality/performance-assurance.ts";
5
4
  import { automaticTaskSummary, boundedRuntimeIntakeMessage } from "../workflows/task-intake.ts";
@@ -7,18 +6,16 @@ import { WORKING_TREE_DIGEST_ALGORITHM } from "../../extensions/working-tree-dig
7
6
  import { createEnvironmentBoundTaskAuthority } from "../policy/task-authority-runtime.ts";
8
7
  import { authorityReplacementState } from "../policy/authority-resume-policy.ts";
9
8
  import { compileCriterionGraph, criterionGraphContextSelection, criterionGraphGuidance, criterionGraphMode } from "../../extensions/criterion-graph.js";
10
-
9
+ import { captureTaskStartBaseline } from "../inspection/task-baseline-start-capture.ts";
11
10
  type ExtensionContext = any;
12
11
  type TaskContract = any;
13
12
  type TaskStartParameters = any;
14
-
15
13
  function sameStringRecord(left: Record<string, string>, right: Record<string, string>): boolean {
16
14
  const leftEntries = Object.entries(left).sort(([a], [b]) => a.localeCompare(b));
17
15
  const rightEntries = Object.entries(right).sort(([a], [b]) => a.localeCompare(b));
18
16
  return leftEntries.length === rightEntries.length
19
17
  && leftEntries.every(([key, value], index) => rightEntries[index]?.[0] === key && rightEntries[index]?.[1] === value);
20
18
  }
21
-
22
19
  function satisfiesAuthorityReplacement(task: TaskContract, state: ReturnType<typeof authorityReplacementState>): boolean {
23
20
  if (!task.authoritySnapshot) return false;
24
21
  if (state.reason === "mechanical-rollback-requested") {
@@ -31,7 +28,6 @@ function satisfiesAuthorityReplacement(task: TaskContract, state: ReturnType<typ
31
28
  }
32
29
  return true;
33
30
  }
34
-
35
31
  export function registerTaskStartTool(pi: ExtensionAPI, deps: Record<string, any>): any {
36
32
  const {
37
33
  DEFAULT_MAX_TASK_ATTEMPTS, ORCHESTRATION_ROLES, REVIEW_LENSES, StringEnum, Type,
@@ -39,10 +35,10 @@ export function registerTaskStartTool(pi: ExtensionAPI, deps: Record<string, any
39
35
  applyRuntimeLifecycleObservation, automaticAcceptanceCriteria, automaticReadOnlyTaskScope, automaticReviewLenses, automaticTaskIntakeMode, automaticTaskRiskLane, automaticTaskScope,
40
36
  acceptanceBaselineGuidance, acceptanceProofGuidance, bindSessionTask, buildAcceptanceReceipt, compactTaskDetails, contextBudgetConfig, createTaskRunId,
41
37
  currentSessionName, defaultWorkPlan, effectiveProtectedPaths, hasGitEvidenceRoot, hasOperatorSessionName,
42
- loadProfileFromContext, normalizeReviewLenses, normalizeWorkPlanSteps, nowIso, policy,
38
+ loadProfileFromContext, matchesProtectedPath, normalizeReviewLenses, normalizeWorkPlanSteps, nowIso, policy,
43
39
  priorTaskAttempts, recordTaskStartCheckpoint, redactText, redactTextArray, registerRuntimeTool,
44
40
  repositoryFileManifest, resolveOrchestrationPolicy, resolveTaskScopePatterns, runtimeLifecycleMode, runtimeState, safeTaskId, selectVerificationPlan,
45
- summarizeAttempt, validTaskScopePattern, validateNewWorkPlan, verifierCommandInstructions, workingTreeSnapshot, workingTreeSnapshotHasUnavailableEvidence,
41
+ summarizeAttempt, validTaskScopePattern, validateNewWorkPlan, verifierCommandInstructions, workingTreeEvidenceDigest, workingTreeSnapshot, workingTreeSnapshotHasUnavailableEvidence,
46
42
  writeTask
47
43
  } = deps;
48
44
  const taskStartTool = {
@@ -287,6 +283,15 @@ export function registerTaskStartTool(pi: ExtensionAPI, deps: Record<string, any
287
283
  if (changeMode === "source-change" && workingTreeSnapshotHasUnavailableEvidence(baselineFileDigests)) {
288
284
  return { content: [{ type: "text", text: "Task start refused: the baseline contains unavailable working-tree content evidence. Restore readable repository files before starting source changes." }], isError: true };
289
285
  }
286
+ if (changeMode === "source-change") {
287
+ const protectedPaths = effectiveProtectedPaths(policy, profile).readProtectedPaths;
288
+ try {
289
+ await captureTaskStartBaseline({ projectRoot: ctx.cwd, taskId, taskRunId, sessionId, capturedAt: createdAt,
290
+ baselineTreeDigest: workingTreeEvidenceDigest(baselineFileDigests), protectedPaths, matchesProtectedPath });
291
+ } catch {
292
+ return { content: [{ type: "text", text: "Task start refused: the private Task Baseline Manifest could not be captured safely. Inspect local-state permissions and retry before editing." }], isError: true };
293
+ }
294
+ }
290
295
  const acceptance = buildAcceptanceReceipt({
291
296
  summary: safeSummary,
292
297
  expectedOutput: redactText(params.expectedOutput),
@@ -369,7 +374,6 @@ export function registerTaskStartTool(pi: ExtensionAPI, deps: Record<string, any
369
374
  appendTrace(ctx.cwd, { taskId, taskRunId, sessionId, sessionName, attempt, event: "task_start", summary: task.summary, riskLane: params.riskLane, intakeMode: task.intakeMode, changeMode: task.changeMode, lifecycleMode, criterionGraphMode: written.criterionGraph.mode, criterionGraphDigest: written.criterionGraph.graphDigest, authorityProfile: written.authoritySnapshot.profile, authoritySnapshotDigest: written.authoritySnapshot.snapshotDigest, scopeMappings, seededContext: seededContext.map((item) => item.path) });
370
375
  appendSessionTrace(pi, { taskId, taskRunId, sessionId, sessionName, attempt, event: "task_start", summary: task.summary, riskLane: params.riskLane, intakeMode: task.intakeMode, changeMode: task.changeMode, lifecycleMode, criterionGraphMode: written.criterionGraph.mode, criterionGraphDigest: written.criterionGraph.graphDigest, authorityProfile: written.authoritySnapshot.profile, authoritySnapshotDigest: written.authoritySnapshot.snapshotDigest, scopeMappings, seededContext: seededContext.map((item) => item.path) });
371
376
  recordTaskStartCheckpoint(ctx, written, firstReady.id, lifecycleMode);
372
-
373
377
  return {
374
378
  content: [{
375
379
  type: "text",
@@ -408,18 +412,13 @@ export function registerTaskStartTool(pi: ExtensionAPI, deps: Record<string, any
408
412
  }
409
413
  };
410
414
  registerRuntimeTool(pi, taskStartTool);
411
-
412
- async function maybeStartAutomaticTask(
413
- prompt: string,
414
- ctx: ExtensionContext
415
- ): Promise<{ started: boolean; text: string; task?: TaskContract } | undefined> {
415
+ async function maybeStartAutomaticTask(prompt: string, ctx: ExtensionContext): Promise<{ started: boolean; text: string; task?: TaskContract } | undefined> {
416
416
  const profile = loadProfileFromContext(ctx);
417
417
  const readProtectedPaths = effectiveProtectedPaths(policy, profile).readProtectedPaths;
418
418
  const intakeMode = automaticTaskIntakeMode(prompt, readProtectedPaths);
419
419
  if (!intakeMode) return undefined;
420
420
  const active = activeSessionTask(ctx.cwd, ctx.sessionManager.getSessionId()) as TaskContract | undefined;
421
421
  if (active?.trace.outcome === "pending") return undefined;
422
-
423
422
  const summary = redactText(automaticTaskSummary(prompt));
424
423
  const sessionName = currentSessionName(ctx);
425
424
  const projectFiles = repositoryFileManifest(ctx.cwd);
@@ -17,6 +17,12 @@ type AuthorizedMutation = {
17
17
  };
18
18
 
19
19
  export type ModelMutationCompletion = { changedPaths: string[]; recordedDigests: Record<string, string> };
20
+ export type ModelMutationEvidenceCompletion = ModelMutationCompletion & {
21
+ beforeSnapshot: Record<string, string> | null;
22
+ targetPaths: string[];
23
+ recordedContentDigests: Record<string, string>;
24
+ proofModes: Record<string, "full-content" | "exact-replacement">;
25
+ };
20
26
 
21
27
  function uniquePaths(values: string[]): string[] {
22
28
  return [...new Set(values.map((value) => String(value ?? "").replaceAll("\\", "/").replace(/^\.\//, "").trim()).filter(Boolean))].sort();
@@ -95,16 +101,30 @@ export class ModelAuthorshipState {
95
101
  currentSnapshot: Record<string, string>,
96
102
  currentContentDigests: Record<string, string> = {}
97
103
  ): ModelMutationCompletion {
104
+ const result = this.completeWithEvidence(identity, toolCallId, success, currentSnapshot, currentContentDigests);
105
+ return { changedPaths: result.changedPaths, recordedDigests: result.recordedDigests };
106
+ }
107
+
108
+ completeWithEvidence(
109
+ identity: ModelMutationIdentity,
110
+ toolCallId: string,
111
+ success: boolean,
112
+ currentSnapshot: Record<string, string>,
113
+ currentContentDigests: Record<string, string> = {}
114
+ ): ModelMutationEvidenceCompletion {
98
115
  const key = this.#key(identity.taskRunId, toolCallId);
99
116
  const reservation = this.#reservations.get(key);
100
117
  this.#reservations.delete(key);
101
- if (!reservation) return { changedPaths: [], recordedDigests: {} };
118
+ const empty: ModelMutationEvidenceCompletion = {
119
+ changedPaths: [], recordedDigests: {}, beforeSnapshot: null, targetPaths: [], recordedContentDigests: {}, proofModes: {}
120
+ };
121
+ if (!reservation) return empty;
102
122
  const changed = changedPaths(reservation.workingTreeSnapshot, currentSnapshot);
103
123
  const evidence = this.#taskEvidence(reservation.identity.taskRunId);
104
124
  const proofPaths = uniquePaths([...reservation.proof.fullContentPaths, ...reservation.proof.replacePaths]);
105
125
  const invalidate = () => {
106
126
  for (const file of uniquePaths([...reservation.targetPaths, ...changed])) evidence.delete(file);
107
- return { changedPaths: changed, recordedDigests: {} };
127
+ return { ...empty, changedPaths: changed, beforeSnapshot: { ...reservation.workingTreeSnapshot }, targetPaths: [...reservation.targetPaths] };
108
128
  };
109
129
  if (!sameIdentity(reservation.identity, identity) || !success || changed.length === 0 || !exactPaths(changed, proofPaths)) return invalidate();
110
130
  const candidates: Array<{ file: string; workingTreeDigest: string; contentDigest: string }> = [];
@@ -116,12 +136,20 @@ export class ModelAuthorshipState {
116
136
  candidates.push({ file, workingTreeDigest, contentDigest: content });
117
137
  }
118
138
  const recordedDigests: Record<string, string> = {};
139
+ const recordedContentDigests: Record<string, string> = {};
140
+ const proofModes: Record<string, "full-content" | "exact-replacement"> = {};
119
141
  for (const candidate of candidates) {
120
142
  evidence.set(candidate.file, { ...reservation.identity, ...candidate });
121
143
  recordedDigests[candidate.file] = candidate.workingTreeDigest;
144
+ recordedContentDigests[candidate.file] = candidate.contentDigest;
145
+ proofModes[candidate.file] = reservation.proof.fullContentPaths.includes(candidate.file) ? "full-content" : "exact-replacement";
122
146
  }
123
147
  while (this.#evidence.size > 100) this.#evidence.delete(this.#evidence.keys().next().value as string);
124
- return { changedPaths: changed, recordedDigests };
148
+ return {
149
+ changedPaths: changed, recordedDigests,
150
+ beforeSnapshot: { ...reservation.workingTreeSnapshot }, targetPaths: [...reservation.targetPaths],
151
+ recordedContentDigests, proofModes
152
+ };
125
153
  }
126
154
 
127
155
  digests(identity: ModelMutationIdentity, currentSnapshot?: Record<string, string>): Record<string, string> {
@@ -6,7 +6,7 @@ import type { TaskContract } from "../../extensions/guard-types.ts";
6
6
  import type { RecoveryHistoryEntry } from "../recovery/recovery-policy.ts";
7
7
  import type { ResumeState } from "../recovery/resume-state.ts";
8
8
  import { ModelAuthorshipState } from "./model-authorship-state.ts";
9
- import type { ModelMutationIdentity } from "./model-authorship-state.ts";
9
+ import type { ModelMutationEvidenceCompletion, ModelMutationIdentity } from "./model-authorship-state.ts";
10
10
  import type { ModelMutationProof } from "../quality/model-mutation-proof.ts";
11
11
  import { PerformanceReviewState } from "./performance-review-state.ts";
12
12
  import type {
@@ -239,6 +239,16 @@ export class RuntimeSessionState {
239
239
  return this.#modelAuthorship.complete(identity, toolCallId, success, currentSnapshot, currentContentDigests);
240
240
  }
241
241
 
242
+ completeAuthorizedModelMutationEvidence(
243
+ identity: ModelMutationIdentity,
244
+ toolCallId: string,
245
+ success: boolean,
246
+ currentSnapshot: Record<string, string>,
247
+ currentContentDigests: Record<string, string> = {}
248
+ ): ModelMutationEvidenceCompletion {
249
+ return this.#modelAuthorship.completeWithEvidence(identity, toolCallId, success, currentSnapshot, currentContentDigests);
250
+ }
251
+
242
252
  successfulModelMutationDigests(identity: ModelMutationIdentity, currentSnapshot?: Record<string, string>): Record<string, string> {
243
253
  return this.#modelAuthorship.digests(identity, currentSnapshot);
244
254
  }