frizz 0.7.7 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/README.md +15 -45
  2. package/dist/claude-agent-broker.js +7 -4
  3. package/dist/dev-child.js +422 -273
  4. package/dist/frizz.js +1003 -398
  5. package/package.json +1 -1
  6. package/runtime/cc-worker/.claude-plugin/plugin.json +1 -1
  7. package/runtime/cc-worker/DECISIONS.md +31 -2
  8. package/runtime/cc-worker/agents/high.md +7 -0
  9. package/runtime/cc-worker/agents/low.md +7 -0
  10. package/runtime/cc-worker/agents/max.md +7 -0
  11. package/runtime/cc-worker/agents/medium.md +7 -0
  12. package/runtime/cc-worker/agents/xhigh.md +7 -0
  13. package/runtime/cc-worker/bin/frizz-mcp.mjs +3 -2
  14. package/runtime/cc-worker/hooks/agent-dispatch.mjs +7 -6
  15. package/runtime/cc-worker/hooks/hooks.json +0 -2
  16. package/runtime/cc-worker/hooks/scratchpad.mjs +5 -3
  17. package/runtime/cc-worker/hooks/session-seed.mjs +17 -17
  18. package/runtime/cc-worker/skills/gh/SKILL.md +5 -19
  19. package/web-dist/assets/{TerminalPane-Cb8jOFP9.js → TerminalPane-BIBHC61j.js} +1 -1
  20. package/web-dist/assets/{abnfDiagram-VRR7QNED-Dtbg2eZ0.js → abnfDiagram-VRR7QNED-CcFQGFPf.js} +1 -1
  21. package/web-dist/assets/architecture-TIHT7OUA-BZEZt7jZ.js +1 -0
  22. package/web-dist/assets/{architectureDiagram-ZJ3FMSHR-DzQjWW7u.js → architectureDiagram-ZJ3FMSHR-DErIQOIs.js} +1 -1
  23. package/web-dist/assets/{blockDiagram-677ZJIJ3-BJnpkLMt.js → blockDiagram-677ZJIJ3-CpsUqur1.js} +1 -1
  24. package/web-dist/assets/{c4Diagram-LMCZKHZV-COdatsYu.js → c4Diagram-LMCZKHZV-D2dHmCEJ.js} +1 -1
  25. package/web-dist/assets/channel-DdFRPviT.js +1 -0
  26. package/web-dist/assets/{chunk-32BRIVSS-CORMw4Vm.js → chunk-32BRIVSS-aOCEfxRW.js} +1 -1
  27. package/web-dist/assets/{chunk-52WLFC77-C7lEadTg.js → chunk-52WLFC77-2iw4nJPC.js} +1 -1
  28. package/web-dist/assets/{chunk-C7G6YPKG-DZy4F97l.js → chunk-C7G6YPKG-BPD3iHVE.js} +1 -1
  29. package/web-dist/assets/{chunk-EX3LRPZG-HynlfV9p.js → chunk-EX3LRPZG-DrefHift.js} +1 -1
  30. package/web-dist/assets/{chunk-FWX5IMBZ-BbwKNhKm.js → chunk-FWX5IMBZ-By940EHT.js} +2 -2
  31. package/web-dist/assets/{chunk-HOUHSVGY-lIhOZSmL.js → chunk-HOUHSVGY-B1Cqvz7e.js} +1 -1
  32. package/web-dist/assets/{chunk-ICXQ74PX-WGxaMO8c.js → chunk-ICXQ74PX-1LkVpWuI.js} +1 -1
  33. package/web-dist/assets/{chunk-MOJQB5TN-B-cx0f3u.js → chunk-MOJQB5TN-Ip1cy64r.js} +1 -1
  34. package/web-dist/assets/{chunk-OGEWGWER-DJceVwZH.js → chunk-OGEWGWER-CNjVyu8F.js} +1 -1
  35. package/web-dist/assets/{chunk-PUDLZKDR-CGwHZns8.js → chunk-PUDLZKDR-9HZR6DAU.js} +1 -1
  36. package/web-dist/assets/{chunk-Q4XR5HBZ-PTSWtmk1.js → chunk-Q4XR5HBZ-vtWwOCuQ.js} +1 -1
  37. package/web-dist/assets/{chunk-V7JOEXUC-VNxHZPcf.js → chunk-V7JOEXUC-DC6YaHG0.js} +1 -1
  38. package/web-dist/assets/{chunk-VAUOI2AC-ZXYCz_Aw.js → chunk-VAUOI2AC-CP-xe7SD.js} +1 -1
  39. package/web-dist/assets/{chunk-VR4S4FIN-9WCtmFJp.js → chunk-VR4S4FIN-wbxDFptH.js} +1 -1
  40. package/web-dist/assets/{chunk-WYO6CB5R-V4EBjpmt.js → chunk-WYO6CB5R-dibXmwpK.js} +1 -1
  41. package/web-dist/assets/{chunk-ZGVPDNZ5-CPW0Z0ae.js → chunk-ZGVPDNZ5-_y_itJHG.js} +1 -1
  42. package/web-dist/assets/classDiagram-OUVF2IWQ-Bf3duLb8.js +1 -0
  43. package/web-dist/assets/classDiagram-v2-EOCWNBFH-Bf3duLb8.js +1 -0
  44. package/web-dist/assets/{cynefin-VYW2F7L2-E7PklfJD.js → cynefin-VYW2F7L2-D1RYokZP.js} +1 -1
  45. package/web-dist/assets/{cynefinDiagram-TSTJHNR4-JIXAPjDf.js → cynefinDiagram-TSTJHNR4-qofqoy3T.js} +1 -1
  46. package/web-dist/assets/{dagre-VKFMJZFB-DjXrdcNx.js → dagre-VKFMJZFB-CgHLoGFk.js} +1 -1
  47. package/web-dist/assets/{diagram-FQU43EPY--i9i0qhm.js → diagram-FQU43EPY-JEAs4LOb.js} +1 -1
  48. package/web-dist/assets/{diagram-G47NLZAW-DxgcENZ_.js → diagram-G47NLZAW--tLd4Lf7.js} +1 -1
  49. package/web-dist/assets/{diagram-NH7WQ7WH-CUy9Nr90.js → diagram-NH7WQ7WH-DPbw9CJU.js} +1 -1
  50. package/web-dist/assets/{diagram-OA4YK3LP-DbTbUaCb.js → diagram-OA4YK3LP-CDrb7nWs.js} +1 -1
  51. package/web-dist/assets/{diagram-WEI45ONY-2gk6xhOq.js → diagram-WEI45ONY-DJswZe3f.js} +1 -1
  52. package/web-dist/assets/{ebnfDiagram-CCIWWBDH-uE2iDETg.js → ebnfDiagram-CCIWWBDH-BP8-PZMF.js} +1 -1
  53. package/web-dist/assets/{erDiagram-Q63AITRT-dztd4MUw.js → erDiagram-Q63AITRT-BQXuebf5.js} +1 -1
  54. package/web-dist/assets/eventmodeling-45OFAUF4-DOLxRQQ5.js +1 -0
  55. package/web-dist/assets/flowDiagram-23GEKE2U-DoK1yb0H.js +1 -0
  56. package/web-dist/assets/{ganttDiagram-NO4QXBWP-DAds6Aht.js → ganttDiagram-NO4QXBWP-DotMb935.js} +1 -1
  57. package/web-dist/assets/{gitGraph-TEB2WS4Q-Ci0XVvIa.js → gitGraph-TEB2WS4Q-B1vbYyKQ.js} +1 -1
  58. package/web-dist/assets/{gitGraphDiagram-IHSO6WYX-C6FULyt8.js → gitGraphDiagram-IHSO6WYX-BjDXKk4m.js} +1 -1
  59. package/web-dist/assets/index-CmrDpsD8.css +1 -0
  60. package/web-dist/assets/{index-CNy5uOpI.js → index-Cs0TDGMu.js} +124 -124
  61. package/web-dist/assets/{info-DKCQHKI2-9N77dOiw.js → info-DKCQHKI2-xLTLqQju.js} +1 -1
  62. package/web-dist/assets/{infoDiagram-FWYZ7A6U-BymP3PgG.js → infoDiagram-FWYZ7A6U-BFfYUsrC.js} +1 -1
  63. package/web-dist/assets/{ishikawaDiagram-FXEZZL3T-CU_kQBz1.js → ishikawaDiagram-FXEZZL3T-45a7VMwm.js} +1 -1
  64. package/web-dist/assets/{journeyDiagram-5HDEW3XC-DZN15HSd.js → journeyDiagram-5HDEW3XC-CEBUpu59.js} +1 -1
  65. package/web-dist/assets/{kanban-definition-HUTT4EX6-J4wR5g_3.js → kanban-definition-HUTT4EX6-RwKtDFzG.js} +1 -1
  66. package/web-dist/assets/{line-SRzGpiDr.js → line-DStcMIry.js} +1 -1
  67. package/web-dist/assets/{mermaid-parser.core-CGBscNGo.js → mermaid-parser.core-B0ekgQMA.js} +3 -3
  68. package/web-dist/assets/{mermaid.core-xNdwXb1r.js → mermaid.core-w1hcQaPy.js} +3 -3
  69. package/web-dist/assets/{mindmap-definition-LN4V7U3C-gR2dbzrj.js → mindmap-definition-LN4V7U3C-D_n38Imb.js} +1 -1
  70. package/web-dist/assets/{packet-7NZHBO7P-DrR4W6I3.js → packet-7NZHBO7P-CstGeBOX.js} +1 -1
  71. package/web-dist/assets/{pegDiagram-2B236MQR-DN7R-_t4.js → pegDiagram-2B236MQR-DvowVyTO.js} +1 -1
  72. package/web-dist/assets/{pie-RZYD4A2V-C8VjQAFZ.js → pie-RZYD4A2V-BOP2j_HH.js} +1 -1
  73. package/web-dist/assets/{pieDiagram-ENE6RG2P-5w64zdD1.js → pieDiagram-ENE6RG2P-CKRqu_2f.js} +1 -1
  74. package/web-dist/assets/{quadrantDiagram-ABIIQ3AL-B4rbezq_.js → quadrantDiagram-ABIIQ3AL-zSArSS8R.js} +1 -1
  75. package/web-dist/assets/{radar-I7S5WNFK-CTbbPB8m.js → radar-I7S5WNFK-BqRdNIBw.js} +1 -1
  76. package/web-dist/assets/{railroad-3IZDKUUU-CY1er15b.js → railroad-3IZDKUUU-BaKcl_LU.js} +1 -1
  77. package/web-dist/assets/railroad-abnf-AHOZXSZD-itqDLg1p.js +1 -0
  78. package/web-dist/assets/railroad-ebnf-EBAXGLYW-ze7rLVCi.js +1 -0
  79. package/web-dist/assets/railroad-peg-LSFZ7HO6-DKsYkEuG.js +1 -0
  80. package/web-dist/assets/{railroadDiagram-RFXS5EU6-Bx2HJ3yT.js → railroadDiagram-RFXS5EU6-BrXTQge9.js} +1 -1
  81. package/web-dist/assets/{requirementDiagram-TGXJPOKE-BLK-Y2rx.js → requirementDiagram-TGXJPOKE-DBBNi_SS.js} +1 -1
  82. package/web-dist/assets/{sankeyDiagram-HTMAVEWB-Dk-8Miv-.js → sankeyDiagram-HTMAVEWB-BwFi7xFy.js} +1 -1
  83. package/web-dist/assets/{sequenceDiagram-DBY2YBRQ-DL2alfR-.js → sequenceDiagram-DBY2YBRQ-CeivqMeT.js} +1 -1
  84. package/web-dist/assets/{stateDiagram-2N3HPSRC-Bka44wf1.js → stateDiagram-2N3HPSRC-C6NZsnFm.js} +1 -1
  85. package/web-dist/assets/stateDiagram-v2-6OUMAXLB-B3YRnI4W.js +1 -0
  86. package/web-dist/assets/{swimlanes-5IMT3BWC-e0GbMwIr.js → swimlanes-5IMT3BWC-C0MubXTG.js} +1 -1
  87. package/web-dist/assets/swimlanesDiagram-G3AALYLV-CXva4Ic9.js +8 -0
  88. package/web-dist/assets/{timeline-definition-FHXFAJF6-CT3GFq89.js → timeline-definition-FHXFAJF6-CtxwSvFu.js} +1 -1
  89. package/web-dist/assets/{treeView-QDETBFTQ-BJauJ0bm.js → treeView-QDETBFTQ-CXcwSjey.js} +1 -1
  90. package/web-dist/assets/{treemap-6X3UGDF4-DCX7A-nx.js → treemap-6X3UGDF4-Uspgr-d1.js} +1 -1
  91. package/web-dist/assets/{vennDiagram-L72KCM5P-D4dm2iTR.js → vennDiagram-L72KCM5P-tZamQQAQ.js} +1 -1
  92. package/web-dist/assets/{wardley-OPB4EBWU-DklTDSId.js → wardley-OPB4EBWU-0_79c19P.js} +1 -1
  93. package/web-dist/assets/{wardleyDiagram-EHGQE667-CikP5hBd.js → wardleyDiagram-EHGQE667-uYmUsP66.js} +1 -1
  94. package/web-dist/assets/{xychartDiagram-FW5EYKEG-FXuOAFpz.js → xychartDiagram-FW5EYKEG-BsOU7Wf7.js} +1 -1
  95. package/web-dist/index.html +2 -2
  96. package/runtime/cc-worker/agents/fable-high.md +0 -8
  97. package/runtime/cc-worker/agents/fable-low.md +0 -8
  98. package/runtime/cc-worker/agents/fable-max.md +0 -8
  99. package/runtime/cc-worker/agents/fable-medium.md +0 -8
  100. package/runtime/cc-worker/agents/fable-xhigh.md +0 -8
  101. package/runtime/cc-worker/agents/haiku.md +0 -7
  102. package/runtime/cc-worker/agents/opus-high.md +0 -8
  103. package/runtime/cc-worker/agents/opus-low.md +0 -8
  104. package/runtime/cc-worker/agents/opus-max.md +0 -8
  105. package/runtime/cc-worker/agents/opus-medium.md +0 -8
  106. package/runtime/cc-worker/agents/opus-xhigh.md +0 -8
  107. package/runtime/cc-worker/agents/sonnet-high.md +0 -8
  108. package/runtime/cc-worker/agents/sonnet-low.md +0 -8
  109. package/runtime/cc-worker/agents/sonnet-max.md +0 -8
  110. package/runtime/cc-worker/agents/sonnet-medium.md +0 -8
  111. package/runtime/cc-worker/agents/sonnet-xhigh.md +0 -8
  112. package/runtime/cc-worker/bin/browser-mcp-tools.json +0 -1192
  113. package/runtime/cc-worker/bin/browser-mcp.mjs +0 -730
  114. package/runtime/cc-worker/hooks/precompact-instructions.mjs +0 -133
  115. package/runtime/cc-worker/skills/waits/SKILL.md +0 -84
  116. package/web-dist/assets/architecture-TIHT7OUA-CTxVpl9_.js +0 -1
  117. package/web-dist/assets/channel-COS0Ygbp.js +0 -1
  118. package/web-dist/assets/classDiagram-OUVF2IWQ-Df5TLnrN.js +0 -1
  119. package/web-dist/assets/classDiagram-v2-EOCWNBFH-Df5TLnrN.js +0 -1
  120. package/web-dist/assets/eventmodeling-45OFAUF4-DPVPOEaJ.js +0 -1
  121. package/web-dist/assets/flowDiagram-23GEKE2U-BMIMgVYd.js +0 -1
  122. package/web-dist/assets/index-D6LsViUY.css +0 -1
  123. package/web-dist/assets/railroad-abnf-AHOZXSZD-DfEpkrtJ.js +0 -1
  124. package/web-dist/assets/railroad-ebnf-EBAXGLYW-Csunejgu.js +0 -1
  125. package/web-dist/assets/railroad-peg-LSFZ7HO6-BgRslbM_.js +0 -1
  126. package/web-dist/assets/stateDiagram-v2-6OUMAXLB-6KcScVPX.js +0 -1
  127. package/web-dist/assets/swimlanesDiagram-G3AALYLV-jaJhlDbE.js +0 -8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frizz",
3
- "version": "0.7.7",
3
+ "version": "0.8.0",
4
4
  "private": false,
5
5
  "description": "A local web UI for running many coding agents at once",
6
6
  "keywords": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frizz",
3
- "description": "Worker-side frizz plugin for frizz-spawned sessions. Each session is a WORKER driving ONE effort (slug via env FRIZZ_THREAD): it SIGNALS through its final message (done, human/timer awaiting, question), keeps automatable waits active with Claude wait tools, and keeps its own free-form scratch directory (.frizz/threads/<session-id>/). Supplies the frizz:<model>-<effort> sub-agent profiles (dispatch as frizz:opus-high, frizz:sonnet-medium, frizz:haiku, ), the on-demand frizz:gh skill, and hooks that seed the worker contract, enforce background/name-stripped sub-agent dispatch, and deny the interactive question/plan prompts (deny-ask, deny-plan) that would hang a dashboard worker. Hooks are inert unless FRIZZ_THREAD is set.",
3
+ "description": "Worker-side frizz plugin for frizz-spawned sessions. Each session is a WORKER driving ONE effort (slug via env FRIZZ_THREAD): it SIGNALS through its final message (done, human/timer awaiting, question), keeps automatable waits active with Claude wait tools, and keeps its own free-form scratch directory (.frizz/threads/<session-id>/). Supplies the effort-only frizz:<effort> sub-agent profiles (frizz:low frizz:max; the model rides the Agent tool's own parameter), the on-demand frizz:gh skill, and hooks that seed the worker contract, enforce background/name-stripped sub-agent dispatch, and deny the interactive question/plan prompts (deny-ask, deny-plan) that would hang a dashboard worker. Hooks are inert unless FRIZZ_THREAD is set.",
4
4
  "version": "0.1.10",
5
5
  "author": { "name": "Colin McDonnell" },
6
6
  "homepage": "https://github.com/colinhacks/frizz",
@@ -1032,7 +1032,7 @@ Maintainer's call, verbatim: *"This is obviously something that should not be a
1032
1032
 
1033
1033
  Three removals, one theme — Frizz's shipped worker contract states frizz MECHANICS, and everything else belongs to the repo or to the dispatch that starts the thread.
1034
1034
 
1035
- - **`runtimeGate` (setting) + `RUNTIME_GATE` (prompt module) — gone.** The browser-QA loop (drive it in Chrome, screenshot into the handoff, escalate to an adversarial reviewer) was frizz's own engineering norm shipped to every worker Frizz dispatches anywhere. That is what `FRIZZ.md` / `CLAUDE.md` are for: `frizzConfigBlock` already injects a repo's own conventions into every spawn/adopt/resume, and this repo keeps its full browser-QA section there. What remains in the shipped contract is the repo-agnostic line that was already in the Quality bar — *"Verify behavior end-to-end before calling anything done."* `VISUAL_EVIDENCE` **stays**: it documents Frizz's guarded local-image proxy, a platform capability, not a QA policy. `chrome-devtools` also stays always-mounted — giving a worker a browser is a capability, not an opinion about when to use it.
1035
+ - **`runtimeGate` (setting) + `RUNTIME_GATE` (prompt module) — gone.** The browser-QA loop (drive it in Chrome, screenshot into the handoff, escalate to an adversarial reviewer) was frizz's own engineering norm shipped to every worker Frizz dispatches anywhere. That is what `FRIZZ.md` / `CLAUDE.md` are for: `frizzConfigBlock` already injects a repo's own conventions into every spawn/adopt/resume, and this repo keeps its full browser-QA section there. What remains in the shipped contract is the repo-agnostic line that was already in the Quality bar — *"Verify behavior end-to-end before calling anything done."* `VISUAL_EVIDENCE` **stays**: it documents Frizz's guarded local-image proxy, a platform capability, not a QA policy. `chrome-devtools` also stays always-mounted — giving a worker a browser is a capability, not an opinion about when to use it. **(Reversed 2026-08-26 — see the entry at the end of this file. The reasoning above survives one step further than it should have: mounting a browser is itself an opinion, and it was billed to every worker in tokens.)**
1036
1036
  - **Model + Effort — removed from the settings drawer.** They are chosen per dispatch in the prompt box (`DispatchPreferences`, one profile per runtime); a second global copy only made it ambiguous which one applied. `Settings.model` / `Settings.effort` survive on the wire: `dispatch-preferences.ts` still seeds the composer's first-run profile from them and `dispatch.ts` still falls back to them for GitHub batch dispatch.
1037
1037
  - **`autoResumeOnLimit` — gone; auto-resume is unconditional.** A thread cut off mid-turn by an exhausted subscription window always gets its own "continue" when the window rolls. `ThreadView.limitPause.autoResume` survives on the wire but is now purely a STALENESS verdict (`resolveLimitPause`): a fault old enough that the wake will never arrive stops promising one.
1038
1038
 
@@ -1105,9 +1105,38 @@ and "exists" stopped meaning "the worker wrote something".
1105
1105
 
1106
1106
  Maintainer: *"Changing the model and effort in a prompt box. That should be remembered, that new setting, but it should also be applied globally across all projects."* It was remembered — `DispatchPreferences` has been durable since the composer grew the selector — but in the per-project SQLite `settings` row, so one server serving N projects showed N different profiles, and a choice made in one project was invisible in the next.
1107
1107
 
1108
- - **The record now lives in `<data>/dispatch-preferences.json`, beside `settings.json`**, read and written through `server/dispatch-preferences.ts` the same way `font` is: machine file → this project's stored row → the Settings-derived default. The context exposes `getDispatchPreferences`/`setDispatchPreference` closures over `home`, so the router never learns where the file is.
1108
+ - **The record is now the `dispatchPreferences` entry of a machine-level key/value store** `server/machine-config.ts`, one JSON object at `<data>/config.json` keyed by record name, each value validated by its owner's schema — resolved store → this project's stored row → the Settings-derived default. The context exposes `getDispatchPreferences`/`setDispatchPreference` closures over `home`, so the router never learns where the record is.
1109
+ - **The store is the machine-level counterpart of a project database's `settings` table, and it has two tenants from day one.** It first landed as a file of its own, `dispatch-preferences.json`; the maintainer asked *"surely we have some general-purpose system for storing bits of persistent configuration like this?"* — there was none at machine level (`settings.json`, `registry.json` and `cloud.json` each hand-roll a reader and writer), so the answer was to build it and move the machine settings (`font`, `notifications`, `localFileOpener`, `projectRail`) into it as the `settings` record. The old `settings.json` is read as a fallback and never written again; a settings reset removes both. `registry.json` and `cloud.json` were left as they are — each has its own lifecycle and locking story, and neither was the question.
1109
1110
  - **No migration.** A project that chose a profile before the file existed keeps showing it from its row; the next selection, made anywhere, writes the file and is what every project opens on from then on. Every write still mirrors into the row, so an older server reading that database sees the same choice.
1110
1111
  - **The whole record moved, including the per-runtime `permissionMode` inside it.** That field is vestigial — no `SetDispatchPreferenceInput` variant can set it and the composer's resolver never reads it (dispatch permission is decided server-side from Settings) — so nothing per-project was given up. Settings' own `permissionMode` stays per project, as before.
1111
1112
  - **The web cache treats `["dispatchPreferencesGet"]` as machine-wide** (`lib/queryKeyScope.ts`), so the composer's optimistic write on one project is what a client-side switch paints on the next, rather than that project's last-seen copy for the beat before a refetch.
1112
1113
 
1113
1114
  Verified on a real two-project stack (launcher + tenant on one server): a profile chosen through the tenant's RPC is what the launcher reads, and back; a per-project `settingsSet` on the launcher stayed invisible to the tenant, which is the control that the two prefixes reach different projects.
1115
+ ## 2026-08-26: Frizz mounts NO browser — a `chrome-devtools` server is the project's to bring
1116
+
1117
+ Maintainer: *"Is the Chrome DevTool stuff something that frizz automatically injects? Why not just let the user bring that themselves? That's very confusing to me. I feel like there's a level of opinionation here that we don't really want."*
1118
+
1119
+ This reverses the 2026-08-03 line above (*"`chrome-devtools` also stays always-mounted — giving a worker a browser is a capability, not an opinion"*). The capability argument stopped holding once the bill was measured: the server's 29 tool schemas sat in the prefix of **every** worker session at **~6,400 tokens**, and most workers never open a page. A capability nobody asked for, charged per turn, is an opinion.
1120
+
1121
+ - **Both backends stopped injecting it.** Claude's inline `--mcp-config` (`claudeMcpConfig`, `dispatch.ts`) and codex's `-c mcp_servers.chrome-devtools=…` app-server override (`codex-mcp.ts`) now mount the unified `frizz` server and nothing else. Parity was the point of the original pairing and it is the point of the removal.
1122
+ - **The lazy proxy went with it.** `cc-worker/bin/browser-mcp.mjs` and its committed schema snapshot `browser-mcp-tools.json` existed only to make the always-on mount affordable in MEMORY (159 MB → ~17 MB per worker, 2026-08-19). With no mount there is nothing to proxy, so they are deleted along with `chromeDevtoolsMcpSpec` / `chromeDevtoolsMcpMount` / `resolveBrowserMcpScript` / `CHROME_DEVTOOLS_MCP`, `scripts/harvest-browser-mcp-tools.mjs`, and the worker-plugin closure entries that required them. The memory win it bought is now the token win.
1123
+ - **Nothing about a browser is banned — it is just not Frizz's to decide.** A project adds a `.mcp.json` (plus `enabledMcpjsonServers` in `.claude/settings.json`, so a headless worker is never blocked on the approval prompt); an operator runs `claude mcp add --scope user`. Frizz's `--mcp-config` ADDS to whatever the CLI discovered rather than replacing it (frizz never passes `--strict-mcp-config`), so both paths reach a dispatched worker untouched.
1124
+ - **This repo does exactly that, and that is the whole demonstration.** Frizz's own skills drive Chrome headless, so the repo root carries the `.mcp.json` that used to be injected — pinned `chrome-devtools-mcp@1.7.0 --experimentalPageIdRouting --headless --isolated --no-usage-statistics`, the same argv the deleted spec rendered. Verified end-to-end on a disposable stack: a worker dispatched in a scratch project with no config reported `frizz` tools and no browser; a worker dispatched in this repo reported the full `mcp__chrome-devtools__*` set with no permission prompt.
1125
+ - **What deliberately stayed.** The orphan reaper still reaps `chrome-devtools-mcp` processes by name (a browser the USER brought leaks exactly the same way), and the transcript still renders a `take_screenshot` image result. Neither depends on who mounted the server.
1126
+
1127
+ ## 2026-08-26: Sub-agent profiles are effort-only, and the dispatch epilogue carries mechanics, not a handoff format
1128
+
1129
+ Follow-on to the browser decision above, from the same audit of what Frizz registers into a worker that the worker did not ask for. The maintainer's frame — *"a level of opinionation here that we don't really want"* — applied to two more registrations, and the frizz Goal had this thread decide them itself.
1130
+
1131
+ - **16 `frizz:<model>-<effort>` profiles → 5 `frizz:<effort>` ones.** The model×effort grid existed because the Agent tool once had no way to pin either; today its own `model` parameter overrides a profile's model, so the only knob a profile still has to carry is `effort`. The grid cost ~1,340 tokens of agent descriptions on every session, and those descriptions doubled as a routing doctrine ("Opus matches Fable and costs less", "Haiku for scripted harvest only") that no project asked for. `low` … `max` carry no model and inherit the worker's; Haiku, which takes no effort setting, is dispatched with `model: "haiku"` and no profile. The worker contract's Sub-agents section now states the two knobs and nothing about which tier deserves which task.
1132
+ - **The dispatch-hook epilogue kept only what a helper cannot discover.** Its first paragraph prescribed the shape of a helper's final message (status, files, SHA, evidence, caveats, next action); that is a handoff format, and it is gone — one sentence remains saying the final message is what the dispatcher reads. The rest stayed because each line is a mechanic learned from a real failure: the `SendMessage({to: "main"})` upward channel, the own-file rule for the scratch directory, no fan-out of its own unless asked, and the symlinked-`.output` wait-loop trap.
1133
+ - **Verified** by the live harness (`_live_broker_workerenv.mts`, now dispatching `frizz:low`): a real broker worker through the real server dispatched the profile and it ran.
1134
+
1135
+ ## 2026-08-26: three more worker registrations deleted — the waits skill, the pre-compaction brief, and the toon nudge
1136
+
1137
+ Third pass of the same audit that removed the browser mount and the model×effort profile grid above, and the same test: does Frizz register this into every worker because the worker needs it, or because Frizz has an opinion?
1138
+
1139
+ - **`skills/waits` is DELETED.** Maintainer: *"I feel like the waits skill is being replaced now. I don't think we need that. We have our own system now for registering watchers and whatnot as tools."* The skill's whole job was teaching a worker how to hold a wait open without falling out of the board's Active band, and the durable half of that is now TOOLS — `mcp__frizz__watch_pr`, `mcp__frizz__timer`, `mcp__frizz__recurring_prompt` — which carry their own descriptions and need no playbook. What remains (a sub-agent owns the wait, `run_in_background` does not hold a rest, never fake a wait with a foreground sleep) is already stated once in the system-prompt contract, which is where a mechanical rule belongs.
1140
+ - **The portable monitors STAYED.** `skills/gh/scripts/{ci-watch,github-watch,review-watch}.mjs` are generated byte-for-byte from `monitors/` and are load-bearing for two other readers: the codex worker prompt names their absolute directory (`monitorScriptsDir()`, `dispatch.ts`, pinned by `dispatch.test.ts`), and `skills/gh` documents them as its declared-tooling fallback. Only the skill went.
1141
+ - **`hooks/precompact-instructions.mjs` is DELETED**, with both its `PreCompact` registrations. Maintainer: *"the pre-compaction instructions are probably too opinionated, entirely too opinionated."* It handed the summarizer an editorial brief about WHAT to preserve — plan, alternatives rejected, rationale, at high fidelity — which is a prescription about how someone else's work should be remembered. `scratchpad.mjs --mode=precompact` keeps both matchers: it only says the worker's scratch files exist and names their paths, which is mechanics.
1142
+ - **The `toon` bullet is gone from the seed's `⟦gh available⟧` block and from `skills/gh`.** Maintainer: *"It seems pretty opinionated to tell it to pipe through toon, given that toon is probably not installed on most machines. That might be over the line."* The original reasoning (`plans/github-integration.md` §9: worker-side yes, server-side no) was measured against THIS machine's toolchain; a `command -v toon` guard makes the advice safe but not less opinionated, and it spent prompt tokens on every authed session to describe a binary almost no repo has. The one raw-API recipe that piped through it now uses `--jq`, which ships with `gh`.
@@ -0,0 +1,7 @@
1
+ ---
2
+ name: high
3
+ description: Frizz sub-agent at high effort. Set the model with the Agent tool's `model` parameter; omitted, the child inherits the worker's model.
4
+ effort: high
5
+ ---
6
+
7
+ Execute the self-contained task in your dispatch prompt.
@@ -0,0 +1,7 @@
1
+ ---
2
+ name: low
3
+ description: Frizz sub-agent at low effort. Set the model with the Agent tool's `model` parameter; omitted, the child inherits the worker's model.
4
+ effort: low
5
+ ---
6
+
7
+ Execute the self-contained task in your dispatch prompt.
@@ -0,0 +1,7 @@
1
+ ---
2
+ name: max
3
+ description: Frizz sub-agent at max effort. Set the model with the Agent tool's `model` parameter; omitted, the child inherits the worker's model.
4
+ effort: max
5
+ ---
6
+
7
+ Execute the self-contained task in your dispatch prompt.
@@ -0,0 +1,7 @@
1
+ ---
2
+ name: medium
3
+ description: Frizz sub-agent at medium effort. Set the model with the Agent tool's `model` parameter; omitted, the child inherits the worker's model.
4
+ effort: medium
5
+ ---
6
+
7
+ Execute the self-contained task in your dispatch prompt.
@@ -0,0 +1,7 @@
1
+ ---
2
+ name: xhigh
3
+ description: Frizz sub-agent at xhigh effort. Set the model with the Agent tool's `model` parameter; omitted, the child inherits the worker's model.
4
+ effort: xhigh
5
+ ---
6
+
7
+ Execute the self-contained task in your dispatch prompt.
@@ -294,8 +294,9 @@ const WATCH_PR = {
294
294
  type: "string",
295
295
  description:
296
296
  "Required for `add`. The pull request, as `owner/repo#123` or a GitHub PR URL. A ref that " +
297
- "cannot be parsed is REFUSED rather than stored a watcher that can never fire is worse than " +
298
- "no watcher, because you would come to rest believing you were covered.",
297
+ "cannot be parsed, or a PR the server's own `gh` cannot read, is REFUSED rather than stored " +
298
+ "a watcher that can never fire is worse than no watcher, because you would come to rest " +
299
+ "believing you were covered. A refusal names the reason; a transient one is worth one retry.",
299
300
  },
300
301
  for: {
301
302
  type: "string",
@@ -6,10 +6,11 @@
6
6
  // foreground agent blocks the worker's turn; a human interjection orphans it).
7
7
  // 2) STRIP `name`/`team_name` — setting either strands a nested dispatch (its result routes
8
8
  // wrong and never returns cleanly), so scrub both silently.
9
- // 3) AUTO-APPEND a repo-neutral ORCHESTRATION EPILOGUE so helpers return a useful handoff,
10
- // know how to reach their dispatcher mid-flight, do NOT fan out a layer of their own unless
11
- // their prompt asked for it, and collect a helper correctly when it did without imposing
12
- // build, test, git, compilation, or process-lifecycle policy on arbitrary repos.
9
+ // 3) AUTO-APPEND a short ORCHESTRATION EPILOGUE carrying only what a helper cannot discover on
10
+ // its own: that its final message is the return value, the `SendMessage({to: "main"})` upward
11
+ // channel, the own-file rule for the scratch directory, no fan-out of its own unless asked, and
12
+ // how a helper it DID dispatch is collected. It carries no handoff format and no build, test,
13
+ // git or process policy — the maintainer had the handoff-format doctrine cut on 2026-08-26.
13
14
  //
14
15
  // WHY NESTING IS DEFAULT-OFF (2026-08-04, maintainer's call): the epilogue used to speak about a
15
16
  // helper's own helper only in the conditional ("if you dispatch a helper of your own…"), which reads
@@ -45,10 +46,10 @@ import { readFileSync } from 'node:fs';
45
46
  const EPILOGUE = `
46
47
 
47
48
  ---
48
- [ORCHESTRATION EPILOGUE — auto-appended by the frizz worker dispatch hook] You are a helper sub-agent for a frizz worker. Your final message is the handoff: report your outcome/status; what you did; changed files, artifacts, and commit SHA when applicable; verification or evidence and its result; caveats or unresolved work; and the next action when one remains. A bare "done" or progress-only message is not a complete handoff.
49
+ [ORCHESTRATION EPILOGUE — auto-appended by the frizz worker dispatch hook] You are a helper sub-agent for a frizz worker. Your final message is the handoff your dispatcher reads: say what you did, what you verified, and what remains.
49
50
  The worker has a scratch directory (it will name the path if it wants your notes on disk). Write your OWN file there — never edit or delete a file another agent wrote, and never treat one shared document as yours to rewrite. Writing your own file there is Frizz coordination state, not a project deliverable or source edit, so it remains allowed when a delegated task limits your deliverable paths with phrases such as "write only <path>" or "do not modify the repo"; never classify it as unauthorized or roll it back. Other project files, including repository-root files, remain governed by your delegated authority; their location alone neither permits nor forbids editing. Do not edit other \`.frizz/\` state unless your prompt explicitly asks you to.
50
51
  You have an upward channel while you work: \`SendMessage({to: "main", summary: "<5-10 words>", message: "…"})\` delivers to your dispatcher. Use it when the dispatcher acting before you finish could change the outcome—for example, when you hit an unresolved blocker, complete a milestone another task needs, or discover that your instructions should change. Do not use it for routine progress updates.
51
- Do the work yourself: do NOT dispatch sub-agents of your own unless your dispatch prompt explicitly tells you to. You are already one prong of someone else's fan-out, and another layer below you buys little — it splits the context you were handed, buries the real work one level further from whoever reads the tree, and leaves you collecting a handoff instead of doing the task. A slice that feels large is still yours to work through in your own turn.
52
+ Do the work yourself: do NOT dispatch sub-agents of your own unless your dispatch prompt explicitly tells you to. You are already one prong of someone else's fan-out; a slice that feels large is still yours to work through in your own turn.
52
53
  If your prompt DOES ask you to dispatch a helper, its completion is delivered to you automatically. Never hand-roll a wait loop over a helper's transcript or \`.output\` path to decide whether it finished: that path is a SYMLINK, so \`stat\` without \`-L\` reports the link's own size (the length of its target path, ~150 bytes) and its frozen creation mtime, and the \`"type":"result"\` record is not reliably written — so a helper that is working hard reads as tiny, stale, and dead, and you will discard live work and redo it. Judge a helper only by its completion notification or the text it returns. Give it a \`description\` naming its narrower slice rather than restating your own, so the dispatch tree stays readable.`;
53
54
 
54
55
  /** @param {unknown} obj @returns {never} */
@@ -58,14 +58,12 @@
58
58
  {
59
59
  "matcher": "auto",
60
60
  "hooks": [
61
- { "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/precompact-instructions.mjs\"" },
62
61
  { "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/scratchpad.mjs\" --mode=precompact" }
63
62
  ]
64
63
  },
65
64
  {
66
65
  "matcher": "manual",
67
66
  "hooks": [
68
- { "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/precompact-instructions.mjs\"" },
69
67
  { "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/scratchpad.mjs\" --mode=precompact" }
70
68
  ]
71
69
  }
@@ -280,9 +280,11 @@ if (mode === 'session-start') {
280
280
  }
281
281
 
282
282
  // ── mode: precompact ─────────────────────────────────────────────────────────────────────────────
283
- // PLAIN STDOUT — joined with the other PreCompact hooks' stdout into the summarizer's
284
- // `Additional Instructions:`. Worded as an ordinary editorial note: precompact-instructions.mjs
285
- // records that a summarizer REFUSES instructions that read like prompt-hijacking.
283
+ // PLAIN STDOUT — handed to the summarizer as its `Additional Instructions:`. cc's usual
284
+ // `hookSpecificOutput` JSON would be read as literal instructions instead. Worded as an ordinary
285
+ // editorial note: a summarizer REFUSES instructions that read like prompt-hijacking (DECISIONS.md).
286
+ // This is the ONLY PreCompact hook the plugin registers — `precompact-instructions.mjs`, which also
287
+ // steered the summarizer, was deleted on 2026-08-26 as too opinionated.
286
288
  if (mode === 'precompact') {
287
289
  const files = listScratch();
288
290
  if (files.length === 0) process.exit(0);
@@ -8,10 +8,9 @@
8
8
  // frontmatter, no status field — a worker SIGNALS through its final message (fences), and anything that
9
9
  // must outlive its context window is an arrangement it makes for itself. This hook injects, on every
10
10
  // session start (startup/resume/clear/compact):
11
- // 1. `core` — a runtime re-grounding + pointer, NOT a second copy of the contract: the full worker
12
- // contract lives ONCE in the system prompt (workerPrompt.ts) the server injects at spawn. This
13
- // carries only what a static system prompt can't: the runtime scratch-directory PATH + an essential
14
- // signal-at-rest anchor + a pointer to the system-prompt contract.
11
+ // 1. `core` — a runtime POINTER, not a copy of the contract: the full worker contract lives ONCE in
12
+ // the system prompt (workerPrompt.ts) the server injects at spawn. This carries only what a
13
+ // static system prompt can't: the runtime scratch-directory PATH, and a one-line pointer.
15
14
  // 2. the SCRATCH DIRECTORY — `.frizz/threads/<session_id>/`, a folder the worker may use as it likes.
16
15
  // 3. on `compact` — a short re-grounding (compaction drops the deep model + this orientation).
17
16
  //
@@ -57,21 +56,23 @@ const scratch = sid
57
56
  ? '.frizz/threads/' + sid + '/'
58
57
  : '.frizz/threads/<session-id>/';
59
58
 
60
- // A RUNTIME re-grounding + pointer, NOT a second copy of the contract. The full worker contract
61
- // (signal fences, scratch-directory rules, sub-agent rules, the question handback) lives
62
- // ONCE in the system prompt frizz injects at spawn (workerPrompt.ts / loadWorkerPrompt) — which is
63
- // re-applied on every resume and survives compaction. This hook adds only what a static system prompt
64
- // CANNOT carry: the runtime-derived scratch-directory PATH, an essential signal-at-rest anchor, and (below)
65
- // the compaction re-read nudge, gh guidance, and the defensive cc-orchestrator off-sentinel.
59
+ // A RUNTIME pointer, NOT a copy of the contract. The full worker contract (signal fences,
60
+ // scratch-directory rules, sub-agent rules, the question handback, the stop criterion) lives ONCE in
61
+ // the system prompt frizz injects at spawn (workerPrompt.ts / loadWorkerPrompt) — re-applied on every
62
+ // resume, and it survives compaction. This hook adds only what a static system prompt CANNOT carry:
63
+ // the runtime-derived scratch-directory PATH, plus (below) the compaction re-read nudge and the
64
+ // auth-gated gh guidance.
65
+ //
66
+ // It used to restate the fence protocol, the stop criterion and the autonomy rule in full — ~4.4 KB
67
+ // (~1,100 tokens) on every startup, resume, clear AND compact, all of it already in the 42 KB system
68
+ // prompt. Trimmed 2026-08-26 (maintainer: "Definitely trim the session seed hook if it's fully
69
+ // repetitive") as part of cutting the per-session token overhead Frizz adds over a plain TUI session.
66
70
  const core =
67
- '⟦frizz worker contract⟧ You are a frizz WORKER driving EXACTLY ONE effort. Your FULL operating contract — the end-of-turn signal fences, scratch-directory rules, sub-agent rules, and the question handback — lives in your SYSTEM PROMPT; follow it there (this is a runtime re-grounding, not a second copy). The human + the frizz app are the ORCHESTRATOR; you drive ONE effort and never scan the board or touch other efforts. There is no orchestrator mode and no fleet to run: doing the work yourself is the default, and you dispatch a sub-agent only when the work genuinely decomposes into independent prongs.\n' +
68
- 'SCRATCH DIRECTORY (OPTIONAL): `' + scratch + '` — a folder kept FOR YOU: any files you like, no format expected, nothing in it read automatically, and never a substitute for doing the work. A single direct task usually needs nothing. On a long effort write the doc you would want if you lost your context — the approach, what you rejected, the human\'s decisions — AS YOU GO, mid-work, then KEEP WORKING, and arm mcp__frizz__recurring_prompt with post_compaction: true and a prompt LINKING that file, because the arming is what brings it back. Give each sub-agent its OWN file rather than a shared one.\n' +
69
- 'DO NOT REST WHILE THE INSTRUCTION HAS PARTS LEFT — finish them in THIS turn; a milestone, a green test run and a long turn are none of them stopping points, and announcing the next step or writing it into a scratch file is not doing it.\n' +
70
- 'ALWAYS SIGN OFF WITH A FENCE, per the fence rules in your system prompt. A rest with NO fence is not a handoff — it is an item nobody can triage, and frizz will tell you so. ```done only when the effort\'s real work is COMPLETE (code LANDED on the mainline — an open PR is NOT done, park it on ```awaiting until it MERGES) and is a DISMISSAL (its card files the thread away where nobody looks again), so if the thread points at future work AT ALL — a pre-fix investigation, a live code-change discussion, follow-up work you DISCOVERED even when someone else will do it — ask a ```question instead, and uncertain is not done; a verdict that ends in something the HUMAN must now do (post this comment, merge or decline, pick one of these) is a ```question carrying your recommendation as option A, never a done card, because a draft you wrote but did not send is filed away with the thread; when your OWN mandate is complete and what is left is a separable effort, DO it first — dispatch a sub-agent, whose result comes BACK to you, so it lands on YOUR card — and ASK second; mcp__frizz__spawn_thread is the LAST resort, for work that genuinely cannot ride on your card, because a spawned thread reports only to the human and nothing it learns returns to you or its siblings; the ONE exception is a planning session whose plan file is fully written and persisted, because that artifact outlives the thread; ```awaiting parks your OWN background work — a shell, a sub-agent, an armed timer, a registered PR watcher — never CI/releases/merge progression (those stay ACTIVE), and never a person: waiting on a person is a ```question; ```question is the operator ask. Waiting on your own background shell? Your shells and sub-agents are watched AUTOMATICALLY — frizz wakes you when one finishes, fence or no fence. NAME it in the fence\'s YAML frontmatter anyway — plural keys taking lists (`shells: [<id>]`, `agents:`, `timers:`, `prs:`) plus a required `for:` duration, then `---` and your prose — and rest: that is what lets you stop without frizz asking you for a handoff, and what shows the human what you are waiting for. Frizz checks every name against what you actually have running. Keep the write-up SHORT: 1-3 sentences, then bullets starting with a **bolded verb phrase**. The fence and the prose above it are TWO SURFACES, not one message written twice — the card is the ledger of what shipped, the prose is only what a ledger cannot hold, and a sentence that would read the same in either belongs in exactly one. And a done message says what HAPPENED: delete every dangling "one thing to carry forward" or "a follow-up could" — do it, spawn it onto its own card, ask about it, or DROP it, and if it is not worth a card it is not worth a sentence.\n' +
71
- 'DECIDE rather than ask: anything derivable from the code, the conventions, or ordinary engineering judgment is YOURS to settle — asking permission to do the work you were dispatched to do is not a question, it is the job. Reserve the operator for the irreversible and the genuinely human-owned.';
71
+ '⟦frizz worker contract⟧ You are a frizz WORKER driving EXACTLY ONE effort. Your FULL operating contract — the end-of-turn signal fences (```done / ```awaiting / ```question), the scratch-directory rules, the sub-agent rules, the question handback and the stop criterion — lives in your SYSTEM PROMPT; follow it there. Always sign off with a fence.\n' +
72
+ 'SCRATCH DIRECTORY (OPTIONAL): `' + scratch + '` — a folder kept FOR YOU, nothing in it read automatically, never a substitute for doing the work. Give each sub-agent its OWN file rather than a shared one.';
72
73
 
73
74
  const grounding =
74
- '⟦frizz worker re-grounding (post-compaction)⟧ Context was just compacted. You are still the frizz worker for effort `' + thread + '` — read whatever you left yourself in `' + scratch + '` NOW to recover your working state and to-do list before asserting anything, and re-read any code before claiming how it is structured. Signal at rest through your FINAL MESSAGE, always with a fence — a fenceless rest is an item nobody can triage: ```done queues a checked completion until Archive and is a DISMISSAL — completed work only, and never when the thread still points at future work (a pre-fix investigation, a live code-change discussion); use a question or bare rest; ```awaiting parks only your own background work, an armed timer, or a registered PR watcher (which wakes on any new review/comment, bot or human) — named in YAML frontmatter with plural list keys (`shells:`/`agents:`/`timers:`/`prs:`) plus a `for:` duration; waiting on a person is a ```question; ```question is the explicit higher-priority operator ask. CI/releases/merge progression stay active through Monitor/background Bash.';
75
+ '⟦frizz worker re-grounding (post-compaction)⟧ Context was just compacted. You are still the frizz worker for effort `' + thread + '` — read whatever you left yourself in `' + scratch + '` NOW to recover your working state and to-do list before asserting anything, and re-read any code before claiming how it is structured. Your system prompt still carries the full contract; sign off with a fence as it says.';
75
76
 
76
77
  // AUTH-GATED gh guidance — teach the worker to use `gh` well, but ONLY when signed in.
77
78
  // Shell `gh auth status --active`: exit 0 = an active gh account is authenticated. The whole gate is
@@ -84,7 +85,6 @@ const ghBlock =
84
85
  '• READ freely: `gh issue view N -R OWNER/REPO --comments`, `gh pr view N`, `gh pr diff N`, `gh pr checks N`, `gh run list`/`gh run view`, `gh api repos/OWNER/REPO/…`. Prefer `--json <fields>` over scraping human text.\n' +
85
86
  '• SEARCH across the repo (and GitHub) with `gh search issues`/`gh search prs` when hunting related work, duplicates, or prior art.\n' +
86
87
  '• READ-ONLY BOUNDARY: never comment, label, assign, close, review, approve, or merge — no mutation of any kind — UNLESS the human explicitly asks in this session. Default to producing your findings/review as your final message, not as a GitHub post.\n' +
87
- '• TOON: pipe LARGE, FLAT `gh … --json` output through `toon` when `command -v toon` finds it. Skip it when unavailable, for tiny payloads, or for deeply-nested output — the savings are noise and nesting defeats tabularization.\n' +
88
88
  'Load the `frizz:gh` skill for the full playbook (recipes + explicit project-local monitor selection + native Monitor/background-Bash CI/PR watches).';
89
89
 
90
90
  let ghAuthed = false;
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: gh
3
- description: The gh-CLI playbook for a frizz worker signed into GitHub (invoke as frizz:gh). Load this whenever your effort touches GitHub — reading or triaging an issue or PR, reviewing a diff, checking CI/release status, or searching issues/PRs — to use `gh` eagerly and correctly: the read-vs-write boundary (never comment/label/close/merge unless the human asks), optional toon use for large JSON, concrete read recipes, and active Monitor/background-Bash CI/PR watches. Only meaningful when you are signed in (`gh auth status --active` exit 0); the session-seed hook injects a pointer here when you are.
4
- version: 0.1.1
3
+ description: The gh-CLI playbook for a frizz worker signed into GitHub (invoke as frizz:gh). Load this whenever your effort touches GitHub — reading or triaging an issue or PR, reviewing a diff, checking CI/release status, or searching issues/PRs — to use `gh` eagerly and correctly: the read-vs-write boundary (never comment/label/close/merge unless the human asks), concrete read recipes, and active Monitor/background-Bash CI/PR watches. Only meaningful when you are signed in (`gh auth status --active` exit 0); the session-seed hook injects a pointer here when you are.
4
+ version: 0.1.2
5
5
  metadata:
6
6
  internal: true
7
7
  ---
@@ -10,7 +10,7 @@ metadata:
10
10
 
11
11
  You are a **frizz worker** and you are **signed into the `gh` CLI in a GitHub repo** (the session-seed hook confirmed `gh auth status --active` before pointing you here). `gh` is the fastest path to issue / PR / CI / release context — reach for it before guessing, and prefer it over scraping the web UI or reasoning from memory.
12
12
 
13
- This skill is the full playbook the injected `⟦gh available⟧` block summarizes: the **read-vs-write boundary**, optional **toon** use for large JSON, concrete **read recipes**, and how to keep a **CI/PR watch** active until the next actionable event.
13
+ This skill is the full playbook the injected `⟦gh available⟧` block summarizes: the **read-vs-write boundary**, concrete **read recipes**, and how to keep a **CI/PR watch** active until the next actionable event.
14
14
 
15
15
  ## The one hard rule — READ freely, WRITE only when asked
16
16
 
@@ -23,20 +23,6 @@ This skill is the full playbook the injected `⟦gh available⟧` block summariz
23
23
 
24
24
  There is no server-side enforcement of this; the boundary is yours to hold.
25
25
 
26
- ## toon — pipe LARGE, FLAT gh JSON through the shim
27
-
28
- `toon` (Token-Oriented Object Notation) losslessly re-encodes JSON ~30–40% smaller for LLM context. Use it only when a `gh … --json` result you're reading into YOUR context is **large and flat** (a list page: `gh issue list`, `gh pr list`, `gh search`, `gh api` list endpoints) and `command -v toon` succeeds. It is optional: do not install it or assume a home-directory-specific location.
29
-
30
- ```bash
31
- if command -v toon >/dev/null 2>&1; then
32
- gh issue list -R OWNER/REPO --json number,title,url,updatedAt --limit 50 | toon
33
- else
34
- gh issue list -R OWNER/REPO --json number,title,url,updatedAt --limit 50
35
- fi
36
- ```
37
-
38
- **Skip toon** for tiny payloads (a handful of fields, one item) and for **deeply-nested** JSON (`reactionGroups`, review threads, nested files) — nesting defeats tabularization, so the savings collapse to noise and you add a parse tax for yourself. A single `gh pr view N --json …` is small — read it raw.
39
-
40
26
  ## Read recipes
41
27
 
42
28
  Always scope with `-R OWNER/REPO` so a command is dir-independent, and prefer `--json <fields>` (+ `-q <jq>`) so you pull exactly what you need.
@@ -52,7 +38,7 @@ gh issue list -R OWNER/REPO --search "sort:reactions-desc is:open" --json number
52
38
  **PRs + diffs**
53
39
  ```bash
54
40
  gh pr view N -R OWNER/REPO --json title,body,state,labels,files,additions,deletions,url
55
- gh pr diff N -R OWNER/REPO # the unified diff — pipe through toon only if HUGE and you just need shape
41
+ gh pr diff N -R OWNER/REPO # the unified diff
56
42
  gh pr checks N -R OWNER/REPO # CI check rollup for the PR
57
43
  gh pr view N -R OWNER/REPO --comments # review threads + conversation
58
44
  ```
@@ -97,7 +83,7 @@ Use search to find duplicates, related work, and prior art before you conclude s
97
83
  **Raw API** for anything the porcelain doesn't cover:
98
84
  ```bash
99
85
  gh api repos/OWNER/REPO/commits/SHA/check-runs --jq '.check_runs[] | {name, conclusion}'
100
- gh api "repos/OWNER/REPO/issues?state=open&labels=bug&per_page=50" | { command -v toon >/dev/null 2>&1 && toon || cat; }
86
+ gh api "repos/OWNER/REPO/issues?state=open&labels=bug&per_page=50" --jq '.[] | {number, title, html_url}'
101
87
  ```
102
88
 
103
89
  ## Keep GitHub automation active