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
@@ -7,7 +7,7 @@ This package keeps shared Pi tools as ordinary source folders under `src/` and r
7
7
  - `src/coding-discipline` — injects a deduplicated silent-mode and quality-discipline block at the very top of the main-session per-turn system prompt for GLM main-session models only (`isGlmModel`) immediately before the LLM request; text-only GLM models get the `lookup` bridge while vision-capable `zai/glm-5.3-flash` inspects images directly; non-GLM models are left untouched; disabled for async sub-agents
8
8
  - `src/credential-firewall` — opt-in secret firewall for high-confidence outbound/session credential redaction; disabled by default
9
9
  - `src/ast-grep` — `ast_grep` / `ast_apply`
10
- - `src/async-subagents` — `subagents` tool and sub-agent slash commands, including oh-my-openagent-style `/ultrawork` (`/ulw`) and `/hyperplan` orchestration prompts, plus config-defined sub-agent model/thinking/args presets selected via `/subagent-preset` from `asyncSubagents` in `~/.config/pi/pi-tools-suite.jsonc`; includes the `frontend` profile for Gemini-friendly UI/UX and visual frontend work and the `oracle` profile for cross-provider second opinions; enforces a 30-minute per-agent execution timeout, project-wide `maxConcurrent` queueing, optional retry/backoff, and `result.json` structured metadata/chaining fields next to raw `result.md`; stores project-local run files and a registry under `.pi/subagents/` so result/status collection can recover after compaction or reload while the main session remains alive
10
+ - `src/async-subagents` — `subagents` tool and sub-agent slash commands, including oh-my-openagent-style `/ultrawork` (`/ulw`) and `/hyperplan` orchestration prompts; agent roles are Markdown files under `src/async-subagents/agents/*.md` plus project `.pi/agents/*.md`, while `/subagent-preset` selects model-pool presets from the bundled/project `agents/presets.jsonc`; includes the `oracle` profile for strong second opinions; enforces a 30-minute per-agent execution timeout, project-wide concurrency queueing, optional per-agent retry/backoff, and `result.json` structured metadata/chaining fields next to raw `result.md`; stores project-local run files and a registry under `.pi/subagents/` so result/status collection can recover after compaction or reload while the main session remains alive
11
11
  - `src/lsp` — shared LSP diagnostics hook/library that enriches mutating tool results with diagnostics and shuts down language servers on session shutdown
12
12
  - `src/comment-checker` — AI-slop comment guard that listens to the `tool_result` event for `write` / `edit` / `apply_patch` mutations, extracts net-new code comment lines, classifies them (filler phrasing, restating code, decorative separators, generic paraphrasing, or — under aggressive strictness — any non-valuable comment), and appends a short nudge to the tool result so the agent removes unnecessary comments on its next turn; TODO/FIXME, license headers, docstrings, pragmas, linter directives, shebangs, and decorators are never flagged; language-agnostic across `//` / `/* */` / `#` / `--` / `<!-- -->` / triple-quote comment styles; per-session deduplication (at most one nudge per 30 s) prevents fix/remark loops; configured via the `commentChecker` section (`enabled`, `strictness`: `conservative` | `balanced` | `aggressive`, default `balanced`) or `PI_COMMENT_CHECKER_ENABLED` / `PI_COMMENT_CHECKER_STRICTNESS`
13
13
  - `src/session-name` — `session_name` tool for reading or setting the current session title directly from tool calls, without relying on slash-command parsing
@@ -21,11 +21,11 @@ This package keeps shared Pi tools as ordinary source folders under `src/` and r
21
21
  - `src/web-search` — `web_search` and `web_fetch` tools migrated from `@ollama/pi-web-search`; uses local Ollama by default or the official Ollama cloud API when an API key is configured, supports Tavily Search/Extract fallback, provides `/web-credentials` for secure user-level key storage, honors `OLLAMA_HOST`, supports request timeouts via `timeout_ms` / `PI_WEB_SEARCH_TIMEOUT_MS`, and reports provider-specific errors
22
22
  - `src/dcp` — headless Dynamic Context Pruning ported from `opencode-dynamic-context-pruning` for the Pi SDK: explicit `compress` tool with range and message modes, `/dcp` commands (context, stats, sweep, manual, decompress, recompress, compress), same-call overlap validation, recoverable compressed-block rollups, grouped message-mode skip diagnostics, stable raw-message anchors when available, protected user/tool preservation, deduplication, error purging, and context nudges; visualization is left to `compress` tool responses and the renderer-owned context-percent click dialog
23
23
  - `src/prompt-commands` — user slash-command builder: `/prompt-commands` opens a CRUD menu for saved prompt-backed slash commands, stores them under `promptCommands` in `~/.config/pi/pi-tools-suite.jsonc`, reloads after edits, and runs each saved prompt as a normal user message
24
- - `src/skill-installer` — `/install-skill [name]` installs a personal skill folder from `~/.agents/local_skills` into the current project's `.pi/skills/` so it activates as a project-local skill, then automatically runs `/reload` so the new skill is picked up without a manual step; `/export-skill [name]` does the reverse, copying a project-local skill back to `~/.agents/local_skills/` for reuse in other projects (no reload, since the library lives outside the project); with no argument either command shows an interactive menu of available skills (folders containing `SKILL.md`), and the `<name>` form installs/exports it directly (headless-safe); existing destinations prompt to overwrite in the UI and are refused in headless mode; `.DS_Store` files are skipped
24
+ - `src/resource-registry` — `/registry` manages one private Git registry with global reusable `skills/` and `agents/` plus project-scoped `projects/<project-key>/tasks.jsonc`, `projects/<project-key>/plans/`, and `projects/<project-key>/TODO.md`; skills install into `.pi/skills/<name>/`, agents into `.pi/agents/<name>.md`, while `push tasks|plans|todo|project` and `pull tasks|plans|todo|project` synchronize `.pi/tasks.jsonc`, `.pi/plans/`, and `.pi/TODO.md` only for the current project; the project key is normally derived from Git `origin` (SSH and HTTPS forms normalize to the same key) and can be overridden per project with `/registry project-key <key>` in `.pi/pi-tools-suite.jsonc`; `status` fetches and groups skills, agents, tasks, plans, and TODO by state (up to date, updates, conflicts, local-only, remote-only, and so on) using `.pi/registry.json` provenance; reusable `install`, `update`, `push`, remote-only `remove`, and local-only `uninstall` support TUI flows and bulk `all` forms, `delete`/`rm` alias remote `remove`, `remove-local`/`local-remove` alias `uninstall`, destructive bulk operations require interactive confirmation, and every successful skill/agent mutation reloads resources once; `/registry configure <git-url> [branch]` stores the registry remote in the user config; Git authentication is delegated to the user's normal Git/SSH credential setup and the local clone is only a disposable cache
25
25
 
26
26
  `index.ts` is intentionally only a thin auto-discovery shim that re-exports `src/index.ts`. There is no `pi.extensions` manifest here, so local Pi auto-discovery loads the suite once via `~/.pi/agent/extensions/pi-tools-suite/index.ts` and does not double-register tools.
27
27
 
28
- Registration order is preserved in `src/index.ts`: coding-discipline, ast-grep, async-subagents, lsp, comment-checker, session-name, session-recovery, repo-discovery command/tool gate, antigravity-auth provider, OpenCode import, todo, model-tools, usage, web-search, dcp, prompt-commands, skill-installer, credential-firewall, then codex-reasoning-fix. Tool metadata and active model-specific tool sets have two modes: standard and repo-aware. When `.indexer-cli` enables `repo_*`, those tools stay active ahead of overlapping lower-level aliases so the indexed discovery surface has priority.
28
+ Registration order is preserved in `src/index.ts`: coding-discipline, ast-grep, async-subagents, lsp, comment-checker, session-name, session-recovery, repo-discovery command/tool gate, antigravity-auth provider, OpenCode import, todo, model-tools, usage, web-search, dcp, prompt-commands, resource-registry, credential-firewall, then codex-reasoning-fix. Tool metadata and active model-specific tool sets have two modes: standard and repo-aware. When `.indexer-cli` enables `repo_*`, those tools stay active ahead of overlapping lower-level aliases so the indexed discovery surface has priority.
29
29
 
30
30
  ## Session recovery
31
31
 
@@ -100,7 +100,13 @@ DCP settings are stored only under `dcp` in the user shared config file `~/.conf
100
100
  "nudgeFrequency": 1,
101
101
  "iterationNudgeThreshold": 6,
102
102
  "nudgeForce": "strong",
103
- "protectedTools": ["compress", "write", "edit", "subagents"]
103
+ "protectedTools": ["compress", "write", "edit", "subagents"],
104
+ "autoCompress": {
105
+ "enabled": false,
106
+ "patience": 2,
107
+ "summarizerModel": [],
108
+ "timeoutMs": 20000
109
+ }
104
110
  },
105
111
  "strategies": {
106
112
  "emergencyCurrentTurnPruning": {
@@ -170,7 +176,11 @@ DCP settings are stored only under `dcp` in the user shared config file `~/.conf
170
176
 
171
177
  `minContextPercent` / `maxContextPercent` accept legacy fractions (`0.25`), percent strings (`"25%"`), or absolute token counts when Pi knows the current model context window. `minContextLimit` / `maxContextLimit` and `modelMinContextLimits` / `modelMaxContextLimits` are explicit absolute-or-percent aliases. `modelOverrides` and the `modelMin*` / `modelMax*` maps support exact model keys plus `*` / `?` wildcard patterns; matching is applied from generic to specific so exact bare-model matches override bare wildcards, and exact `provider/model` matches override provider wildcards. Array fields are union-merged, so model-specific `protectedTools` extend the defaults instead of replacing them. If `compress.protectUserMessages` is enabled, range compression appends selected user messages verbatim instead of rejecting the range; individual message compression still skips protected raw user messages. Protected tool outputs are copied into summaries for tools protected by name or `protectedFilePatterns`; protected `subagents` result reads also try to include the saved `result.md` artifact when available.
172
178
 
173
- `strategies.emergencyCurrentTurnPruning` is the default-enabled lossy safety floor for a single unfinished turn that has no normal compression candidate. DCP first emits emergency reminders and offers only safe old same-turn tool-result candidates. After `patience` ignored reminders, or at the model-independent `hardContextPercent`, it replaces eligible oldest result bodies until the estimated provider context reaches `targetContextPercent` or a margin below the model emergency threshold. User messages, configured/protected data, the newest `keepRecentToolPairs`, and results not present in an accepted provider request are never selected. The raw session transcript is unchanged. Setting `enabled` to `false` disables same-turn candidates and lossy pruning, but keeps the non-destructive emergency reminder.
179
+ `compress.autoCompress.enabled` is `false` by default. When explicitly enabled, its `patience` counts completed correlated main-provider opportunities, not repeated context transforms; `summarizerModel: []` uses the bounded extractive fallback without a model call, while configured models share the single `timeoutMs` summarizer deadline. If that deadline expires, DCP still has a bounded finalization grace to commit the extractive fallback. Auto commit is accepted only when the full projected replacement has positive gain and meets the current budget-recovery target.
180
+
181
+ `strategies.emergencyCurrentTurnPruning` is the default-enabled lossy safety floor for a single unfinished turn that has no normal compression candidate. DCP first emits emergency reminders and offers only safe old same-turn tool-result candidates. After `patience` completed ignored opportunities, or at the model-independent `hardContextPercent`, it replaces eligible oldest result bodies until the estimated provider context reaches `targetContextPercent` or a margin below the model emergency threshold. User messages, configured/protected data, the newest `keepRecentToolPairs`, and results without **completed** provider evidence are never selected. HTTP 2xx alone is not evidence; DCP promotes eligibility only after an unambiguously correlated successful finalized assistant response, and ambiguous retries/interleaving fail closed. The raw session transcript is unchanged. Setting `enabled` to `false` disables same-turn candidates and lossy pruning, but keeps the non-destructive emergency reminder.
182
+
183
+ DCP sidecars are session-private versioned generation envelopes under `<sessionDir>/dcp-state/`. Saves use private atomic files, retain a last-valid `.prev` generation, validate payload/block-graph integrity on load, quarantine corrupt primaries, and use a cross-process exclusive lock rather than silent last-writer-wins. Live paused sessions are not deleted merely for age. Protected subagent artifacts are optional bounded recovery input: reads are async, rooted at the session cwd, reject symlink escapes and oversized files, and never silently truncate a required protected artifact.
174
184
 
175
185
  Set `dcp.debug: true` to write a JSONL debug log of DCP context/prune/compress events to `~/.pi/agent/dcp-debug.jsonl` (override the path with `PI_DCP_DEBUG_LOG`, or enable without config via `PI_DCP_DEBUG=1`); off by default. The log is size-limited and rotated: once it reaches `dcp.debugLog.maxBytes` (default `5242880` = 5 MB) it is renamed to `.1`, older backups shift down (`.1`→`.2`, …) and the oldest beyond `dcp.debugLog.maxBackups` (default `3`, minimum `1`) is dropped; override either with `PI_DCP_DEBUG_MAX_BYTES` / `PI_DCP_DEBUG_MAX_BACKUPS`.
176
186
 
@@ -427,21 +437,120 @@ Notes:
427
437
 
428
438
  ## Async sub-agents
429
439
 
430
- Sub-agent model routing normally follows task overrides, subagent type config, then `ASYNC_SUBAGENTS_MODEL` / `PI_SUBAGENTS_MODEL` fallbacks. Set `ASYNC_SUBAGENTS_FORCE_CURRENT_MODEL=1` (or `PI_SUBAGENTS_FORCE_CURRENT_MODEL=1`) to ignore task/config/env model choices and launch every sub-agent with the current parent session model. When this flag is enabled, any `--model` entries in sub-agent extra args are stripped so they cannot override the current model.
440
+ Model selection uses the ordered candidates from each agent's Markdown file,
441
+ filtered by the selected preset's available models and runtime capabilities.
442
+ Explicit task/CLI model overrides bypass the pool. Setting
443
+ `ASYNC_SUBAGENTS_FORCE_CURRENT_MODEL=1` (or
444
+ `PI_SUBAGENTS_FORCE_CURRENT_MODEL=1`) deliberately selects the parent model and
445
+ strips conflicting model arguments; this is not the economical default.
446
+
447
+ The five built-in modes are `research` (read-only evidence and independent
448
+ review), `implement` (bounded code, docs, tests, or UI changes), `verify`
449
+ (run checks and diagnose logs without fixing files), `browser-qa` (trusted
450
+ browser workflow), and `oracle` (deliberate strong second opinion).
451
+ Ordinary workers use economical model candidates; no built-in parent-tier
452
+ rule promotes them to a flagship. Oracle is the exception, not an automatic
453
+ retry for difficult work. Task-specific discipline belongs in the brief.
454
+
455
+ Delegate when a suitable lower-cost worker can handle bounded work or noisy
456
+ intermediate evidence should stay outside the parent context. One sequential
457
+ task can qualify. Keep decisions and integration in the parent; read compact
458
+ results and verify selectively rather than repeating the worker's investigation.
459
+ Do trivial reads/edits directly. Redirect a noisy command to a log without an
460
+ extra LLM when no interpretation is needed. `verify`'s no-edit instruction is
461
+ a behavioral contract, not a read-only filesystem sandbox for its shell.
462
+
463
+ Run `/ultrawork` or `/ulw` for orchestration, `/hyperplan` to pressure-test a
464
+ plan, or set `ULTRAWORK=1` to apply the orchestration prompt to normal inputs.
465
+ `ULTRAWORK_AUTO=1` classifies only the first normal input on non-GPT parents;
466
+ GPT-like parents skip that automatic transform, not ordinary delegation.
467
+
468
+ See [Model pools and migration](docs/subagent-model-pools.md) for the selection
469
+ contract, configuration examples, override rules and legacy compatibility.
470
+
471
+ ### Parent-first role selection
472
+
473
+ The parent normally selects an explicit `subagentType` from the effective
474
+ system-prompt catalog, preferring a matching project-local specialist. Valid
475
+ explicit types bypass the LLM router entirely; presets, model selection, tools,
476
+ skills, and role instructions are still applied by the normal config resolver.
477
+ Model/thinking overrides are not substitutes for selecting a role.
478
+
479
+ The router remains enabled as a fallback for omitted types: use it when the role
480
+ is unclear or the user explicitly requests automatic routing. Only omitted
481
+ tasks are classified, in one batch; the parent's explicit choices are preserved.
482
+ Real-browser QA still requires explicit `subagentType: "browser-qa"`.
483
+
484
+ Unknown explicit types and failed/incomplete automatic routing reject the
485
+ **entire spawn batch before run state or child processes are created**. The tool
486
+ returns an error with affected task IDs and available types; the parent should
487
+ correct the roles and resubmit the whole batch. Provider error responses are
488
+ failures too, not successful routes. Configured fallback router models may be
489
+ tried, but missing routes are never silently replaced with `quick`/`defaultType`.
490
+
491
+ With `routing.enabled: false`, every spawn task must supply a valid explicit
492
+ type. `defaultType` remains a preference for genuinely ambiguous LLM choices
493
+ and a legacy config-resolver default, not a spawn error fallback. Existing
494
+ callers relying on an implicit default must now choose a type explicitly.
495
+
496
+ ### Project-local agents (`.pi/agents/*.md`)
497
+
498
+ A project can ship sub-agent roles as individual Markdown files in
499
+ `<project>/.pi/agents/`. The first such directory found walking up from the
500
+ session cwd is used; each top-level `*.md` file becomes a `subagentType` named
501
+ after the file. Parent and router see the short `description`; only the child
502
+ receives the Markdown body. A project's ordered `models` are filtered through
503
+ the same active preset pool as built-in agents.
504
+
505
+ ```markdown
506
+ ---
507
+ description: Use for reviewing this repo's diff — knows the house rules.
508
+ icon: eye
509
+ models:
510
+ - zai/glm-5-turbo
511
+ - openai-codex/gpt-5.6-luna
512
+ thinking: low
513
+ tools: read, grep
514
+ retry:
515
+ maxRetries: 1
516
+ backoffMs: 2000
517
+ ---
518
+
519
+ You are this project's staff reviewer. Apply the repo rules from
520
+ AGENTS.md before approving anything; cite file paths first.
521
+ ```
431
522
 
432
- For an oh-my-openagent-style workflow, run `/ultrawork` or `/ulw` to ask the parent agent to split broad work into configured async-subagents roles (`quick`, `scan`, `research`, `docs`, `frontend`, `browser-qa`, `implement`, `tests`, `review`, `deep`, `oracle`). Set `ULTRAWORK=1` before launching Pi to apply that compact routing prompt to normal non-slash user inputs automatically. Set `ULTRAWORK_AUTO=1` to ask the lightweight router model to classify only the first normal user input on non-GPT parent models: clear broad/parallel work is transformed into ultrawork, vague potentially-complex work gets a soft delegation hint, and narrow work is left unchanged. GPT-like parent models skip only this automatic transform; they can still use `/ultrawork` and `subagents` normally. `frontend` is for UI/UX, styling, layout, responsive behavior, and visual component polish; `browser-qa` reproduces browser bugs and proves fixes with deterministic assertions plus screenshot/video/trace evidence; `review` covers security/performance/audit tracks; `implement` covers refactors; `deep` covers debugging/root-cause; `oracle` is for sparse cross-provider second opinions on high-stakes uncertainty. Run `/hyperplan` to pressure-test a plan before implementation.
523
+ - Frontmatter keys: `name` (must match the filename), `description`, `icon`, `models`, `thinking`, `tools`, `isolatedSkills`, `extraArgs`, `promptAppend`, `promptOverride`, `retry`, `maxResultBytes`, `timeoutMs`. Legacy `model`, `fallbackModels`, and `modelByParent` still load. Unknown keys are rejected with an error naming the file.
524
+ - Array fields accept block lists (`- item`), inline arrays (`[a, b]`), or comma-separated strings (`tools: read, grep, bash`). The frontmatter YAML subset is intentionally small: scalars, quoted strings, numbers, comments, lists, and nested maps for `modelByParent`/`retry`. Tabs, block scalars (`|`/`>`), anchors/aliases, and flow maps are hard errors naming file and line.
525
+ - The markdown body becomes `promptAppend`: it is appended after the standard generated prompt (parent objective + task + output format), so the agent still receives its task in the usual structure. Use frontmatter `promptOverride` for full prompt replacement.
526
+ - Precedence: bundled Markdown defines the built-ins, then the nearest project `.pi/agents/*.md` file overrides the same-named built-in field-by-field. Markdown is the only source of agent role/profile definitions. The removed `asyncSubagents` section and old standalone config-path variables are not read.
527
+ - Files without frontmatter are skipped (a `README.md` there is fine). Definition loading is uncached: edits apply on the next config read/spawn without a restart, and the effective system-prompt catalog is rebuilt at parent-agent start.
528
+ - Bundled roles use the same format internally under `src/async-subagents/agents/*.md`; built-in and project-local profiles therefore share one parser and normalization path instead of maintaining a second role-description schema in TypeScript.
529
+ - `icon` names an agent glyph for UIs that render sub-agent widgets (pix TUI panel, Pix Desktop subagents panel): `agent` (neutral default), `search`, `code`, `flask`, `globe`, `sparkles`, `brain`, `wrench`, `terminal`, `bug`, `book`, `eye`, `zap`, `rocket`. The value is passed through opaquely; unknown names render as the neutral agent icon, and status stays color-coded next to it.
433
530
 
434
531
  ### Private browser QA and project auth
435
532
 
436
533
  The built-in `browser-qa` role runs on `zai/glm-5.3-flash`, with
437
- `openai-codex/gpt-5.6-luna` as its fallback. Its browser
438
- workflow is an explicit private skill under `src/async-subagents/private-skills/`,
439
- outside normal Pi skill discovery. The role's first-class `isolatedSkills` setting launches the child with
440
- `--no-skills` plus one self-contained private workflow. It bundles the relevant
441
- scenario-design, locator, waiting, assertion, evidence, and cleanup guidance next
442
- to its trusted runner, so browser QA does not depend on a separately installed
443
- skill or CLI. The private workflow remains mandatory when configuration appends
444
- other isolated skills; parent and ordinary sub-agent sessions do not discover it.
534
+ `openai-codex/gpt-5.6-luna` as its fallback. Its complete workflow and detailed
535
+ scenario-design guidance live in the Markdown body of
536
+ `src/async-subagents/agents/browser-qa.md`. The normal profile loader appends
537
+ that body to the QA child's task prompt; the parent and LLM router receive only
538
+ the short `description`. There is no additional QA skill to discover or read.
539
+
540
+ Executable resources live under `src/async-subagents/agents/browser-qa/`.
541
+ The launcher supplies the installed runner's absolute path in
542
+ `PI_BROWSER_QA_RUNNER`; the child invokes `node "$PI_BROWSER_QA_RUNNER"` from
543
+ the delegated project's cwd. This non-secret path is set only for QA children.
544
+ QA always launches with `--no-skills`, even when `isolatedSkills` is empty,
545
+ and skill flags in `extraArgs` cannot bypass that isolation. Explicitly
546
+ configured `isolatedSkills` remain supported as optional additions; no built-in
547
+ QA `--skill` is injected. Other roles retain their normal discovery behavior.
548
+
549
+ Model/thinking/tool-only overrides in a project `browser-qa.md` inherit the
550
+ bundled Markdown workflow. A project Markdown body replaces the inherited
551
+ `promptAppend` under the usual field-level merge rules; custom QA instructions must preserve the runner-only,
552
+ credential, target, and evidence contracts. Runner-enforced isolation and
553
+ credential handling remain in code, not in the prompt.
445
554
 
446
555
  Public browser QA does not require an auth profile or `.pi/qa_auth.jsonc`: run it
447
556
  with an explicit base URL, whose exact origin becomes the fail-closed allowlist.
@@ -498,8 +607,8 @@ creating a template. Only an explicit authenticated request may create the
498
607
  private template. Missing, rejected, or expired selected auth returns
499
608
  `QA_AUTH_UPDATE_REQUIRED`, naming only the profile/file/reason needed for the
500
609
  parent to ask the user for an update and rerun. See
501
- `src/async-subagents/private-skills/browser-qa/references/qa-auth.example.jsonc`
502
- for complete profile shapes and `references/qa-flow.example.jsonc` beside it for
610
+ `src/async-subagents/agents/browser-qa/examples/qa-auth.example.jsonc`
611
+ for complete profile shapes and `examples/qa-flow.example.jsonc` beside it for
503
612
  the declarative, non-executable QA action/assertion format.
504
613
 
505
614
  Browser QA videos automatically visualize pointer interactions. Clicks and
@@ -512,70 +621,81 @@ so screenshots and assertions remain state-focused.
512
621
 
513
622
  Async-subagents also injects a lightweight oh-my-openagent-style system-prompt strategy by model: non-GPT parents get `parallel-first`, an orchestration-first hint that favors ultrawork/subagents for broad work, while GPT-like parents get `deep-work`, a direct deep-worker hint that uses subagents only when clearly useful. Explicit custom system prompts (`--system-prompt`, `SYSTEM.md`, custom templates) are respected and skip this injection by default. Disable it with `PI_AGENT_STRATEGY=off`; force a strategy with `PI_AGENT_STRATEGY=parallel-first` or `PI_AGENT_STRATEGY=deep-work`; set `PI_AGENT_STRATEGY_WITH_CUSTOM_PROMPT=1` to append it even when a custom prompt is present.
514
623
 
515
- For blind-model screenshot/image inspection, use the main-session `coding-discipline` lookup tool; the bundled default uses vision-capable `zai/glm-5.3-flash`. Async-subagents still supports `imagePaths` on tasks when a broader delegated track genuinely needs images, but it no longer ships a dedicated `vision` role. Dynamic provider capabilities can be missing or stale after switching models, so blind parent models can still be configured explicitly with case-insensitive `*` masks under `asyncSubagents.vision.blindModelPatterns` in `~/.config/pi/pi-tools-suite.jsonc`; do not include `zai/glm-5.3-flash` because it accepts image input. This keeps guidance honest, not a sub-agent role.
516
-
517
- When a task omits `subagentType`, async-subagents asks a lightweight router model to choose one configured type for each task from the task text/scope and the `types.<name>.description` metadata. Explicit task `subagentType` still wins. Keep type descriptions short, literal, and distinct because they are inserted into the router prompt for a small model. Router settings live under `asyncSubagents.routing` (`enabled`, `model`, `maxTaskChars`, `maxTokens`, `maxRetries`, `timeoutMs`, `debug`); the default router model is `zai/glm-4.5-air`. If the router is disabled, unavailable, aborted, or returns invalid JSON, omitted types fall back to `defaultType`.
518
-
519
- Define optional `presets` under `asyncSubagents` in `~/.config/pi/pi-tools-suite.jsonc`, `$PI_CONFIG_DIR/pi-tools-suite.jsonc`, or project `.pi/pi-tools-suite.jsonc`, then use `/subagent-preset` or `/subagent-preset-config` to pick one persistent active preset for future spawns across all sessions. Set `AGENTS_PRESET=<name>` before launching Pi to override the saved preset for only the current process/session without changing the saved selection. If Pi is already running, use `/subagent-preset session <name>` for the same process-only override, and `/subagent-preset session-clear` to remove that runtime override. The TUI only selects presets already present in config; it does not edit JSON. If no `asyncSubagents` section exists, run `/subagent-preset init` to insert the bundled sample from `src/async-subagents/async-subagents.sample.jsonc` into the shared config (or to copy a standalone override file when `ASYNC_SUBAGENTS_CONFIG` / `PI_SUBAGENTS_CONFIG` is set). Existing config sections/files are never overwritten. Presets select an agent/model configuration: they can provide global fallback `model`/`thinking`/`extraArgs` and per-role overrides under `asyncSubagents.presets.<name>.types.<subagentType>`. They can also provide ordered `fallbackModels` globally or per-role; when a sub-agent fails with quota/rate-limit errors such as 429, async-subagents immediately tries the next fallback model and remembers the exhausted provider for the current Pi process/session, so later spawns skip that provider until Pi exits. This is intended for provider-level fallback chains such as `antigravity/* → openai-codex/* → zai/*` or `openai-codex/* → zai/*`; omit fallbacks for effectively unlimited providers. Antigravity account rotation has priority over preset fallback: async-subagents only falls back after Antigravity reports that all configured accounts are exhausted for that model. Explicit task model overrides and force-current-model disable preset fallback for that task. The active preset name is stored separately in `~/.pi/agent/subagent-preset-selection.json`.
520
-
521
- Example shared async-subagents config section:
624
+ For blind-model screenshot/image inspection, use the main-session `coding-discipline` lookup tool; the bundled default uses vision-capable `zai/glm-5.3-flash`. Async-subagents still supports `imagePaths` on tasks when a broader delegated track genuinely needs images, but it no longer ships a dedicated `vision` role. Provider image metadata is supplemented by an internal compatibility list for known blind models so the parent does not falsely claim visual access; this is runtime capability policy, not agent configuration.
625
+
626
+ When `subagentType` is omitted, the lightweight role router classifies the task
627
+ using the descriptions. Explicit types bypass it. Unknown types or failed
628
+ routing reject the batch, never substitute `defaultType`. Choosing a worker
629
+ model from its candidate list does not involve an LLM call.
630
+
631
+ ### Presets are available-model pools
632
+
633
+ Each agent declares an ordered `models` list in Markdown. A preset declares
634
+ which model references may be used, not another role/model/thinking matrix.
635
+ Selection preserves agent order, intersects it with `preset.models`, checks
636
+ runtime registration/auth availability, and takes the first usable candidate.
637
+ Pool order does not change preference and pool-only models are never appended.
638
+ Without a preset, the full agent list is eligible. Candidate order expresses
639
+ the configured budget preference; runtime does not infer current API prices.
640
+
641
+ Image-bearing tasks and `browser-qa` require confirmed image support; configured
642
+ blind-model masks override runtime image metadata. Remaining eligible models
643
+ form the quota fallback chain, so neither quota history nor image fallback can
644
+ escape the pool. Antigravity account rotation still happens before provider
645
+ fallback. No match, no usable model, or an explicitly empty list rejects the
646
+ whole batch before run directories or child processes are created. A new custom
647
+ agent must supply candidates instead of silently inheriting the parent model.
648
+
649
+ Oracle uses its separate strong-model list and prefers another provider when
650
+ available, but also respects the pool. A same-provider choice is allowed when
651
+ the pool offers no alternative; cross-provider independence is not guaranteed.
652
+ Explicit task/CLI model overrides and `FORCE_CURRENT_MODEL` remain deliberate
653
+ escape hatches and disable automatic model fallback for that task. They do not
654
+ bypass the image-capability check.
655
+
656
+ Bundled pools live in `src/async-subagents/agents/presets.jsonc`. Add or override
657
+ project pools in the nearest `.pi/agents/presets.jsonc`. Select a saved pool
658
+ with `/subagent-preset`; use `AGENTS_PRESET=<name>` or
659
+ `/subagent-preset session <name>` for a process-only override and
660
+ `/subagent-preset session-clear` to remove it. The saved selection lives in
661
+ `~/.pi/agent/subagent-preset-selection.json`. `/subagent-preset path` shows the
662
+ bundled and project preset paths. The shipped pools are `cheap` (GLM), `gpt`,
663
+ and `deep` (the retained legacy name for the mixed pool, not worker escalation).
664
+ Agent descriptions, instructions, model order, thinking, tools, retry, and
665
+ timeouts remain in agent Markdown; selecting a pool never changes them.
666
+
667
+ Example project `.pi/agents/presets.jsonc`:
522
668
 
523
669
  ```jsonc
524
670
  {
525
- "asyncSubagents": {
526
- "defaultType": "quick",
527
- "routing": {
528
- "enabled": true,
529
- "model": "zai/glm-4.5-air",
530
- "timeoutMs": 12000
531
- },
532
- "presets": {
533
- "cheap": {
534
- "description": "Use GLM by role, including GLM-5.3 Flash for multimodal work.",
535
- "types": {
536
- "quick": { "model": "zai/glm-5.3", "thinking": "off" },
537
- "frontend": { "model": "zai/glm-5.3-flash", "thinking": "medium" },
538
- "browser-qa": { "model": "zai/glm-5.3-flash", "fallbackModels": ["openai-codex/gpt-5.6-luna"], "thinking": "low" },
539
- "review": { "model": "zai/glm-5.3", "thinking": "high" }
540
- }
541
- }
542
- },
543
- "types": {
544
- "frontend": {
545
- "description": "Use for frontend UI/UX visual work: styling, layout, typography, animation, responsive states, component polish, accessibility. Avoid backend/business logic unless needed for UI behavior.",
546
- "thinking": "medium"
547
- },
548
- "review": {
549
- "description": "Use for review/audit of existing code or changes: correctness, security, performance, maintainability, API risks, quality. Do not implement new code.",
550
- "thinking": "high"
551
- }
552
- }
671
+ "cheap": {
672
+ "description": "GLM workers with a strong oracle candidate.",
673
+ "models": ["zai/glm-5-turbo", "zai/glm-5.3-flash", "zai/glm-5.3"]
674
+ },
675
+ "project-gpt": {
676
+ "description": "GPT models approved for this project.",
677
+ "models": ["openai-codex/gpt-5.6-luna", "openai-codex/gpt-5.6-terra"]
553
678
  }
554
679
  }
555
680
  ```
556
681
 
557
- ### Parent-model-aware model selection (`modelByParent`)
682
+ ### Legacy configuration compatibility
558
683
 
559
- Any type profile can carry `modelByParent`: a map from glob model refs (matched against the **current parent model**, e.g. `"zai/*"`) to a model for that role. The first matching key wins. Values may be a model string or `{ "model": "...", "fallbackModels": [...] }`. It is resolved after an explicit task `model` / `forcedModel`, but **before** the preset/static profile `model`, so a role can always pick a model based on who the parent is — independent of the active preset.
684
+ Old built-in role names are no longer implicit aliases. `quick`, `scan`,
685
+ `review`, `deep`, `docs`, `frontend`, and `tests` are valid only when explicitly
686
+ defined as ordinary project `.pi/agents/<name>.md` files.
560
687
 
561
- The canonical use case is an **`oracle`** role that consults a flagship model from a *different* provider than the parent for a second opinion:
562
-
563
- ```jsonc
564
- "oracle": {
565
- "description": "Cross-provider second opinion: consult a flagship from a different provider than the parent to pressure-test a hard decision. Read-only; advise, do not edit.",
566
- "model": "openai-codex/gpt-5.6-sol",
567
- "fallbackModels": ["zai/glm-5.3"],
568
- "thinking": "max",
569
- "modelByParent": {
570
- "zai/*": { "model": "openai-codex/gpt-5.6-sol", "fallbackModels": ["zai/glm-5.3"] },
571
- "openai-codex/*": "zai/glm-5.3",
572
- "antigravity/*": { "model": "zai/glm-5.3", "fallbackModels": ["openai-codex/gpt-5.6-sol"] },
573
- "anthropic/*": { "model": "openai-codex/gpt-5.6-sol", "fallbackModels": ["zai/glm-5.3"] }
574
- }
575
- }
576
- ```
688
+ Within an agent Markdown file, legacy `model` plus `fallbackModels` and
689
+ `modelByParent` remain readable. `models` is a complete replacement list: it
690
+ clears inherited legacy model/fallback/parent routing. New built-ins use ordered
691
+ `models` lists and contain no parent-tier escalation maps.
577
692
 
578
- With this config a GLM parent (`zai/*`) spawns the oracle on `gpt-5.6-sol`, a GPT parent (`openai-codex/*`) spawns it on `glm-5.3`, and so on — automatically, at spawn time, with no `task.model` needed. The parent model ref is read from the spawn context (`ctx.model`) and passed into resolution. Pattern matching is case-insensitive `*` glob (same engine as `vision.blindModelPatterns`). When no key matches (or no parent model is known), the role falls back to its static `model` + `fallbackModels`. An explicit `task.model` or `ASYNC_SUBAGENTS_FORCE_CURRENT_MODEL=1` still overrides the match.
693
+ The removed `asyncSubagents` section is not part of the public schema or generated
694
+ user config and is no longer read at runtime. Existing files can remain on disk
695
+ without being rewritten, but they have no effect: migrate role definitions to
696
+ `.pi/agents/*.md` and custom model pools to `.pi/agents/presets.jsonc`. Runtime
697
+ retry structures and the separate role router continue to use the term
698
+ `fallbackModels` for actual fallback-only lists, not agent candidates.
579
699
 
580
700
  Sub-agents run with `--no-session` by default to avoid writing duplicate Pi session JSONL files for fire-and-forget background work. Set `ASYNC_SUBAGENTS_ENABLE_SESSIONS=1` to restore persisted per-agent sessions under each agent's `sessions/` directory; this also registers the session-navigation slash commands (`/sub-open`, `/sub-back`, `/sub-where`) needed for switching and deeper post-mortem navigation.
581
701
 
@@ -583,7 +703,7 @@ Sub-agent runs are stored in the current project's `.pi/subagents/` directory wh
583
703
 
584
704
  Runtime logs are minimized by default: successful agents do not keep `events.jsonl`, and `stderr.log` is discarded unless the agent fails. Set `ASYNC_SUBAGENTS_DEBUG_LOGS=1` / `PI_SUBAGENTS_DEBUG_LOGS=1` to keep diagnostic logs for successful agents too; debug event logs store a compact RPC event summary instead of the full streaming transcript. Defaults are 0 bytes for `events.jsonl` without debug, 32 MiB for debug `events.jsonl`, 8 MiB for retained `stderr.log`, and 8 MiB for a single RPC JSON line; override with `ASYNC_SUBAGENTS_MAX_EVENTS_BYTES` / `PI_SUBAGENTS_MAX_EVENTS_BYTES`, `ASYNC_SUBAGENTS_MAX_STDERR_BYTES` / `PI_SUBAGENTS_MAX_STDERR_BYTES`, and `ASYNC_SUBAGENTS_MAX_RPC_LINE_CHARS` / `PI_SUBAGENTS_MAX_RPC_LINE_CHARS`.
585
705
 
586
- `asyncSubagents` config also supports `maxConcurrent` (default 5, project-wide; `0` means unlimited), global/per-type `retry` with exponential backoff, global/per-type `maxResultBytes` for bounding `result.json.resultText` while keeping raw `result.md` intact, and global/per-type/preset `timeoutMs` for wall-clock agent watchdogs. Spawn calls and individual task objects can pass `timeoutSeconds` to shorten the watchdog for synthetic tests or bounded probes. Stop requests mark running, queued planned, and retry-pending agents as `stopped` so queued work is not launched later. Completed agents write `result.json` with status/duration/model/retry metadata plus best-effort `summary`, `findings`, `files`, `risks`, `nextActions`, and `confidence` fields for parent-agent chaining.
706
+ Runtime concurrency defaults to 5 agents per project and the global result summary bound defaults to 100000 bytes. These are internal engine defaults rather than normal user configuration. Per-agent `retry`, `maxResultBytes`, and `timeoutMs` belong in agent Markdown; spawn calls and individual task objects can pass `timeoutSeconds` to shorten the watchdog for synthetic tests or bounded probes. Stop requests mark running, queued planned, and retry-pending agents as `stopped` so queued work is not launched later. Completed agents write `result.json` with status/duration/model/retry metadata plus best-effort `summary`, `findings`, `files`, `risks`, `nextActions`, and `confidence` fields for parent-agent chaining.
587
707
 
588
708
  ## OpenCode credential import
589
709
 
@@ -1,28 +1,43 @@
1
1
  # Browser QA sub-agent specification
2
2
 
3
+ ## Type
4
+
5
+ As-is
6
+
7
+ ## Lifecycle
8
+
9
+ Active implemented contract.
10
+
3
11
  ## Goal
4
12
 
5
13
  Provide a cheap, fast `browser-qa` async-subagent that reproduces browser bugs
6
14
  and proves fixes with deterministic assertions plus screenshot, video, and trace
7
- evidence. The role uses `zai/glm-5.3-flash`, falling back to
8
- `openai-codex/gpt-5.6-luna`.
9
-
10
- ## Private skill isolation
11
-
12
- - The browser QA skill lives under `src/async-subagents/private-skills/`, outside
13
- Pi's normal skill discovery roots.
15
+ evidence. Its ranked `models` list prefers `zai/glm-5.3-flash`, then
16
+ `openai-codex/gpt-5.6-luna`, filtered by the active preset's model pool and
17
+ confirmed runtime image support.
18
+
19
+ ## Inline agent workflow and skill isolation
20
+
21
+ - All operating instructions, flow contracts, scenario-design guidance, and
22
+ auth-scaffolding rules live in `src/async-subagents/agents/browser-qa.md`.
23
+ Its body becomes the QA child's `promptAppend` through the shared agent
24
+ loader. Parent and router catalogs include only its short `description`.
25
+ - Runner code, vendor dependencies/licenses, and optional JSONC examples live
26
+ under `src/async-subagents/agents/browser-qa/`; none is a discoverable skill.
14
27
  - Sub-agent processes disable normal extension discovery, then always load the
15
- suite's model-tools and Antigravity provider extensions explicitly, regardless
16
- of the selected model. This keeps the process isolated without making any
17
- Antigravity-backed role unavailable.
28
+ suite's model-tools extension. They load the Antigravity provider extension
29
+ only when an Antigravity model is explicitly selected.
18
30
  - A type profile may declare `isolatedSkills`. Spawning that profile adds
19
31
  `--no-skills` followed by one explicit `--skill` per configured path.
20
- - The `browser-qa` profile always loads one self-contained private workflow.
21
- Relevant browser-test design guidance is bundled beside its trusted runner;
22
- no separately discovered skill or browser CLI is required. Configuration may
23
- append isolated skills but cannot remove the mandatory private workflow.
24
- - Other sub-agent profiles and the parent session must not discover the private
25
- skill automatically.
32
+ - `browser-qa` always disables normal skill discovery and filters skill flags
33
+ out of `extraArgs`, even without configured skills. It no longer injects a
34
+ mandatory QA skill. Explicitly configured skills are optional additions.
35
+ - The launcher sets `PI_BROWSER_QA_RUNNER` to the absolute installed runner path,
36
+ replacing inherited values, and strips it from ordinary child environments.
37
+ QA invokes `node "$PI_BROWSER_QA_RUNNER"` without guessing paths from cwd.
38
+ - Model-only profile overrides inherit the workflow. An explicit profile
39
+ `promptAppend` replaces the body like any other agent profile; it is not an
40
+ immutable security boundary. Runtime protections remain in the runner.
26
41
 
27
42
  ## Authentication contract
28
43
 
@@ -98,7 +113,7 @@ evidence. The role uses `zai/glm-5.3-flash`, falling back to
98
113
 
99
114
  ## Reliability and shutdown contract
100
115
 
101
- - The built-in `browser-qa` profile has a 120-second wall-clock budget unless
116
+ - The built-in `browser-qa` profile has a 300-second wall-clock budget unless
102
117
  the caller explicitly supplies a task or spawn timeout. This bounds model
103
118
  stalls as well as browser work.
104
119
  - The trusted runner has its own bounded lifecycle. Browser launch, context
@@ -122,13 +137,27 @@ evidence. The role uses `zai/glm-5.3-flash`, falling back to
122
137
  failure the runner snapshots and kills only its own descendants before it
123
138
  exits, covering that detached browser tree without touching a user's browser.
124
139
 
140
+ ## Related files
141
+
142
+ - `external/pi-tools-suite/src/async-subagents/agents/browser-qa.md`
143
+ - `external/pi-tools-suite/src/async-subagents/core/browser-qa.ts`
144
+ - `external/pi-tools-suite/src/async-subagents/core/spawn.ts`
145
+ - `external/pi-tools-suite/src/async-subagents/agents/browser-qa/scripts/browser-qa-runner.mjs`
146
+ - `external/pi-tools-suite/test/async-subagents/core.test.ts`
147
+ - `external/pi-tools-suite/test/async-subagents/browser-qa-runner.test.ts`
148
+ - `external/pi-tools-suite/test/async-subagents/browser-qa-runner.e2e.test.ts`
149
+ - `external/pi-tools-suite/test/async-subagents/selection-e2e.test.ts`
150
+
125
151
  ## Acceptance criteria
126
152
 
127
- 1. `browser-qa` resolves to the intended model/fallback and its self-contained
128
- private workflow, and its isolated child process can register the configured
153
+ 1. `browser-qa` resolves to the intended model/fallback and its inline Markdown
154
+ workflow, and its isolated child process can register the configured
129
155
  model provider.
130
- 2. Spawn args contain `--no-skills` and the mandatory private skill for this
131
- profile; ordinary profiles retain existing skill discovery behavior.
156
+ 2. Default QA spawn args contain `--no-skills` but no `--skill`. The child
157
+ receives the full workflow in its initial prompt and can invoke the bundled
158
+ runner through `PI_BROWSER_QA_RUNNER` from an unrelated project directory.
159
+ Optional configured skills still load; ordinary profiles retain existing
160
+ skill discovery behavior and do not receive QA-only environment paths.
132
161
  3. Auth profile listing and all error output are redacted; model-authored input
133
162
  cannot execute code in the credential-bearing process.
134
163
  4. Runner tests cover public execution without an auth file, explicit profile