frizz 0.2.0 → 0.3.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.
- package/README.md +17 -17
- package/dist/claude-agent-broker.js +63 -23
- package/dist/dev-child.js +6877 -4459
- package/dist/frizz.js +654 -529
- package/package.json +6 -2
- package/runtime/cc-worker/.claude-plugin/plugin.json +1 -1
- package/runtime/cc-worker/DECISIONS.md +64 -4
- package/runtime/cc-worker/bin/frizz-mcp.mjs +494 -57
- package/runtime/cc-worker/hooks/agent-dispatch.mjs +1 -1
- package/runtime/cc-worker/hooks/deny-plan.mjs +1 -1
- package/runtime/cc-worker/hooks/hooks.json +0 -7
- package/runtime/cc-worker/hooks/precompact-instructions.mjs +39 -28
- package/runtime/cc-worker/hooks/scratchpad.mjs +142 -169
- package/runtime/cc-worker/hooks/session-seed.mjs +16 -15
- package/runtime/cc-worker/skills/waits/SKILL.md +2 -2
- package/web-dist/apple-touch-icon.png +0 -0
- package/web-dist/assets/{TerminalPane-ROKHp1ib.js → TerminalPane-CTdetDJJ.js} +2 -2
- package/web-dist/assets/{abnfDiagram-VRR7QNED-DcpdhBs3.js → abnfDiagram-VRR7QNED-BDKrjCMs.js} +1 -1
- package/web-dist/assets/architecture-TIHT7OUA-ChUMo004.js +1 -0
- package/web-dist/assets/{architectureDiagram-ZJ3FMSHR-CUAKf0mn.js → architectureDiagram-ZJ3FMSHR-BJebpUUM.js} +1 -1
- package/web-dist/assets/{blockDiagram-677ZJIJ3-BPwpJIzx.js → blockDiagram-677ZJIJ3-BNbuk25k.js} +1 -1
- package/web-dist/assets/{c4Diagram-LMCZKHZV-1lptuHzZ.js → c4Diagram-LMCZKHZV-lCfyotdU.js} +1 -1
- package/web-dist/assets/channel-pr7r6raB.js +1 -0
- package/web-dist/assets/{chunk-32BRIVSS-CFR9AKjY.js → chunk-32BRIVSS-DP72SEkr.js} +1 -1
- package/web-dist/assets/{chunk-52WLFC77-CM9uct7m.js → chunk-52WLFC77-DxO3gN-p.js} +1 -1
- package/web-dist/assets/{chunk-C7G6YPKG-DiveJARw.js → chunk-C7G6YPKG-BXFx9Vlr.js} +1 -1
- package/web-dist/assets/{chunk-EX3LRPZG-BE1CBw8F.js → chunk-EX3LRPZG-CR3sHpPf.js} +1 -1
- package/web-dist/assets/{chunk-FWX5IMBZ-DL42uXiO.js → chunk-FWX5IMBZ-CJ8L__oG.js} +2 -2
- package/web-dist/assets/{chunk-HOUHSVGY-DPhJWgDw.js → chunk-HOUHSVGY-BCl3JSWr.js} +1 -1
- package/web-dist/assets/{chunk-ICXQ74PX-CwYy-6AP.js → chunk-ICXQ74PX-CZxFMci1.js} +1 -1
- package/web-dist/assets/{chunk-MOJQB5TN-Ds5I9wxq.js → chunk-MOJQB5TN-Ck3_47dB.js} +1 -1
- package/web-dist/assets/{chunk-OGEWGWER-DHiZJwQD.js → chunk-OGEWGWER-CVXjES-F.js} +1 -1
- package/web-dist/assets/{chunk-PUDLZKDR-B-eyQTsF.js → chunk-PUDLZKDR-JjrVgaR7.js} +1 -1
- package/web-dist/assets/{chunk-Q4XR5HBZ-DK7dB3Ti.js → chunk-Q4XR5HBZ-C5YMRAQ0.js} +1 -1
- package/web-dist/assets/{chunk-V7JOEXUC-Dn59m74L.js → chunk-V7JOEXUC-DK0mfUHU.js} +1 -1
- package/web-dist/assets/{chunk-VAUOI2AC-DK7x36hd.js → chunk-VAUOI2AC-BKBntpid.js} +1 -1
- package/web-dist/assets/{chunk-VR4S4FIN-D7-CI3Yl.js → chunk-VR4S4FIN-zgE1dG6U.js} +1 -1
- package/web-dist/assets/{chunk-WYO6CB5R-B3l-mLCs.js → chunk-WYO6CB5R-CZhh1IBq.js} +1 -1
- package/web-dist/assets/{chunk-ZGVPDNZ5-Dobxlxie.js → chunk-ZGVPDNZ5-CrNjIEem.js} +1 -1
- package/web-dist/assets/classDiagram-OUVF2IWQ-CvGbPMn_.js +1 -0
- package/web-dist/assets/classDiagram-v2-EOCWNBFH-CvGbPMn_.js +1 -0
- package/web-dist/assets/{cynefin-VYW2F7L2-Dh7RuEUJ.js → cynefin-VYW2F7L2-Ca_BPfTG.js} +1 -1
- package/web-dist/assets/{cynefinDiagram-TSTJHNR4-ClPi2mZZ.js → cynefinDiagram-TSTJHNR4-CsINQf6g.js} +1 -1
- package/web-dist/assets/{dagre-VKFMJZFB-52_WP1QV.js → dagre-VKFMJZFB-CE0DYMFy.js} +1 -1
- package/web-dist/assets/{diagram-FQU43EPY-D_1zVsTL.js → diagram-FQU43EPY-BqTduEYE.js} +1 -1
- package/web-dist/assets/{diagram-G47NLZAW-CdZxuGUy.js → diagram-G47NLZAW-Cho718s6.js} +1 -1
- package/web-dist/assets/{diagram-NH7WQ7WH-C8pSFu0P.js → diagram-NH7WQ7WH-D0Z8t9UC.js} +1 -1
- package/web-dist/assets/{diagram-OA4YK3LP-C5bjZLre.js → diagram-OA4YK3LP-CBacyeDx.js} +1 -1
- package/web-dist/assets/{diagram-WEI45ONY-Bxzhiuzn.js → diagram-WEI45ONY-CozpXa4j.js} +1 -1
- package/web-dist/assets/{ebnfDiagram-CCIWWBDH-g-Z0J2wP.js → ebnfDiagram-CCIWWBDH-ba4NbQQo.js} +1 -1
- package/web-dist/assets/{erDiagram-Q63AITRT-DVNkgIHp.js → erDiagram-Q63AITRT-B3BciOYa.js} +1 -1
- package/web-dist/assets/eventmodeling-45OFAUF4-DKmyo-jd.js +1 -0
- package/web-dist/assets/flowDiagram-23GEKE2U-DluCBvT4.js +1 -0
- package/web-dist/assets/{ganttDiagram-NO4QXBWP-_71pQYEK.js → ganttDiagram-NO4QXBWP-lPmrRit4.js} +1 -1
- package/web-dist/assets/{gitGraph-TEB2WS4Q-ChIZiGZS.js → gitGraph-TEB2WS4Q-BjyclOq0.js} +1 -1
- package/web-dist/assets/{gitGraphDiagram-IHSO6WYX-DCHAFI0l.js → gitGraphDiagram-IHSO6WYX-pzeb4Yrw.js} +1 -1
- package/web-dist/assets/index-BQtjYMpV.css +1 -0
- package/web-dist/assets/index-CLW1Q49U.js +360 -0
- package/web-dist/assets/{info-DKCQHKI2-BW-n_T1j.js → info-DKCQHKI2-Bwycegvf.js} +1 -1
- package/web-dist/assets/{infoDiagram-FWYZ7A6U-CgDYsKi9.js → infoDiagram-FWYZ7A6U-BCvRGj_5.js} +1 -1
- package/web-dist/assets/{ishikawaDiagram-FXEZZL3T-ClzGNt9N.js → ishikawaDiagram-FXEZZL3T-Ofw1RMj3.js} +1 -1
- package/web-dist/assets/{journeyDiagram-5HDEW3XC-DSCQxkHC.js → journeyDiagram-5HDEW3XC-C5ROwFio.js} +1 -1
- package/web-dist/assets/{kanban-definition-HUTT4EX6-CdrdX9N8.js → kanban-definition-HUTT4EX6-YLPLkpeT.js} +1 -1
- package/web-dist/assets/{line-ha38Dc-1.js → line-KtkNqRgI.js} +1 -1
- package/web-dist/assets/{mermaid-parser.core-Z4uMcpip.js → mermaid-parser.core-D_FfqBe7.js} +3 -3
- package/web-dist/assets/{mermaid.core-iZRq3hbu.js → mermaid.core-Ffv8anVf.js} +3 -3
- package/web-dist/assets/{mindmap-definition-LN4V7U3C-DmhInJO_.js → mindmap-definition-LN4V7U3C-B2jj4vfm.js} +1 -1
- package/web-dist/assets/{packet-7NZHBO7P-DBPB36Kl.js → packet-7NZHBO7P-BjmWHwra.js} +1 -1
- package/web-dist/assets/{pegDiagram-2B236MQR-CAH3ljfj.js → pegDiagram-2B236MQR-Dq3iJDyq.js} +1 -1
- package/web-dist/assets/{pie-RZYD4A2V-_h_eX4Ca.js → pie-RZYD4A2V-jBbH1lv9.js} +1 -1
- package/web-dist/assets/{pieDiagram-ENE6RG2P-DFBPus8j.js → pieDiagram-ENE6RG2P-C3ETW9lq.js} +1 -1
- package/web-dist/assets/{quadrantDiagram-ABIIQ3AL-DMvOCjt8.js → quadrantDiagram-ABIIQ3AL-DItSmme7.js} +1 -1
- package/web-dist/assets/{radar-I7S5WNFK-2EzoPHEZ.js → radar-I7S5WNFK-6ey6crgP.js} +1 -1
- package/web-dist/assets/{railroad-3IZDKUUU-BPJnn-hm.js → railroad-3IZDKUUU-Cii-Mn0E.js} +1 -1
- package/web-dist/assets/railroad-abnf-AHOZXSZD-U_vb4BrX.js +1 -0
- package/web-dist/assets/railroad-ebnf-EBAXGLYW-BIHG7gNU.js +1 -0
- package/web-dist/assets/railroad-peg-LSFZ7HO6-Cpd9r-tB.js +1 -0
- package/web-dist/assets/{railroadDiagram-RFXS5EU6-DKq5FagA.js → railroadDiagram-RFXS5EU6-M363ils_.js} +1 -1
- package/web-dist/assets/{requirementDiagram-TGXJPOKE-BJ5tGazp.js → requirementDiagram-TGXJPOKE-CTs2_V6T.js} +1 -1
- package/web-dist/assets/{sankeyDiagram-HTMAVEWB-XSJjcBhX.js → sankeyDiagram-HTMAVEWB-QTLLcDPD.js} +1 -1
- package/web-dist/assets/{sequenceDiagram-DBY2YBRQ-CBb8emSe.js → sequenceDiagram-DBY2YBRQ-Bxw9Tr6e.js} +1 -1
- package/web-dist/assets/{stateDiagram-2N3HPSRC-DDfRW94V.js → stateDiagram-2N3HPSRC-BecB6roG.js} +1 -1
- package/web-dist/assets/stateDiagram-v2-6OUMAXLB-JXw9T96l.js +1 -0
- package/web-dist/assets/{swimlanes-5IMT3BWC-DvRYbkZi.js → swimlanes-5IMT3BWC-COiYgS0w.js} +1 -1
- package/web-dist/assets/swimlanesDiagram-G3AALYLV--1Wv7FQQ.js +8 -0
- package/web-dist/assets/{timeline-definition-FHXFAJF6-BNUa_DwI.js → timeline-definition-FHXFAJF6-Ci22coeH.js} +1 -1
- package/web-dist/assets/{treeView-QDETBFTQ-I6-IW6nJ.js → treeView-QDETBFTQ-4DW35czh.js} +1 -1
- package/web-dist/assets/{treemap-6X3UGDF4-CWWmEUYJ.js → treemap-6X3UGDF4-Dq_-Z6-Y.js} +1 -1
- package/web-dist/assets/{vennDiagram-L72KCM5P-DTDrPGLk.js → vennDiagram-L72KCM5P-CHQSIEYq.js} +1 -1
- package/web-dist/assets/{wardley-OPB4EBWU-CNsdgXXA.js → wardley-OPB4EBWU-Bwlh7HCY.js} +1 -1
- package/web-dist/assets/{wardleyDiagram-EHGQE667-YE0tq3Kh.js → wardleyDiagram-EHGQE667-DctjuPYn.js} +1 -1
- package/web-dist/assets/{xychartDiagram-FW5EYKEG-D0ofMX8C.js → xychartDiagram-FW5EYKEG-ZoIGosv8.js} +1 -1
- package/web-dist/favicon-16.png +0 -0
- package/web-dist/favicon-32.png +0 -0
- package/web-dist/favicon.svg +17 -61
- package/web-dist/icon-192.png +0 -0
- package/web-dist/icon-512.png +0 -0
- package/web-dist/icon-maskable-512.png +0 -0
- package/web-dist/index.html +19 -8
- package/web-dist/manifest.webmanifest +3 -3
- package/runtime/cc-worker/hooks/scratchpad-stop.mjs +0 -125
- package/runtime/cc-worker/skills/handoff/SKILL.md +0 -209
- package/web-dist/assets/architecture-TIHT7OUA-CAviNivx.js +0 -1
- package/web-dist/assets/channel-CqKDIFQF.js +0 -1
- package/web-dist/assets/classDiagram-OUVF2IWQ-B_-6iXYY.js +0 -1
- package/web-dist/assets/classDiagram-v2-EOCWNBFH-B_-6iXYY.js +0 -1
- package/web-dist/assets/eventmodeling-45OFAUF4-MpmeH5YZ.js +0 -1
- package/web-dist/assets/flowDiagram-23GEKE2U-D-QgjjhF.js +0 -1
- package/web-dist/assets/index-w4v-GZEc.js +0 -358
- package/web-dist/assets/index-zyi22LPz.css +0 -1
- package/web-dist/assets/railroad-abnf-AHOZXSZD-YeUoiySk.js +0 -1
- package/web-dist/assets/railroad-ebnf-EBAXGLYW-Ddw1SuGG.js +0 -1
- package/web-dist/assets/railroad-peg-LSFZ7HO6-Dd8BOGeW.js +0 -1
- package/web-dist/assets/stateDiagram-v2-6OUMAXLB-hc41W5Lx.js +0 -1
- package/web-dist/assets/swimlanesDiagram-G3AALYLV-BZyGdgSG.js +0 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "frizz",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A local web UI for running many coding agents at once",
|
|
6
6
|
"keywords": [
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"typecheck": "tsc -b packages/shared packages/rpc packages/server . && pnpm --filter @frizz/web typecheck",
|
|
41
41
|
"test": "nub --test --test-force-exit 'board/*.test.mjs' 'scripts/**/*.test.mjs' 'src/**/*.test.ts' 'packages/shared/src/**/*.test.ts' 'packages/server/src/**/*.test.ts' 'packages/web/src/**/*.test.ts'",
|
|
42
42
|
"prepack": "node ./scripts/prepare-package.mjs && node ./scripts/build-package.mjs && node ./scripts/publish-manifest.mjs --strip",
|
|
43
|
-
"postpack": "node ./scripts/publish-manifest.mjs --restore"
|
|
43
|
+
"postpack": "node ./scripts/publish-manifest.mjs --restore && node ./scripts/prepare-package.mjs --clean"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@parcel/watcher": "^2.5",
|
|
@@ -53,6 +53,10 @@
|
|
|
53
53
|
"typescript": "^5.7"
|
|
54
54
|
},
|
|
55
55
|
"pnpm": {
|
|
56
|
+
"overrides": {
|
|
57
|
+
"react": "19.2.7",
|
|
58
|
+
"react-dom": "19.2.7"
|
|
59
|
+
},
|
|
56
60
|
"onlyBuiltDependencies": [
|
|
57
61
|
"node-pty",
|
|
58
62
|
"@parcel/watcher",
|
|
@@ -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
|
|
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.",
|
|
4
4
|
"version": "0.1.10",
|
|
5
5
|
"author": { "name": "Colin McDonnell" },
|
|
6
6
|
"homepage": "https://github.com/colinhacks/frizz",
|
|
@@ -30,8 +30,8 @@ what was ported from the orchestrator `cc/` plugin, what was dropped, and why.
|
|
|
30
30
|
| Hook | Event | Ported from | What it does for a worker |
|
|
31
31
|
| --- | --- | --- | --- |
|
|
32
32
|
| `session-seed.mjs` | SessionStart (startup/resume/clear/compact) | cc `session-seed.mjs` | Injects the single-thread worker contract + the bound slug + its file path; re-grounds on compact. Also writes cc's `off` sentinel defensively (see interplay). |
|
|
33
|
-
| `precompact-instructions.mjs` | PreCompact (auto/manual) | new — no cc equivalent | Steers WHAT SURVIVES compaction: emits an editorial brief asking the summarizer to preserve the high-level approach (plan, alternatives rejected, rationale) at high fidelity, plus a closing "Re-grounding before continuing:" section naming the
|
|
34
|
-
| `scratchpad.mjs` | SessionStart (startup/resume/clear/compact) + PreCompact (auto/manual) + UserPromptSubmit + PostToolUse | new — no cc equivalent | Keeps
|
|
33
|
+
| `precompact-instructions.mjs` | PreCompact (auto/manual) | new — no cc equivalent | Steers WHAT SURVIVES compaction: emits an editorial brief asking the summarizer to preserve the high-level approach (plan, alternatives rejected, rationale) at high fidelity, plus a closing "Re-grounding before continuing:" section naming the thread's scratch-directory path and the files to re-read. **PLAIN STDOUT is the channel** — cc's usual `hookSpecificOutput` JSON would be handed to the summarizer as its literal instructions. Skips sub-agent contexts (the derived scratch-directory path is only guaranteed for the top-level worker). |
|
|
34
|
+
| `scratchpad.mjs` | SessionStart (startup/resume/clear/compact) + PreCompact (auto/manual) + UserPromptSubmit + PostToolUse | new — no cc equivalent | Keeps a worker aware of its per-thread scratch DIRECTORY (`.frizz/threads/<sid>/`). `--mode=session-start` NAMES the files in it on the context-losing sources (compact/resume/clear) — a listing, never their content — and otherwise teaches the arrangement (write a doc, then arm `post_compaction`); `--mode=precompact` (**plain stdout**) tells the summarizer those files exist so it carries their paths forward; `--mode=nudge` fires on BOTH UserPromptSubmit and PostToolUse (mid-turn — the one that matters for long autonomous turns) once context has grown past `STALE_TOKENS` since the last write. Both nudge channels share one state file, so mid-turn firing does not multiply reminders. NOT gated on `FRIZZ_THREAD`; `--via=project` marks the repo-local registration and defers to this one inside a frizz worker. |
|
|
35
35
|
| `agent-dispatch.mjs` | PreToolUse(Agent) | cc `agent-dispatch.mjs` | Enforces `run_in_background:true`, strips `name`/`team_name`, appends a worker-flavored orchestration epilogue. |
|
|
36
36
|
| `bash-background.mjs` | PreToolUse(Bash) | new | Denies a local shell job that escapes through `&` without a later `wait` or EXIT trap, including one hidden inside a command-position `bash -c '…'`. Shell job control bypasses Claude's task registry, so Frizz cannot track or wake it; self-contained probe concurrency, and a wrapper handed to another program (`ssh`/`docker run`/`limactl shell`), remain allowed. |
|
|
37
37
|
| `agent-bind.mjs` | PostToolUse(Agent) | cc `agent-bind.mjs` (verbatim behavior) | Records `agentId → thread` into `.frizz/.agent-bindings.jsonl` in cc's exact format, so a worker's THREAD-tagged helper renders on the frizz board's per-thread liveness. |
|
|
@@ -273,10 +273,22 @@ defect, and arguably correct: an explicit human rule should beat a blanket polic
|
|
|
273
273
|
|
|
274
274
|
MARKER: `<stateDir>/perm-requests/<slug>.json` now carries `decision` / `rule` / `reason` / `command`
|
|
275
275
|
alongside the original fields. The tailer treats ONLY a deferred request as a human block (an
|
|
276
|
-
auto-resolved one must never card as "Needs you"), and surfaces the last
|
|
277
|
-
the only durable record an approval leaves anywhere, since allows are never written to the transcript.
|
|
276
|
+
auto-resolved one must never card as "Needs you"), and surfaces the last DENIAL as `permPolicy`.
|
|
278
277
|
A marker with no `decision` (an older plugin build) still blocks exactly as before.
|
|
279
278
|
|
|
279
|
+
APPROVALS ARE NOT SURFACED — reversed 2026-08-07. The tailer originally retained allows too, on the
|
|
280
|
+
reasoning that an approval leaves no other durable record (Claude Code renders "Allowed by
|
|
281
|
+
PermissionRequest hook" in the pane and writes nothing to the transcript), and Chat rendered them as
|
|
282
|
+
one quiet `Auto-approved <command> · rule <name>` line. The flaw was that `permPolicy` has no CLEAR:
|
|
283
|
+
the line stuck to the bottom of the thread permanently, so one routine `git status --short` read as
|
|
284
|
+
the thread's standing condition long after the turn that ran it (maintainer: *"This message just
|
|
285
|
+
showed up randomly, and now it's stuck showing up in the thread forever … it's fucking useless"*).
|
|
286
|
+
Nothing was blocked and nobody was waiting, so the visibility it bought was worth less than the
|
|
287
|
+
permanent noise. Denials keep the card: they are rare, they changed what the worker could do, and the
|
|
288
|
+
refusal also lands in the transcript, so the card is a pointer to something real rather than the only
|
|
289
|
+
copy of it. If approval visibility is ever wanted again it needs an EXPIRY (or a per-turn scope) —
|
|
290
|
+
re-adding the sticky line is not the fix.
|
|
291
|
+
|
|
280
292
|
VERIFICATION: `scripts/verify-perm-marker.mjs` runs the REAL hook the way Claude Code does and
|
|
281
293
|
asserts every branch. The allow path was additionally driven against a REAL interactive `claude` (it
|
|
282
294
|
cannot be exercised under `claude -p`, where PermissionRequest hooks do not fire).
|
|
@@ -1023,3 +1035,51 @@ The rule now LEADS both child-facing epilogues, with the collection paragraph ke
|
|
|
1023
1035
|
This is a PROMPT-level default, deliberately NOT the hook-level depth-2 DENY rejected on 2026-07-31 as too blunt: a dispatcher that genuinely wants a prong fanned out says so in the prompt and the child dispatches, unmodified. Also left alone: `workerPrompt.ts` — the root contract already authorizes fan-out *"when work genuinely decomposes"*, and the root is the one agent whose fan-out is wanted.
|
|
1024
1036
|
|
|
1025
1037
|
Pinned by a new test in `agent-dispatch-hook.test.ts` (the lead-with-the-default wording plus the re-hinged conditional) and one in `scratchpad-hook.test.ts` (the codex block).
|
|
1038
|
+
|
|
1039
|
+
|
|
1040
|
+
## 2026-08-06: the canonical scratchpad is DELETED — a free scratch directory, and compaction recovery moves to the recurring prompt
|
|
1041
|
+
|
|
1042
|
+
Frizz provisioned one canonical `scratch.md` per thread and a `SessionStart` hook spliced its HEAD into
|
|
1043
|
+
the context window after every compaction. The argument for the injection was sound and is worth
|
|
1044
|
+
restating, because it is what any replacement has to answer: a bare "remember to read your scratchpad"
|
|
1045
|
+
routes recovery through a decision the model can skip, which is exactly the failure the pad existed to
|
|
1046
|
+
prevent.
|
|
1047
|
+
|
|
1048
|
+
It still lost, on three counts. It made a MAINTAINED FILE the price of admission for every worker,
|
|
1049
|
+
including the ones whose whole task was one edit. It needed a merge-only contract per backend to stop
|
|
1050
|
+
sub-agents clobbering the one document — an epilogue in `agent-dispatch.mjs`, a `--mode=subagent-start`
|
|
1051
|
+
epilogue for codex, a legend line in every provisioned pad, and a paragraph of the worker contract, all
|
|
1052
|
+
of it policing a hazard rather than removing it. And the injection was INVISIBLE to the operator, who
|
|
1053
|
+
could neither see what their worker would be handed nor change it.
|
|
1054
|
+
|
|
1055
|
+
**What replaced it, maintainer's design:** the thread gets `.frizz/threads/<session-id>/` as a free-form
|
|
1056
|
+
scratch DIRECTORY — nothing provisioned into it, no reserved filename, no format — and compaction
|
|
1057
|
+
recovery moves to `mcp__frizz__recurring_prompt`'s new POST-COMPACTION trigger (scheduler SOURCE 7,
|
|
1058
|
+
landed the same day). The worker writes whatever doc it likes and LINKS it in the prompt; frizz re-sends
|
|
1059
|
+
that text the instant the context is summarized away. Durable in SQLite, visible and editable in the
|
|
1060
|
+
thread footer, and the worker chooses what it gets back.
|
|
1061
|
+
|
|
1062
|
+
The sub-agent story falls out for free: **one file per writer**. There is nothing to merge, so there is
|
|
1063
|
+
nothing to clobber, and the entire merge contract is deleted rather than reworded. Both child epilogues
|
|
1064
|
+
now say "write your OWN file; never edit or delete a file another agent wrote". The delegated-authority
|
|
1065
|
+
carve-out ("write only <path>" must not forbid the child's own coordination file) MOVED out of the
|
|
1066
|
+
worker contract and into the two epilogues that actually reach a child — it is pinned in
|
|
1067
|
+
`agent-dispatch-hook.test.ts` and `scratchpad-hook.test.ts` rather than in the contract goldens.
|
|
1068
|
+
|
|
1069
|
+
**The accepted cost, stated plainly rather than engineered around.** The maintainer chose this over a
|
|
1070
|
+
hybrid that kept a canonical doc, knowing compaction recovery degrades from a guaranteed injection to a
|
|
1071
|
+
pointer the model can skip. So the hook now NAMES the files in the directory and never their content
|
|
1072
|
+
(`scratchpad-hook.test.ts` pins that a body written into a scratch file does not appear in the
|
|
1073
|
+
injection). Re-growing that listing back into a content injection would restore exactly what was
|
|
1074
|
+
removed. The guaranteed channel is the arming, and every surface that mentions the directory also
|
|
1075
|
+
mentions `post_compaction: true`, because a folder nothing ever reads back is a folder of notes nobody
|
|
1076
|
+
opens.
|
|
1077
|
+
|
|
1078
|
+
**Two migrations that cost nothing.** `discover.ts`'s transcript-recovery sentinel shortened from
|
|
1079
|
+
`threads/<id>/scratch.md` to `threads/<id>/` — the new string is a PREFIX of the old one, so every
|
|
1080
|
+
transcript written before today still matches and no live thread lost its recovery path (pinned by
|
|
1081
|
+
`discover.test.ts`). And the Doc tab now renders the directory: files concatenated under a heading
|
|
1082
|
+
each, newest first, dotfiles excluded (frizz's own `.scratchpad-state.json` is not the worker's notes),
|
|
1083
|
+
binaries named rather than inlined, with per-file and total caps that say when they truncated. It is
|
|
1084
|
+
gated on the directory being NON-EMPTY rather than merely present, since dispatch now creates it empty
|
|
1085
|
+
and "exists" stopped meaning "the worker wrote something".
|