pi-ui-extend 1.0.40 → 1.0.42

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 (186) hide show
  1. package/README.md +10 -2
  2. package/dist/app/app.d.ts +3 -0
  3. package/dist/app/app.js +26 -0
  4. package/dist/app/commands/command-host.d.ts +1 -0
  5. package/dist/app/commands/command-model-actions.js +6 -1
  6. package/dist/app/commands/command-registry.js +3 -3
  7. package/dist/app/commands/command-session-actions.d.ts +0 -1
  8. package/dist/app/commands/command-session-actions.js +30 -15
  9. package/dist/app/commands/reload-context-inventory.d.ts +11 -0
  10. package/dist/app/commands/reload-context-inventory.js +59 -0
  11. package/dist/app/extensions/extension-actions-controller.d.ts +1 -0
  12. package/dist/app/extensions/extension-actions-controller.js +6 -0
  13. package/dist/app/extensions/subagent-catalog-state.d.ts +9 -0
  14. package/dist/app/extensions/subagent-catalog-state.js +23 -0
  15. package/dist/app/icons.d.ts +14 -0
  16. package/dist/app/icons.js +33 -0
  17. package/dist/app/rendering/conversation-tool-renderer.js +2 -2
  18. package/dist/app/rendering/dcp-stats.d.ts +6 -1
  19. package/dist/app/rendering/dcp-stats.js +214 -46
  20. package/dist/app/rendering/editor-panels.js +17 -8
  21. package/dist/app/session/lazy-session-manager.js +12 -1
  22. package/dist/app/session/session-lifecycle-controller.d.ts +1 -0
  23. package/dist/app/session/session-lifecycle-controller.js +6 -0
  24. package/dist/app/session/tabs-controller.d.ts +3 -5
  25. package/dist/app/session/tabs-controller.js +31 -22
  26. package/dist/app/subagents/subagents-files.js +60 -1
  27. package/dist/app/subagents/subagents-model.d.ts +15 -1
  28. package/dist/app/subagents/subagents-model.js +52 -17
  29. package/dist/app/types.d.ts +7 -0
  30. package/dist/bundled-extensions/session-title/config.js +1 -1
  31. package/dist/default-pix-config.js +10 -0
  32. package/dist/markdown-format.js +27 -9
  33. package/dist/schemas/index.d.ts +1 -0
  34. package/dist/schemas/index.js +1 -0
  35. package/dist/schemas/pi-tools-suite-schema.d.ts +106 -71
  36. package/dist/schemas/pi-tools-suite-schema.js +68 -88
  37. package/dist/schemas/pix-schema.d.ts +7 -0
  38. package/dist/schemas/pix-schema.js +14 -0
  39. package/dist/schemas/tasks-schema.d.ts +18 -0
  40. package/dist/schemas/tasks-schema.js +41 -0
  41. package/docs/concurrency.md +6 -0
  42. package/docs/desktop-mvp.md +12 -1
  43. package/docs/desktop-task-manager.md +93 -82
  44. package/external/pi-tools-suite/README.md +192 -72
  45. package/external/pi-tools-suite/docs/browser-qa-subagent.md +50 -21
  46. package/external/pi-tools-suite/docs/context-gateway-p00-adr.md +216 -0
  47. package/external/pi-tools-suite/docs/context-gateway-p01n-gate-review.md +122 -0
  48. package/external/pi-tools-suite/docs/context-gateway-p01n-measurement.md +133 -0
  49. package/external/pi-tools-suite/docs/context-gateway-p01r-ra-evidence.md +111 -0
  50. package/external/pi-tools-suite/docs/context-gateway-p01r-rb-evidence.md +100 -0
  51. package/external/pi-tools-suite/docs/context-gateway-p01r-rc-evidence.md +69 -0
  52. package/external/pi-tools-suite/docs/context-gateway-p01r-rd-evidence.md +100 -0
  53. package/external/pi-tools-suite/docs/context-gateway-p01r-re-evidence.md +74 -0
  54. package/external/pi-tools-suite/docs/context-gateway-p01r-rf-evidence.md +153 -0
  55. package/external/pi-tools-suite/docs/context-gateway-p01r-rg-evidence.md +235 -0
  56. package/external/pi-tools-suite/docs/evals.md +1 -1
  57. package/external/pi-tools-suite/docs/session-recovery.md +40 -14
  58. package/external/pi-tools-suite/docs/subagent-model-pools.md +120 -0
  59. package/external/pi-tools-suite/package.json +3 -0
  60. package/external/pi-tools-suite/src/async-subagents/{private-skills → agents}/browser-qa/scripts/browser-qa-runner.mjs +82 -1
  61. package/external/pi-tools-suite/src/async-subagents/{private-skills/browser-qa/SKILL.md → agents/browser-qa.md} +261 -12
  62. package/external/pi-tools-suite/src/async-subagents/agents/frontier-review.md +23 -0
  63. package/external/pi-tools-suite/src/async-subagents/agents/implement.md +20 -0
  64. package/external/pi-tools-suite/src/async-subagents/agents/oracle.md +16 -0
  65. package/external/pi-tools-suite/src/async-subagents/agents/presets.jsonc +16 -0
  66. package/external/pi-tools-suite/src/async-subagents/agents/research.md +20 -0
  67. package/external/pi-tools-suite/src/async-subagents/agents/verify.md +18 -0
  68. package/external/pi-tools-suite/src/async-subagents/commands.ts +20 -72
  69. package/external/pi-tools-suite/src/async-subagents/core/activity.ts +33 -0
  70. package/external/pi-tools-suite/src/async-subagents/core/agent-catalog.ts +42 -0
  71. package/external/pi-tools-suite/src/async-subagents/core/agent-strategy.ts +13 -93
  72. package/external/pi-tools-suite/src/async-subagents/core/agents-dir.ts +499 -0
  73. package/external/pi-tools-suite/src/async-subagents/core/browser-qa.ts +9 -0
  74. package/external/pi-tools-suite/src/async-subagents/core/config.ts +284 -417
  75. package/external/pi-tools-suite/src/async-subagents/core/model-fallback.ts +1 -1
  76. package/external/pi-tools-suite/src/async-subagents/core/model-selection.ts +54 -0
  77. package/external/pi-tools-suite/src/async-subagents/core/prompt.ts +7 -6
  78. package/external/pi-tools-suite/src/async-subagents/core/routing.ts +65 -45
  79. package/external/pi-tools-suite/src/async-subagents/core/spawn.ts +18 -6
  80. package/external/pi-tools-suite/src/async-subagents/core/state.ts +40 -0
  81. package/external/pi-tools-suite/src/async-subagents/core/types.ts +7 -0
  82. package/external/pi-tools-suite/src/async-subagents/index.ts +77 -3
  83. package/external/pi-tools-suite/src/async-subagents/lib.ts +12 -9
  84. package/external/pi-tools-suite/src/async-subagents/tools/spawn.ts +54 -22
  85. package/external/pi-tools-suite/src/async-subagents/tools/subagents.ts +6 -4
  86. package/external/pi-tools-suite/src/async-subagents/types.ts +3 -0
  87. package/external/pi-tools-suite/src/config.ts +42 -2
  88. package/external/pi-tools-suite/src/context-gateway/accounting.ts +151 -0
  89. package/external/pi-tools-suite/src/context-gateway/config.ts +120 -0
  90. package/external/pi-tools-suite/src/context-gateway/enforcement.ts +102 -0
  91. package/external/pi-tools-suite/src/context-gateway/index.ts +214 -0
  92. package/external/pi-tools-suite/src/context-gateway/metadata-normalization.ts +88 -0
  93. package/external/pi-tools-suite/src/context-gateway/storeless-capabilities.ts +89 -0
  94. package/external/pi-tools-suite/src/context-gateway/telemetry.ts +502 -0
  95. package/external/pi-tools-suite/src/context-gateway/test-output-parser.ts +326 -0
  96. package/external/pi-tools-suite/src/context-gateway/types.ts +158 -0
  97. package/external/pi-tools-suite/src/context-inventory.ts +99 -0
  98. package/external/pi-tools-suite/src/dcp/auto-compress-budget.ts +106 -0
  99. package/external/pi-tools-suite/src/dcp/auto-compress.ts +892 -136
  100. package/external/pi-tools-suite/src/dcp/commands.ts +82 -139
  101. package/external/pi-tools-suite/src/dcp/compress-tool.ts +533 -74
  102. package/external/pi-tools-suite/src/dcp/compression-blocks.ts +488 -94
  103. package/external/pi-tools-suite/src/dcp/compression-preview.ts +122 -0
  104. package/external/pi-tools-suite/src/dcp/compression-progress.ts +70 -0
  105. package/external/pi-tools-suite/src/dcp/config.ts +86 -68
  106. package/external/pi-tools-suite/src/dcp/conversation-index.ts +421 -0
  107. package/external/pi-tools-suite/src/dcp/debug-log.ts +7 -5
  108. package/external/pi-tools-suite/src/dcp/index.ts +617 -203
  109. package/external/pi-tools-suite/src/dcp/journal.ts +566 -0
  110. package/external/pi-tools-suite/src/dcp/progress-controller.ts +244 -0
  111. package/external/pi-tools-suite/src/dcp/prompts.ts +83 -189
  112. package/external/pi-tools-suite/src/dcp/protected-continuity.ts +175 -0
  113. package/external/pi-tools-suite/src/dcp/provider-tool-results.ts +189 -0
  114. package/external/pi-tools-suite/src/dcp/pruner-candidates.ts +299 -79
  115. package/external/pi-tools-suite/src/dcp/pruner-compression-blocks.ts +173 -281
  116. package/external/pi-tools-suite/src/dcp/pruner-emergency.ts +2 -4
  117. package/external/pi-tools-suite/src/dcp/pruner-message-ids.ts +23 -15
  118. package/external/pi-tools-suite/src/dcp/pruner-metadata.ts +11 -1
  119. package/external/pi-tools-suite/src/dcp/pruner-nudge.ts +30 -82
  120. package/external/pi-tools-suite/src/dcp/pruner-tools.ts +28 -136
  121. package/external/pi-tools-suite/src/dcp/pruner.ts +18 -33
  122. package/external/pi-tools-suite/src/dcp/recovery.ts +129 -0
  123. package/external/pi-tools-suite/src/dcp/shadow-plan.ts +127 -0
  124. package/external/pi-tools-suite/src/dcp/state-transaction.ts +102 -0
  125. package/external/pi-tools-suite/src/dcp/state.ts +158 -580
  126. package/external/pi-tools-suite/src/dcp/ui.ts +1 -0
  127. package/external/pi-tools-suite/src/default-pi-tools-suite-config.ts +36 -214
  128. package/external/pi-tools-suite/src/index.ts +16 -1
  129. package/external/pi-tools-suite/src/model-tools/index.ts +76 -42
  130. package/external/pi-tools-suite/src/repo-discovery/index.ts +84 -18
  131. package/external/pi-tools-suite/src/repo-discovery/native-compact.ts +458 -0
  132. package/external/pi-tools-suite/src/resource-registry/index.ts +2290 -0
  133. package/external/pi-tools-suite/src/session-recovery/index.ts +189 -43
  134. package/external/pi-tools-suite/src/shell-command-policy.ts +219 -0
  135. package/external/pi-tools-suite/src/tool-descriptions.ts +41 -38
  136. package/external/pi-tools-suite/src/truncation-metadata-normalizer/index.ts +17 -0
  137. package/package.json +6 -3
  138. package/schemas/pi-tools-suite.json +540 -312
  139. package/schemas/pix.json +24 -0
  140. package/schemas/tasks.json +132 -0
  141. package/skills/spec-wiki/SKILL.md +55 -0
  142. package/skills/spec-wiki/evals/evals.json +132 -0
  143. package/skills/spec-wiki/evals/files/bootstrap/architecture/rfc-007.md +14 -0
  144. package/skills/spec-wiki/evals/files/bootstrap/docs/how-to-pay.md +4 -0
  145. package/skills/spec-wiki/evals/files/bootstrap/docs/overview.md +9 -0
  146. package/skills/spec-wiki/evals/files/bootstrap/requirements/payment-behavior.md +17 -0
  147. package/skills/spec-wiki/evals/files/bootstrap/src/payments.ts +12 -0
  148. package/skills/spec-wiki/evals/files/bootstrap/tests/payments.test.ts +11 -0
  149. package/skills/spec-wiki/evals/files/focused/src/session.ts +5 -0
  150. package/skills/spec-wiki/evals/files/focused/tests/session.test.ts +17 -0
  151. package/skills/spec-wiki/evals/files/maintenance/low-signal/incoming/capture.txt +2 -0
  152. package/skills/spec-wiki/evals/files/maintenance/low-signal/src/capture.ts +3 -0
  153. package/skills/spec-wiki/evals/files/maintenance/move/docs/old-job-contract.md +18 -0
  154. package/skills/spec-wiki/evals/files/maintenance/move/src/job.ts +5 -0
  155. package/skills/spec-wiki/evals/files/maintenance/new-relation/docs/session-refresh.md +24 -0
  156. package/skills/spec-wiki/evals/files/maintenance/new-relation/incoming/refresh-worker.ts +7 -0
  157. package/skills/spec-wiki/evals/files/maintenance/new-relation/src/session.ts +7 -0
  158. package/skills/spec-wiki/evals/files/maintenance/no-impact/docs/auth-contract.md +17 -0
  159. package/skills/spec-wiki/evals/files/maintenance/no-impact/incoming/telemetry-format.ts +3 -0
  160. package/skills/spec-wiki/evals/files/maintenance/no-impact/src/auth.ts +3 -0
  161. package/skills/spec-wiki/evals/files/query/docs/how-to-run-jobs.md +4 -0
  162. package/skills/spec-wiki/evals/files/query/docs/spec-overview.md +9 -0
  163. package/skills/spec-wiki/evals/files/query/features/jobs/cancellation-contract.md +15 -0
  164. package/skills/spec-wiki/evals/files/query/features/jobs/retry-spec.md +6 -0
  165. package/skills/spec-wiki/evals/maintenance_regression.py +311 -0
  166. package/skills/spec-wiki/evals/retrieval-eval.md +37 -0
  167. package/skills/spec-wiki/evals/retrieval-evals.json +37 -0
  168. package/skills/spec-wiki/evals/trigger-evals.json +94 -0
  169. package/skills/spec-wiki/references/bootstrap.md +100 -0
  170. package/skills/spec-wiki/references/focused-spec.md +117 -0
  171. package/skills/spec-wiki/references/index-schema.md +330 -0
  172. package/skills/spec-wiki/references/maintenance.md +134 -0
  173. package/skills/spec-wiki/references/query.md +74 -0
  174. package/skills/spec-wiki/scripts/spec_wiki.py +2076 -0
  175. package/docs/desktop-markdown-media.md +0 -77
  176. package/external/pi-tools-suite/docs/dcp-emergency-current-turn.md +0 -102
  177. package/external/pi-tools-suite/src/async-subagents/async-subagents.sample.jsonc +0 -270
  178. package/external/pi-tools-suite/src/async-subagents/private-skills/browser-qa/references/auth-scaffold-spec.md +0 -78
  179. package/external/pi-tools-suite/src/async-subagents/private-skills/browser-qa/references/qa-design.md +0 -223
  180. package/external/pi-tools-suite/src/dcp/state-persistence.ts +0 -195
  181. package/external/pi-tools-suite/src/skill-installer/index.ts +0 -333
  182. package/skills/spec-lite/SKILL.md +0 -140
  183. /package/external/pi-tools-suite/src/async-subagents/{private-skills/browser-qa/references → agents/browser-qa/examples}/qa-auth.example.jsonc +0 -0
  184. /package/external/pi-tools-suite/src/async-subagents/{private-skills/browser-qa/references → agents/browser-qa/examples}/qa-flow.example.jsonc +0 -0
  185. /package/external/pi-tools-suite/src/async-subagents/{private-skills → agents}/browser-qa/vendor/fflate.LICENSE +0 -0
  186. /package/external/pi-tools-suite/src/async-subagents/{private-skills → agents}/browser-qa/vendor/fflate.mjs +0 -0
@@ -0,0 +1,235 @@
1
+ # Context Gateway P01-R / R-G storeless release evidence
2
+
3
+ <!-- markdownlint-disable MD013 -->
4
+
5
+ > Scope frozen before the R-G measurement gate on 7 September 2026.
6
+ > Repository HEAD: `daa1b06`; tested source tree is dirty and earlier live run identities must not be inferred from HEAD alone.
7
+ > This document does not authorise Context Gateway enforce mode or P02 durable storage.
8
+
9
+ ## Scope fixed before measurement
10
+
11
+ The candidate storeless release is deliberately small:
12
+
13
+ | Surface | Decision for R-G | Runtime effect |
14
+ | --- | --- | --- |
15
+ | Context Gateway observe | Keep available, `off` by default | Aggregate measurement/classification only; no result replacement or archive. |
16
+ | `repo_*` Native Compact | Accept as explicit opt-in profile | Existing bounded native flags/cursors/validation; no store. |
17
+ | `truncation-metadata-normalizer` | Accept as separate explicit opt-in module | Removes only proven duplicate truncation metadata for measured Read/shell/ast_grep shapes. |
18
+ | test/build parser | Keep observe-only | Safe classification/metrics only; no result replacement. |
19
+ | mutation/LSP | Native passthrough | Existing outcome/diagnostics behavior only. |
20
+ | web/document | Native passthrough / limited | No second fetch, no archive. |
21
+ | structured JSON | Native passthrough / limited | No generic parse/rewrite. |
22
+ | subagent result | Native passthrough / producer-managed lifetime | No parent grant or lifetime extension. |
23
+ | images | Native passthrough | No text replacement. |
24
+ | direct browser / MCP | Unsupported | Not in the claimed denominator. |
25
+
26
+ Provider-specific equality claims are limited to the installed OpenAI-completions
27
+ serialization path already exercised by the deterministic harness. UI claims are
28
+ limited to the current TUI result renderers and the existing ACP/Desktop lazy
29
+ persisted-result flow. Native temp-output contents do not get a new UI/ACP reader.
30
+
31
+ ## Metrics and release criteria fixed before measurement
32
+
33
+ R-G evaluates the following dimensions independently:
34
+
35
+ - task/fact correctness and execution outcome;
36
+ - initial delivered result bytes and all continuation/recovery calls;
37
+ - JSONL/details bytes for metadata-only cleanup;
38
+ - actual checked provider payload equality/usage rather than converting metadata
39
+ bytes into token estimates;
40
+ - tool-call/refusal/retry counts and elapsed time for model-driven evidence that
41
+ already exists;
42
+ - parser/capability CPU work through explicit scan/output bounds rather than a
43
+ claim based on one timing sample;
44
+ - native temp/current-file/index lifetime limitations and unavailable recovery;
45
+ - unsupported paths and failures remain in the report rather than being removed
46
+ from the denominator.
47
+
48
+ There is no aggregate batch-budget claim. P00 proved stable per-call identity and
49
+ source-order delivery, but not a host API that supplies a durable whole-batch
50
+ budget before execution. Batch cost is therefore the sum of actual per-result
51
+ traffic/calls in measurements.
52
+
53
+ ## Measurement results
54
+
55
+ The measurements below were run after the scope and criteria above were written.
56
+
57
+ ### Native Compact deterministic paired corpus
58
+
59
+ `PI_CONTEXT_GATEWAY_BENCHMARK_REPORT=1 bun test test/context-gateway/benchmark.test.ts`
60
+ compares the historical baseline behavior with the current Native Compact profile
61
+ over search, structure, AST, explain and dependency scenarios. All eight critical
62
+ facts are recovered in both arms.
63
+
64
+ | Metric | Baseline | Native Compact | Delta |
65
+ | --- | ---: | ---: | ---: |
66
+ | Delivered repo bytes including continuations | 71,025 | 27,519 | **-61.25%** |
67
+ | Tool calls | 6 | 8 | +2 |
68
+ | Continuation calls | 1 | 3 | +2 |
69
+ | Refusals | 0 | 0 | 0 |
70
+ | Full overrides | 0 | 0 | 0 |
71
+ | Critical facts | 8/8 | 8/8 | equal |
72
+
73
+ This is the expected trade-off for narrow native paging: substantially fewer
74
+ delivered bytes, but potentially more calls. It is not evidence of lower total
75
+ model cost by itself.
76
+
77
+ ### Historical model-driven paired evidence
78
+
79
+ The retained `zai/glm-5.3` paired report
80
+ `test/evals/artifacts/p01n-2026-09-07T17-30-21-479Z/p01n-paired-report.json`
81
+ contains three Prompt Compact / Native Compact pairs; all **6 arm-runs passed**.
82
+ It predates R-A v2 source/corpus identity, so R-G uses it only as historical
83
+ model-behavior/cost evidence rather than pretending it certifies the current dirty
84
+ tree byte-for-byte.
85
+
86
+ | Aggregate metric | Prompt Compact | Native Compact | Delta |
87
+ | --- | ---: | ---: | ---: |
88
+ | Repo-result bytes | 1,286 | 983 | **-23.6%** |
89
+ | All tool-result bytes | 9,737 | 9,149 | **-6.0%** |
90
+ | Tool calls | 14 | 12 | **-14.3%** |
91
+ | Parent tokens | 179,855 | 207,611 | **+15.4%** |
92
+ | Parent cost | $0.0682 | $0.0923 | **+35.4%** |
93
+ | Elapsed | 88.682s | 96.219s | **+8.5%** |
94
+ | Native refusals / full overrides / refusal retries | 0 / 0 / 0 | 0 / 0 / 0 | equal |
95
+
96
+ The live evidence therefore argues **against** making Native Compact the default:
97
+ repo traffic improved, but total token/cost/latency did not consistently improve.
98
+ It remains a useful explicit opt-in for workloads where repo-result volume is the
99
+ binding constraint.
100
+
101
+ ### Metadata normalizer
102
+
103
+ The normalizer changes only `details.truncation.content` on proven Read/shell/
104
+ `ast_grep` SDK shapes. A deterministic 24,007-byte duplicate fixture measured:
105
+
106
+ | Metric | Raw | Normalized | Delta |
107
+ | --- | ---: | ---: | ---: |
108
+ | Serialized tool-result JSON | 48,396 B | 24,376 B | **-24,020 B (-49.6%)** |
109
+ | Ten identical persisted results | — | — | **240,200 B avoided** |
110
+
111
+ The actual SDK fixtures in R-B also remove more than 40 KiB of duplicated metadata
112
+ from large Read/Bash results while preserving visible content and structural
113
+ truncation fields.
114
+
115
+ This is deliberately reported as JSONL/metadata savings only. The installed
116
+ OpenAI-completions serialization contract is byte-equivalent before/after cleanup
117
+ because tool-result `details` are not serialized to that provider payload. R-G
118
+ therefore claims **no token, cache or model-quality saving** from the normalizer.
119
+
120
+ An additional 52,000-byte duplicate sample, matching the approximate size of the
121
+ live observe residual details, measured `104,408 → 52,395 B` for the serialized
122
+ tool-result object and `52,279 → 266 B` for `details`: **52,013 B** removed while
123
+ visible content remained `52,035 B`. Seven reference-machine rounds of 10,000
124
+ normalizer calls on that sample measured approximately `3.5–4.3 µs/call`. These
125
+ timings are diagnostics, not a portable release threshold.
126
+
127
+ ### Residual and negative corpus
128
+
129
+ The live observe-only residual run shows the measured large classes remain real:
130
+ Read/Bash/ast_grep each delivered roughly 52 KiB of result content and roughly
131
+ another 52 KiB of details at the checked boundary. The Bash task assertion failed
132
+ because the model made an extra call; the large Bash observation itself remained
133
+ valid. That failure stays visible rather than being removed from the denominator.
134
+
135
+ R-A–R-F deterministic contracts cover the rest of the offline release corpus:
136
+
137
+ - small/exact/control results and current-file Read continuation;
138
+ - Unicode/CRLF/long-line and changed file/index behavior;
139
+ - successful Bash/ast_grep native recovery plus missing/replaced temp output;
140
+ - timeout/abort/nonzero and unavailable structured recovery handles;
141
+ - parser middle failures, PASS→exit-1 conflict, ANSI/CR, mixed/compound commands,
142
+ unknown formats and a bounded 1 Mi-character parser scan;
143
+ - mutation/LSP outcomes, web errors/cancellation, opaque large-integer JSON,
144
+ subagent producer-managed artifacts, image passthrough and unsupported browser/MCP;
145
+ - late/reloaded/session-switched results, parallel calls and UI/history replay.
146
+
147
+ The test/build parser is bounded but remains observe-only. Its prospective compact
148
+ candidate is all-or-passthrough and must fit the configured result budget; no
149
+ runtime result delivery, provider traffic, calls or token usage are changed by it.
150
+ On a 4,550,063-character synthetic input the 1 Mi-character scan bound produced
151
+ `scan-limited / partial`; seven rounds of 100 parses measured about
152
+ `16.2–16.9 ms/call` on the reference machine. This is CPU/telemetry evidence only,
153
+ not a shaping or provider-saving claim.
154
+
155
+ ## Live-run decision
156
+
157
+ R-G does **not** request another live model run for the selected release scope:
158
+
159
+ - the metadata normalizer is provider-invisible on the checked serializer and has
160
+ deterministic JSONL/provider equality contracts;
161
+ - the test/build parser does not replace results;
162
+ - mutation/LSP, web/JSON/subagent/image surfaces remain native passthrough;
163
+ - Native Compact already has retained paired model-driven evidence, while all
164
+ post-run changes relevant to this scope are deterministic policy/validation
165
+ hardening rather than a new model-visible adapter.
166
+
167
+ The R-A v2 recovery runner remains available for a future claim that specifically
168
+ depends on exact model-driven native-handle recovery. Such a run still requires
169
+ separate authorization and must create a new v2-identity report. R-G does not
170
+ reinterpret the old v1 recovery reports as v2 passes.
171
+
172
+ ## Release decision
173
+
174
+ Accept the verified storeless scope with conservative defaults:
175
+
176
+ 1. **Context Gateway stays `off` by default.** Observe remains an explicit passive
177
+ measurement mode; `enforce` remains unavailable.
178
+ 2. **Native Compact is accepted only as explicit opt-in.** Default
179
+ `repoDiscovery.profile` remains `baseline` because live total-cost evidence is
180
+ mixed despite lower repo-result traffic.
181
+ 3. **`truncation-metadata-normalizer` is accepted as a separate explicit opt-in.**
182
+ It remains disabled by default and claims JSONL/metadata reduction, not token
183
+ savings.
184
+ 4. **Test/build parsing stays observe-only.** No production compact-result adapter
185
+ is enabled without a proven recovery/lifetime contract for omitted data.
186
+ 5. **Mutation/LSP, web/document, JSON, subagent and visual paths remain their R-E
187
+ passthrough/limited decisions.** Browser/MCP direct adapters remain unsupported.
188
+ 6. **P02 durable store remains deferred.** R-G found no task requiring new durable
189
+ snapshot identity strongly enough to justify store/readers/quotas now.
190
+
191
+ Rollback is configuration-only for future calls: disable the normalizer module,
192
+ return `repoDiscovery.profile` to `baseline`, and/or set Context Gateway mode to
193
+ `off`. Rollback does not delete session history, native temp files, user data or
194
+ DCP state and does not require a manual sync operation.
195
+
196
+ ## Deterministic R-G gate
197
+
198
+ The final gate reuses the independently proven R-A–R-F contracts rather than one
199
+ monolithic test process where unrelated LSP/AgentSession suites can interfere with
200
+ shared process/temp state. The required groups are:
201
+
202
+ - Context Gateway/storeless contracts, Native Compact, recovery validator/corpus,
203
+ eval harness and coverage registry;
204
+ - ACP lazy history/replay and typecheck;
205
+ - root tab ownership/session UI contracts;
206
+ - suite/root `git diff --check` and source typechecks.
207
+
208
+ No new live model call, manual suite sync, durable store, reader tool or DCP change
209
+ is part of the R-G release gate.
210
+
211
+ The final external-suite P01-R gate is:
212
+
213
+ ```text
214
+ bun test \
215
+ test/context-gateway \
216
+ test/repo-native-compact.test.ts \
217
+ test/repo-discovery.test.ts \
218
+ test/config.test.ts \
219
+ test/evals/extension-contracts.test.ts \
220
+ test/evals/harness.test.ts \
221
+ test/evals/recovery-corpus.test.ts \
222
+ test/evals/recovery-run-identity.test.ts \
223
+ test/evals/recovery-report.test.ts \
224
+ test/evals/recovery-validation.test.ts
225
+ ```
226
+
227
+ Result: **144 pass, 0 fail, 1011 assertions**; suite typecheck and
228
+ `git diff --check` pass. Root SDK pin remains `0.85.1`; generated schemas are
229
+ unchanged when checked through `node --import tsx` (the sandbox blocks the normal
230
+ `tsx` CLI IPC socket), and root `tsc --noEmit` passes.
231
+
232
+ R-F's separate host/UI gates remain green: root TUI/session **98/98**, ACP lazy
233
+ current-result **4/4** plus an additional **6/6** persisted-history/request-boundary
234
+ suite and typecheck, and Desktop transcript/client **28/28** with Desktop check at
235
+ zero errors (two pre-existing accessibility warnings).
@@ -137,7 +137,7 @@ The current extension registry covers all 19 modules:
137
137
  | `web-search` | web-search tests | deterministic only |
138
138
  | `dcp` | DCP prompt/pruning/state tests | existing prompt evals |
139
139
  | `prompt-commands` | eval extension contracts | deterministic only |
140
- | `skill-installer` | eval extension contracts | deterministic only |
140
+ | `resource-registry` | resource-registry integration + eval extension contracts | deterministic only |
141
141
  | `credential-firewall` | firewall tests | deterministic only |
142
142
  | `codex-reasoning-fix` | reasoning-fix tests | deterministic only |
143
143
 
@@ -2,6 +2,14 @@
2
2
 
3
3
  Status: implemented MVP contract (semantic search is intentionally deferred).
4
4
 
5
+ ## Type
6
+
7
+ As-is
8
+
9
+ ## Lifecycle
10
+
11
+ Active implemented contract.
12
+
5
13
  ## Goal
6
14
 
7
15
  Let an agent recover the task, recent instructions, file activity, and useful raw
@@ -28,19 +36,29 @@ active model context by compaction remains discoverable.
28
36
 
29
37
  A section starts at the first selected entry, a user message, a compaction, or a
30
38
  branch summary. Its stable ID is derived from the start entry ID. The overview
31
- reports bounded head and tail sections with entry ranges, counts, and compact
32
- role/tool/error/file statistics. Labels are previews, not inferred decisions.
39
+ reports bounded section pages with entry ranges, counts, and compact
40
+ role/tool/error/file statistics. When more sections exist it returns an opaque
41
+ `nextCursor`; continuing with that cursor resumes after the last delivered
42
+ section. Labels are previews, not inferred decisions.
33
43
 
34
44
  ### Reading and search
35
45
 
36
- `session_read_section` requires a section ID produced for the same scope. It
37
- renders message roles and text, tool calls and arguments, tool results,
46
+ `session_read_section` accepts either a section ID produced for the same scope or
47
+ one exact raw `entry_id`. Direct entry reads avoid scanning from the start of a
48
+ section and are useful when overview/search already identified the exact entry.
49
+ Without a continuation cursor, callers must pass exactly one of `section_id` or
50
+ `entry_id`.
51
+
52
+ The reader renders message roles/text, tool calls/arguments, tool results,
38
53
  compaction summaries, and branch summaries with per-entry and total output
39
- limits.
54
+ limits. Long entry bodies and multi-entry pages return an opaque `nextCursor`;
55
+ passing that cursor continues at the exact entry/body offset and must use the
56
+ same scope.
40
57
 
41
58
  `session_search` is case-insensitive by default and searches message text, tool
42
59
  arguments/results, custom-message content, and compaction or branch summaries.
43
- It returns entry and section IDs plus bounded snippets. Regex and semantic
60
+ It returns entry and section IDs plus bounded snippets. Search pages use an
61
+ opaque cursor bound to scope, query, and case-sensitivity. Regex and semantic
44
62
  search are out of scope for the MVP.
45
63
 
46
64
  ### Recovery context
@@ -60,6 +78,8 @@ tools are not guessed to be mutations.
60
78
 
61
79
  - Results use small defaults and hard caps for result count, entry body size,
62
80
  and total text size.
81
+ - Overview, read, and search pagination use opaque validated cursors; a cursor
82
+ from another scope/query or a stale section is rejected rather than guessed.
63
83
  - Empty or in-memory sessions return a normal explanatory result.
64
84
  - Unknown or partially shaped entries are ignored or rendered conservatively.
65
85
  - Concurrent sibling tool results might not yet be visible when recovery runs.
@@ -68,17 +88,23 @@ tools are not guessed to be mutations.
68
88
  - Parent-session metadata is reported when Pi exposes it; parent files are not
69
89
  traversed.
70
90
 
91
+ ## Related files
92
+
93
+ - `external/pi-tools-suite/src/session-recovery/index.ts`
94
+ - `external/pi-tools-suite/src/tool-descriptions.ts`
95
+ - `external/pi-tools-suite/test/session-recovery.test.ts`
96
+
71
97
  ## Verification
72
98
 
73
99
  Deterministic tests cover active versus all branches, raw pre-compaction search,
74
- stable section IDs, Unicode case-insensitive search, bounded output, empty
75
- sessions, current-call exclusion, recent errors, file carry-forward details,
76
- and conservative handling of unknown entries. Release verification runs the
77
- suite typecheck/tests/smoke gate, host `npm run check`, and then syncs the suite
78
- with `npm run sync:pi-tools-suite`.
100
+ stable section IDs, overview/search pagination, direct late-entry reads,
101
+ continued long bodies, Unicode case-insensitive search, bounded output, empty
102
+ sessions, DCP-control filtering, current-call exclusion, recent errors, file
103
+ carry-forward details, and conservative handling of unknown entries. Release
104
+ verification runs the suite typecheck/tests/smoke gate and host checks.
79
105
 
80
106
  ## Evidence
81
107
 
82
- Evidence is recorded by the implementation tests in
83
- `test/session-recovery.test.ts` and the verification commands reported with the
84
- change.
108
+ Evidence is recorded by
109
+ `external/pi-tools-suite/test/session-recovery.test.ts` and the implementation
110
+ in `external/pi-tools-suite/src/session-recovery/index.ts`.
@@ -0,0 +1,120 @@
1
+ # Sub-agent model pools
2
+
3
+ Sub-agents primarily reduce the cost of bounded work and keep intermediate
4
+ source, searches and logs out of the parent context. The parent owns planning,
5
+ integration, decisions and the final answer. Actual savings depend on worker
6
+ quality, retries and how much work the parent repeats; the configuration is
7
+ not a price oracle.
8
+
9
+ ## Six execution modes
10
+
11
+ - `research`: read-only evidence gathering, searches and focused review questions.
12
+ - `implement`: bounded code, documentation, test and frontend changes.
13
+ - `verify`: run checks and interpret logs, without fixing source or tests.
14
+ - `browser-qa`: isolated browser workflow with assertions and visual artifacts.
15
+ - `frontier-review`: independent post-implementation code review on a strong
16
+ model; hidden when the current parent model matches the role's availability
17
+ gate.
18
+ - `oracle`: a deliberate strong second opinion, not automatic worker escalation.
19
+
20
+ Task-specific discipline belongs in the brief or `promptAppend`. A new project
21
+ agent is warranted when it adds a durable contract, capabilities or resources,
22
+ not merely a professional title. `verify` has a behavioral no-edit contract;
23
+ shell access is not a read-only filesystem sandbox.
24
+
25
+ ## Agent priority, preset availability
26
+
27
+ Each Markdown profile owns its ordered `models` list. This is one candidate
28
+ chain for initial selection and subsequent quota fallbacks:
29
+
30
+ ```yaml
31
+ ---
32
+ description: Make bounded implementation changes.
33
+ models:
34
+ - zai/glm-5.3-flash
35
+ - openai-codex/gpt-5.6-terra
36
+ - openai-codex/gpt-5.6-luna
37
+ thinking: medium
38
+ ---
39
+ ```
40
+
41
+ A preset contains a set of available models, not a per-agent matrix. Project
42
+ pools live in `.pi/agents/presets.jsonc`:
43
+
44
+ ```jsonc
45
+ {
46
+ "gpt": {
47
+ "description": "Models available for this project",
48
+ "models": [
49
+ "openai-codex/gpt-5.6-luna",
50
+ "openai-codex/gpt-5.6-terra",
51
+ "openai-codex/gpt-5.6-sol"
52
+ ]
53
+ }
54
+ }
55
+ ```
56
+
57
+ The example agent selects Terra, not Luna: the agent's order wins. Sol is
58
+ available in the pool but absent from this worker's chain, so it cannot become
59
+ an automatic implementation fallback. The oracle and frontier-review can
60
+ declare Sol in their own chains. Model references in `models` must be exact
61
+ `provider/model` values, not wildcards.
62
+
63
+ The resolver intersects the agent chain with the selected pool. Runtime
64
+ selection then skips unregistered, unauthenticated or session-exhausted models.
65
+ Tasks with images and browser QA require confirmed image support. The first
66
+ eligible candidate runs; only the remaining eligible candidates are passed to
67
+ quota fallback. An empty intersection or unavailable chain rejects the batch
68
+ before any children or run state are created. Model selection makes no LLM
69
+ completion request; the optional role router is a separate operation.
70
+
71
+ Oracle prefers another provider when possible, but still respects the pool.
72
+ It never substitutes an ordinary cheap candidate merely to avoid a selection
73
+ error. A single-provider pool cannot promise cross-provider independence.
74
+
75
+ Explicit task `model`, CLI `--model`, and `FORCE_CURRENT_MODEL` remain deliberate
76
+ overrides: they bypass the pool and do not add automatic fallback candidates.
77
+ The parent should not use these to evade the configured budget. The pool is
78
+ a selection policy, not a security boundary against explicit overrides.
79
+
80
+ ## Selection and compatibility
81
+
82
+ Use `/subagent-preset <name>`, `AGENTS_PRESET=<name>` or
83
+ `/subagent-preset session <name>`. Clearing the preset uses agent priorities
84
+ without a pool filter. The shipped names remain compatible with saved choices:
85
+ `cheap` is the GLM pool, `gpt` the GPT pool, and `deep` the mixed pool. The last
86
+ name no longer means that ordinary workers should escalate to flagship models.
87
+ Bundled definitions live beside the built-in agents in
88
+ `src/async-subagents/agents/presets.jsonc`; a project file with the same preset
89
+ name overrides that pool.
90
+
91
+ Old role names are not implicit aliases. `quick`, `scan`, `review`, `deep`,
92
+ `docs`, `frontend`, and `tests` work only when explicitly defined as ordinary
93
+ custom/project types. This keeps the effective catalog and accepted names exact.
94
+
95
+ Agent frontmatter can gate whether a role exists for the current parent model:
96
+ `forParentModels` is an optional allow-list and `notForParentModels` is an
97
+ optional deny-list; deny wins when both match. These fields accept model
98
+ patterns such as `zai/*` and affect the parent catalog, explicit role
99
+ validation, and automatic routing. They do not change which model the child
100
+ runs on; `models` / legacy model selectors still own child model selection.
101
+
102
+ Legacy `model` plus `fallbackModels` and `modelByParent` still load when they are
103
+ declared in an agent Markdown file. New profile `models` replaces inherited
104
+ legacy selection fields. Empty `models` means no candidates, not permission to
105
+ inherit the parent model. Model-less project specialists must declare candidates
106
+ or receive an explicit model override.
107
+
108
+ The removed `asyncSubagents` section is no longer part of the public config
109
+ schema and is not read at runtime. Existing legacy files are left untouched but
110
+ have no effect. Migrate role definitions to `.pi/agents/*.md` and custom pools to
111
+ `.pi/agents/presets.jsonc`.
112
+
113
+ ## Compact handoff
114
+
115
+ Give workers a scope, acceptance criteria and the evidence needed to start.
116
+ Read compact results first and inspect raw artifacts selectively. One noisy
117
+ sequential investigation can justify a worker; a command whose exit status is
118
+ sufficient usually only needs a saved log, not another LLM. Independent review
119
+ of substantive code changes uses `frontier-review` when it is present in the
120
+ current parent catalog; use `research` for focused evidence/review questions.
@@ -33,6 +33,9 @@
33
33
  "test:evals:live": "PI_TOOLS_SUITE_EVALS_LIVE=1 bun test --concurrent --max-concurrency=4 test/evals/live-evals.test.ts",
34
34
  "evals": "npm run test:evals:contracts && bun test test/evals/live-evals.test.ts",
35
35
  "evals:report": "bun test/evals/run-evals.ts",
36
+ "evals:p01n": "bun test/evals/run-p01n-paired.ts",
37
+ "evals:context-gateway-observe": "bun test/evals/run-context-gateway-observe.ts",
38
+ "evals:context-gateway-recovery": "bun test/evals/run-context-gateway-recovery.ts",
36
39
  "bench:locate": "PI_LOCATE_BENCH_ITERATIONS=5 PI_LOCATE_BENCH_FAKE_IDX=0 PI_LOCATE_BENCH_MODEL=zai/glm-5-turbo PI_LOCATE_BENCH_MODES=direct-read-grep,ast-structural,repo-search-hybrid,repo-discovery,subagent-search,unrestricted-suite node test/fixtures/hard-to-find-project/benchmark/run-locate-benchmark.mjs",
37
40
  "bench:locate:analyze": "node test/fixtures/hard-to-find-project/benchmark/analyze-locate-benchmark.mjs",
38
41
  "test:locate-benchmark-e2e": "PI_LOCATE_BENCH_E2E=1 PI_LOCATE_BENCH_MODEL=zai/glm-5-turbo bun test test/locate-benchmark-e2e.test.ts",
@@ -2206,12 +2206,60 @@ foreach ($candidatePid in $descendants) {
2206
2206
  });
2207
2207
  return;
2208
2208
  }
2209
+
2210
+ // Prefer parent-based enumeration when available. macOS sandboxed hosts can
2211
+ // deny `ps` while still allowing pgrep(1); relying only on `ps` leaves a
2212
+ // detached Playwright/browser process alive after a timeout. Collect the
2213
+ // whole tree before killing anything so descendants cannot be re-parented
2214
+ // out of reach, then terminate deepest-first. A detached child is normally a
2215
+ // process-group leader, so also try its negative PID before the individual
2216
+ // PID; non-group-leaders simply yield ESRCH and fall through safely.
2217
+ const pgrepDescendants = [];
2218
+ const pgrepPendingParents = [process.pid];
2219
+ let pgrepAvailable = true;
2220
+ for (let index = 0; index < pgrepPendingParents.length; index += 1) {
2221
+ const parentPid = pgrepPendingParents[index];
2222
+ const result = spawnSync("pgrep", ["-P", String(parentPid)], {
2223
+ encoding: "utf8",
2224
+ timeout: 1000,
2225
+ maxBuffer: 256 * 1024,
2226
+ });
2227
+ if (result.error?.code === "ENOENT") {
2228
+ pgrepAvailable = false;
2229
+ break;
2230
+ }
2231
+ if (result.status !== 0 && result.status !== 1) {
2232
+ pgrepAvailable = false;
2233
+ break;
2234
+ }
2235
+ for (const line of (result.stdout ?? "").split("\n")) {
2236
+ const pid = Number(line.trim());
2237
+ if (!Number.isInteger(pid) || pid <= 0 || pgrepDescendants.includes(pid)) continue;
2238
+ pgrepDescendants.push(pid);
2239
+ pgrepPendingParents.push(pid);
2240
+ }
2241
+ }
2242
+ if (pgrepAvailable) {
2243
+ for (const pid of [...pgrepDescendants].reverse()) {
2244
+ try { process.kill(-pid, "SIGKILL"); } catch { /* not a group leader or already gone */ }
2245
+ try { process.kill(pid, "SIGKILL"); } catch { /* already gone */ }
2246
+ }
2247
+ return;
2248
+ }
2249
+
2209
2250
  const snapshot = spawnSync("ps", ["-axo", "pid=,ppid=,pgid="], {
2210
2251
  encoding: "utf8",
2211
2252
  timeout: 1000,
2212
2253
  maxBuffer: 2 * 1024 * 1024,
2213
2254
  });
2214
- if (snapshot.status !== 0 || !snapshot.stdout) return;
2255
+ if (snapshot.status !== 0 || !snapshot.stdout) {
2256
+ // Sandboxed macOS hosts can deny `ps` process enumeration while still
2257
+ // allowing parent-scoped `pgrep -P`. Fall back to a bounded recursive
2258
+ // parent walk so a detached browser process is not left behind merely
2259
+ // because the broader process snapshot is unavailable.
2260
+ terminateRunnerDescendantsWithPgrep(process.pid);
2261
+ return;
2262
+ }
2215
2263
  const processes = snapshot.stdout
2216
2264
  .split("\n")
2217
2265
  .map((line) => line.trim().split(/\s+/).map(Number))
@@ -2241,6 +2289,39 @@ foreach ($candidatePid in $descendants) {
2241
2289
  }
2242
2290
  }
2243
2291
 
2292
+ function terminateRunnerDescendantsWithPgrep(rootPid) {
2293
+ const descendants = [];
2294
+ const seen = new Set([rootPid]);
2295
+ const pendingParents = [rootPid];
2296
+ for (let index = 0; index < pendingParents.length && descendants.length < 4096; index += 1) {
2297
+ const parentPid = pendingParents[index];
2298
+ const result = spawnSync("pgrep", ["-P", String(parentPid)], {
2299
+ encoding: "utf8",
2300
+ timeout: 500,
2301
+ maxBuffer: 256 * 1024,
2302
+ });
2303
+ // pgrep exits 1 when there are no matching children. Any other failure is
2304
+ // fail-closed for this fallback; callers still terminate the runner itself.
2305
+ if (result.status !== 0 && result.status !== 1) continue;
2306
+ for (const line of (result.stdout ?? "").split("\n")) {
2307
+ const pid = Number.parseInt(line.trim(), 10);
2308
+ if (!Number.isInteger(pid) || pid <= 0 || seen.has(pid)) continue;
2309
+ seen.add(pid);
2310
+ descendants.push(pid);
2311
+ pendingParents.push(pid);
2312
+ }
2313
+ }
2314
+
2315
+ // Kill leaves before their parents so descendants cannot be reparented
2316
+ // before we have sent them a signal. Detached children are killed by PID;
2317
+ // unlike the primary `ps` path this fallback does not need their PGID.
2318
+ for (let index = descendants.length - 1; index >= 0; index -= 1) {
2319
+ try {
2320
+ process.kill(descendants[index], "SIGKILL");
2321
+ } catch { /* already gone */ }
2322
+ }
2323
+ }
2324
+
2244
2325
  function sanitizeTraceArchiveInWorker(tracePath, secrets, deadline) {
2245
2326
  return new Promise((resolve, reject) => {
2246
2327
  const worker = new Worker(new URL(import.meta.url), {