frizz-server 0.15.25 → 0.15.26
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/dist/claude-agent-broker.js +84 -15
- package/dist/dev-child.js +2719 -661
- package/package.json +1 -1
- package/runtime/cc-worker/bin/frizzctl.mjs +18 -5
- package/runtime/cc-worker/hooks/deny-ask.mjs +5 -5
- package/runtime/cc-worker/hooks/deny-plan.mjs +2 -2
- package/runtime/cc-worker/hooks/perm-policy.mjs +3 -2
- package/runtime/cc-worker/hooks/session-seed.mjs +1 -1
- package/runtime/cc-worker/lib/frizz-tools.mjs +203 -308
- package/runtime/cc-worker/skills/gh/SKILL.md +2 -2
- package/web-dist/assets/{abnfDiagram-VRR7QNED-BUGGhGcL.js → abnfDiagram-VRR7QNED-CNyfSRB-.js} +1 -1
- package/web-dist/assets/{arc-DlmiB5Kw.js → arc-B7GpXPgU.js} +1 -1
- package/web-dist/assets/architecture-TIHT7OUA-DFqMJLC6.js +1 -0
- package/web-dist/assets/{architectureDiagram-ZJ3FMSHR-m4afIjbT.js → architectureDiagram-ZJ3FMSHR-BL9AvVPw.js} +1 -1
- package/web-dist/assets/{blockDiagram-677ZJIJ3-Kz2humn5.js → blockDiagram-677ZJIJ3-Bk0zPEyN.js} +1 -1
- package/web-dist/assets/{c4Diagram-LMCZKHZV-SeHCCIRv.js → c4Diagram-LMCZKHZV-DshZ5qfH.js} +1 -1
- package/web-dist/assets/channel-BhCIHKNP.js +1 -0
- package/web-dist/assets/{chunk-32BRIVSS-Cs4BaciL.js → chunk-32BRIVSS-Dizvs5Li.js} +1 -1
- package/web-dist/assets/{chunk-52WLFC77-Hrl54hxN.js → chunk-52WLFC77-EMHLNOFY.js} +1 -1
- package/web-dist/assets/{chunk-C7G6YPKG-C_LwXwMT.js → chunk-C7G6YPKG-fJaXKcoK.js} +1 -1
- package/web-dist/assets/{chunk-EX3LRPZG-s0-pq_ja.js → chunk-EX3LRPZG-HprJlZtU.js} +1 -1
- package/web-dist/assets/{chunk-FWX5IMBZ-Ci_L6bRR.js → chunk-FWX5IMBZ-D4Kfd-PN.js} +2 -2
- package/web-dist/assets/{chunk-HOUHSVGY-Cn43tXaT.js → chunk-HOUHSVGY-B6Mk78rz.js} +1 -1
- package/web-dist/assets/{chunk-ICXQ74PX-DaehSUDb.js → chunk-ICXQ74PX-C82cqtFI.js} +1 -1
- package/web-dist/assets/{chunk-MOJQB5TN-BOLvHrOY.js → chunk-MOJQB5TN-u1x1nYem.js} +1 -1
- package/web-dist/assets/{chunk-OGEWGWER-B7N0H72R.js → chunk-OGEWGWER-CfTCyDTh.js} +1 -1
- package/web-dist/assets/{chunk-PUDLZKDR-D9Tpv5xu.js → chunk-PUDLZKDR-C5Tr296g.js} +1 -1
- package/web-dist/assets/{chunk-Q4XR5HBZ-CZxzEfvh.js → chunk-Q4XR5HBZ-CDWIuCum.js} +1 -1
- package/web-dist/assets/{chunk-RYQCIY6F-CH35JHMA.js → chunk-RYQCIY6F-1kBJEeqJ.js} +1 -1
- package/web-dist/assets/{chunk-V7JOEXUC-28qGatq3.js → chunk-V7JOEXUC-klZC3He0.js} +1 -1
- package/web-dist/assets/{chunk-VAUOI2AC-CkO9u5CM.js → chunk-VAUOI2AC-KxE_dl7F.js} +1 -1
- package/web-dist/assets/{chunk-VR4S4FIN-BFszczwO.js → chunk-VR4S4FIN-DzTR01Sr.js} +1 -1
- package/web-dist/assets/{chunk-WYO6CB5R-CuBoterc.js → chunk-WYO6CB5R-Bz3_NY0w.js} +1 -1
- package/web-dist/assets/{chunk-XXDRQBXY-8nlDi-YO.js → chunk-XXDRQBXY-8BnGChAk.js} +1 -1
- package/web-dist/assets/{chunk-ZGVPDNZ5-B5WfIiLa.js → chunk-ZGVPDNZ5-CrkRzpPb.js} +1 -1
- package/web-dist/assets/classDiagram-OUVF2IWQ-BwjDIolk.js +1 -0
- package/web-dist/assets/classDiagram-v2-EOCWNBFH-BwjDIolk.js +1 -0
- package/web-dist/assets/{cose-bilkent-JH36ORCC-Csxg0M3P.js → cose-bilkent-JH36ORCC-DPG2EHnF.js} +1 -1
- package/web-dist/assets/{cynefin-VYW2F7L2-DY-oaly-.js → cynefin-VYW2F7L2-DxcxILDk.js} +1 -1
- package/web-dist/assets/{cynefinDiagram-TSTJHNR4-Baev5OIz.js → cynefinDiagram-TSTJHNR4-7sJ6wP__.js} +1 -1
- package/web-dist/assets/{dagre-VKFMJZFB-VV2KSHL4.js → dagre-VKFMJZFB-SJEyJ4rz.js} +1 -1
- package/web-dist/assets/{diagram-FQU43EPY-rLuhqzIC.js → diagram-FQU43EPY-Wcdsv0P_.js} +1 -1
- package/web-dist/assets/{diagram-G47NLZAW-BBRVU5Kr.js → diagram-G47NLZAW-B6BZ7zQo.js} +1 -1
- package/web-dist/assets/{diagram-NH7WQ7WH-BMSjTTHf.js → diagram-NH7WQ7WH-CtDA1PI9.js} +1 -1
- package/web-dist/assets/{diagram-OA4YK3LP-7NO_QsSx.js → diagram-OA4YK3LP-CdpweEmv.js} +1 -1
- package/web-dist/assets/{diagram-WEI45ONY-evQWfr1h.js → diagram-WEI45ONY-7t3uF33P.js} +1 -1
- package/web-dist/assets/{dist-BoiR_HZa.js → dist-B9lHlEOl.js} +1 -1
- package/web-dist/assets/{ebnfDiagram-CCIWWBDH-BGCXILB-.js → ebnfDiagram-CCIWWBDH-B3COYz5O.js} +1 -1
- package/web-dist/assets/{erDiagram-Q63AITRT-CJSi0YB2.js → erDiagram-Q63AITRT-Bu2R48kZ.js} +1 -1
- package/web-dist/assets/eventmodeling-45OFAUF4-CkJKP4v8.js +1 -0
- package/web-dist/assets/flowDiagram-23GEKE2U-GUo1f41A.js +1 -0
- package/web-dist/assets/{ganttDiagram-NO4QXBWP-DfKGoGJe.js → ganttDiagram-NO4QXBWP-DHaD8AsE.js} +1 -1
- package/web-dist/assets/{gitGraph-TEB2WS4Q-DDOEbCVa.js → gitGraph-TEB2WS4Q-4lWdjXjQ.js} +1 -1
- package/web-dist/assets/{gitGraphDiagram-IHSO6WYX-tKMl1T5T.js → gitGraphDiagram-IHSO6WYX-Cfwf7OSS.js} +1 -1
- package/web-dist/assets/index-Ccmq3ie-.css +2 -0
- package/web-dist/assets/index-JmPE6HTE.js +369 -0
- package/web-dist/assets/{info-DKCQHKI2-BqMXJJEF.js → info-DKCQHKI2-m9CiI1ls.js} +1 -1
- package/web-dist/assets/{infoDiagram-FWYZ7A6U-DXpmORxt.js → infoDiagram-FWYZ7A6U-CuSqktgG.js} +1 -1
- package/web-dist/assets/{ishikawaDiagram-FXEZZL3T-D9yCb_iG.js → ishikawaDiagram-FXEZZL3T-By4RUAid.js} +1 -1
- package/web-dist/assets/{journeyDiagram-5HDEW3XC-DwyXsO1X.js → journeyDiagram-5HDEW3XC-DG0j1rYj.js} +1 -1
- package/web-dist/assets/{kanban-definition-HUTT4EX6-C-BupP2L.js → kanban-definition-HUTT4EX6-FUs5nKgH.js} +1 -1
- package/web-dist/assets/{line-CVohBkYV.js → line-hUw2N2pN.js} +1 -1
- package/web-dist/assets/{linear-CUS0dsDf.js → linear-BO0jjB2S.js} +1 -1
- package/web-dist/assets/{mermaid-parser.core-BaUI30hf.js → mermaid-parser.core-D1gbOxjg.js} +3 -3
- package/web-dist/assets/{mermaid.core-DRwFVBM9.js → mermaid.core-DVlHSH5E.js} +3 -3
- package/web-dist/assets/{mindmap-definition-LN4V7U3C-Dwz7wXjl.js → mindmap-definition-LN4V7U3C-36mZJhg3.js} +1 -1
- package/web-dist/assets/{packet-7NZHBO7P-Cc8S-JIW.js → packet-7NZHBO7P-ee_dSZ_l.js} +1 -1
- package/web-dist/assets/{pegDiagram-2B236MQR-DEvuejFX.js → pegDiagram-2B236MQR-T04ZP7_1.js} +1 -1
- package/web-dist/assets/{pie-RZYD4A2V-lDSko9Ox.js → pie-RZYD4A2V-CgzvejQO.js} +1 -1
- package/web-dist/assets/{pieDiagram-ENE6RG2P-DoIHahh_.js → pieDiagram-ENE6RG2P-CK8_lkQJ.js} +1 -1
- package/web-dist/assets/{quadrantDiagram-ABIIQ3AL-ttYUswX_.js → quadrantDiagram-ABIIQ3AL-BX7B-RuD.js} +1 -1
- package/web-dist/assets/{radar-I7S5WNFK-Dlai2VWL.js → radar-I7S5WNFK-CCWcFiS2.js} +1 -1
- package/web-dist/assets/{railroad-3IZDKUUU-CfOvvQCL.js → railroad-3IZDKUUU-D8RYaz8I.js} +1 -1
- package/web-dist/assets/railroad-abnf-AHOZXSZD-BIqOg_LJ.js +1 -0
- package/web-dist/assets/railroad-ebnf-EBAXGLYW-BRPgZKlP.js +1 -0
- package/web-dist/assets/railroad-peg-LSFZ7HO6-Brgy-BUA.js +1 -0
- package/web-dist/assets/{railroadDiagram-RFXS5EU6-BRpMN8zD.js → railroadDiagram-RFXS5EU6-DGJ0oKTd.js} +1 -1
- package/web-dist/assets/{requirementDiagram-TGXJPOKE-C1f5KNrx.js → requirementDiagram-TGXJPOKE-BVQLI9-P.js} +1 -1
- package/web-dist/assets/{sankeyDiagram-HTMAVEWB-CjXPLZ2A.js → sankeyDiagram-HTMAVEWB-B5ggFMDw.js} +1 -1
- package/web-dist/assets/{sequenceDiagram-DBY2YBRQ-BxVxwb4e.js → sequenceDiagram-DBY2YBRQ-BadwsmJp.js} +1 -1
- package/web-dist/assets/{src-DjcREoQq.js → src-DOszP0Mb.js} +1 -1
- package/web-dist/assets/{stateDiagram-2N3HPSRC-CCx9rSmu.js → stateDiagram-2N3HPSRC-kImZu5Rm.js} +1 -1
- package/web-dist/assets/stateDiagram-v2-6OUMAXLB-CmGlxfpO.js +1 -0
- package/web-dist/assets/{swimlanes-5IMT3BWC-L3Legvfa.js → swimlanes-5IMT3BWC-CzX_Y32B.js} +1 -1
- package/web-dist/assets/swimlanesDiagram-G3AALYLV-UcSbtgIg.js +8 -0
- package/web-dist/assets/{timeline-definition-FHXFAJF6-0p22547Z.js → timeline-definition-FHXFAJF6-Kkw3Kc6H.js} +1 -1
- package/web-dist/assets/{treeView-QDETBFTQ-Xv4-kZ7I.js → treeView-QDETBFTQ-EuCs9-Ch.js} +1 -1
- package/web-dist/assets/{treemap-6X3UGDF4-MhycNmte.js → treemap-6X3UGDF4-C8bZntYA.js} +1 -1
- package/web-dist/assets/{vennDiagram-L72KCM5P-P33JCPMu.js → vennDiagram-L72KCM5P-CK-XdQRZ.js} +1 -1
- package/web-dist/assets/{wardley-OPB4EBWU-CS41M7I-.js → wardley-OPB4EBWU-DwOmFrbt.js} +1 -1
- package/web-dist/assets/{wardleyDiagram-EHGQE667-CbQaI_DG.js → wardleyDiagram-EHGQE667-DtSbjytW.js} +1 -1
- package/web-dist/assets/{xychartDiagram-FW5EYKEG-tg1lQQ6H.js → xychartDiagram-FW5EYKEG-C-Onuqe8.js} +1 -1
- package/web-dist/index.html +2 -2
- package/web-dist/assets/architecture-TIHT7OUA-DvYaN-Hu.js +0 -1
- package/web-dist/assets/channel-Og7O24Xl.js +0 -1
- package/web-dist/assets/classDiagram-OUVF2IWQ-DBua7nWT.js +0 -1
- package/web-dist/assets/classDiagram-v2-EOCWNBFH-DBua7nWT.js +0 -1
- package/web-dist/assets/eventmodeling-45OFAUF4-CMWWvyUk.js +0 -1
- package/web-dist/assets/flowDiagram-23GEKE2U-CFOr0Vr_.js +0 -1
- package/web-dist/assets/index-DYhjAs_a.js +0 -354
- package/web-dist/assets/index-htGvcLfn.css +0 -2
- package/web-dist/assets/railroad-abnf-AHOZXSZD-Br3ohVd5.js +0 -1
- package/web-dist/assets/railroad-ebnf-EBAXGLYW-DFaY0AnY.js +0 -1
- package/web-dist/assets/railroad-peg-LSFZ7HO6-Cy2FBxXb.js +0 -1
- package/web-dist/assets/stateDiagram-v2-6OUMAXLB-bSyE7VSt.js +0 -1
- package/web-dist/assets/swimlanesDiagram-G3AALYLV-n0v1Z0Xu.js +0 -8
package/package.json
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* be bare where the registry says so (`frizzctl title "Fix queue focus"`).
|
|
21
21
|
* JSON `--input <file>`, `--input -` for stdin, or a JSON object as the first argument — the
|
|
22
22
|
* same object the command's schema describes. This is `gh api --input`, and it is what
|
|
23
|
-
* makes a nested payload
|
|
23
|
+
* makes a nested payload or a long one sayable at all.
|
|
24
24
|
* text files any text argument also takes `--<name>-file <path|->` — `gh pr create --body-file`.
|
|
25
25
|
*
|
|
26
26
|
* STDIN IS NEVER READ UNLESS `-` ASKS FOR IT. An agent's shell hands a command an open pipe more often
|
|
@@ -29,6 +29,11 @@
|
|
|
29
29
|
*
|
|
30
30
|
* EXIT CODES: 0 the command did what it says; 1 it failed, or was called wrongly; 2 it REFUSED — a gate
|
|
31
31
|
* that held (`done` with a question still open), so `frizzctl done … || …` can tell the two apart.
|
|
32
|
+
*
|
|
33
|
+
* A RETIRED COMMAND (`ask`, `secret`: a question is a ```question fence since 2026-10-13) is still a
|
|
34
|
+
* command, because the worker that reaches for one is the worker that needs to be told what replaced it.
|
|
35
|
+
* It refuses whatever it is given — no argument is parsed, so no usage error can stand in front of the
|
|
36
|
+
* lesson, and stdin is never read — and its `--help` is the same text. `frizzctl --help` does not list it.
|
|
32
37
|
*/
|
|
33
38
|
import { readFileSync } from "node:fs"
|
|
34
39
|
import { CLI, HANDLERS, Refused, TOOLS } from "../lib/frizz-tools.mjs"
|
|
@@ -281,7 +286,7 @@ function topHelp() {
|
|
|
281
286
|
"",
|
|
282
287
|
"Arguments arrive three ways, and they combine (a flag wins over JSON):",
|
|
283
288
|
` flags ${NAME} watch shell bzvtnt3ig --for 2h`,
|
|
284
|
-
` JSON ${NAME}
|
|
289
|
+
` JSON ${NAME} goal start --input goal.json (--input - reads stdin; a '{…}' first argument works too)`,
|
|
285
290
|
` text files any text argument takes --<name>-file <path|->: ${NAME} done --body-file handoff.md`,
|
|
286
291
|
"",
|
|
287
292
|
"Text holding backticks, $ or quotes goes through a file or a QUOTED heredoc, never a double-quoted",
|
|
@@ -347,6 +352,12 @@ function commandHelp(tool) {
|
|
|
347
352
|
].join("\n")
|
|
348
353
|
}
|
|
349
354
|
|
|
355
|
+
/** A retired command's page: its one-line summary, then the text it refuses with — printed as written,
|
|
356
|
+
* never wrapped, because it carries a fence the worker copies. @param {any} tool */
|
|
357
|
+
function retiredHelp(tool) {
|
|
358
|
+
return `${NAME} ${hyphen(tool.name)} — ${CLI[tool.name].summary}\n\n${CLI[tool.name].retired}`
|
|
359
|
+
}
|
|
360
|
+
|
|
350
361
|
/** Whether the arguments ask for help, read the way parseArgs reads them: a `-h` that is a flag's
|
|
351
362
|
* VALUE (`steer other --message -h`) is the message, not a request for help, and the command must run
|
|
352
363
|
* rather than print help and exit 0 having sent nothing. Its own pass, with no side effects, so that
|
|
@@ -377,10 +388,12 @@ async function main(argv) {
|
|
|
377
388
|
if (!first || first === "--help" || first === "-h" || first === "help") {
|
|
378
389
|
const about = first === "help" && rest[0] ? toolNamed(rest[0]) : undefined
|
|
379
390
|
if (first === "help" && rest[0] && !about) throw new UsageError(unknownCommand(rest[0]))
|
|
380
|
-
return { code: 0, out: about ? commandHelp(about) : topHelp() }
|
|
391
|
+
return { code: 0, out: about ? (CLI[about.name]?.retired ? retiredHelp(about) : commandHelp(about)) : topHelp() }
|
|
381
392
|
}
|
|
382
393
|
const tool = toolNamed(first)
|
|
383
394
|
if (!tool) throw new UsageError(unknownCommand(first))
|
|
395
|
+
const retired = CLI[tool.name]?.retired
|
|
396
|
+
if (retired) return rest.includes("--help") || rest.includes("-h") ? { code: 0, out: retiredHelp(tool) } : { code: 2, out: retired }
|
|
384
397
|
const asked = helpAsked(tool, rest)
|
|
385
398
|
if (asked === "help") return { code: 0, out: commandHelp(tool) }
|
|
386
399
|
if (asked === "schema") return { code: 0, out: JSON.stringify(tool.inputSchema, null, 2) }
|
|
@@ -414,11 +427,11 @@ function distance(a, b) {
|
|
|
414
427
|
/** @param {string} raw */
|
|
415
428
|
function unknownCommand(raw) {
|
|
416
429
|
const want = under(raw.toLowerCase())
|
|
417
|
-
const near = TOOLS.filter((t) => t.name.includes(want) || want.includes(t.name) || distance(t.name, want) <= 2).map((t) => hyphen(t.name))
|
|
430
|
+
const near = TOOLS.filter((t) => !CLI[t.name]?.retired && (t.name.includes(want) || want.includes(t.name) || distance(t.name, want) <= 2)).map((t) => hyphen(t.name))
|
|
418
431
|
return (
|
|
419
432
|
`\`${NAME}\` has no command ${JSON.stringify(raw)}.` +
|
|
420
433
|
(near.length ? ` Did you mean: ${near.join(", ")}?` : "") +
|
|
421
|
-
`\nCommands: ${TOOLS.map((t) => hyphen(t.name)).join(", ")}.\nRun \`${NAME} --help\` for what each one does.`
|
|
434
|
+
`\nCommands: ${TOOLS.filter((t) => !CLI[t.name]?.retired).map((t) => hyphen(t.name)).join(", ")}.\nRun \`${NAME} --help\` for what each one does.`
|
|
422
435
|
)
|
|
423
436
|
}
|
|
424
437
|
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
// @ts-check
|
|
3
3
|
// PreToolUse hook on AskUserQuestion (frizz-worker). A frizz worker runs under a dashboard, not a
|
|
4
4
|
// live chat: an interactive question prompt would hang the session invisibly (nobody is at the
|
|
5
|
-
// keyboard to click it). Deny with a redirect to the async pattern:
|
|
6
|
-
//
|
|
7
|
-
// rest normally; the answer arrives as its own wake.
|
|
5
|
+
// keyboard to click it). Deny with a redirect to the async pattern: ask it in a structured ```question
|
|
6
|
+
// fence in the worker's own message (a row, registered when the message lands — since 2026-10-13; it
|
|
7
|
+
// was `frizzctl ask` before that), keep working, and rest normally; the answer arrives as its own wake.
|
|
8
8
|
// GATE: inert unless FRIZZ_THREAD is set. FAIL OPEN on parse errors.
|
|
9
9
|
//
|
|
10
10
|
// SECOND GATE: also inert when FRIZZ_NATIVE_ASK=1. The premise above — "nobody is at the keyboard" —
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
// operator answers and which returns the chosen labels to the tool. The broker bridge sets that var
|
|
14
14
|
// only when an InteractionStore is actually wired to render and resolve the card, so a denial here
|
|
15
15
|
// would block a question the operator CAN see. Any other path leaves the var unset, so it keeps the
|
|
16
|
-
// deny plus the
|
|
16
|
+
// deny plus the ```question fence redirect.
|
|
17
17
|
import { readFileSync } from 'node:fs';
|
|
18
18
|
|
|
19
19
|
const slug = process.env.FRIZZ_THREAD;
|
|
@@ -32,7 +32,7 @@ process.stdout.write(
|
|
|
32
32
|
hookEventName: 'PreToolUse',
|
|
33
33
|
permissionDecision: 'deny',
|
|
34
34
|
permissionDecisionReason:
|
|
35
|
-
'Interactive prompts freeze headless workers (no one is at the keyboard to answer).
|
|
35
|
+
'Interactive prompts freeze headless workers (no one is at the keyboard to answer). Ask it in a ```question fence in your own message instead: `id:` (a slug of your choosing), `kind:` (`choice`, `multi`, `text` or `secret`), a one-line `question:`, and `options:` as `- label:` items with a one-line `description:` each, the recommended one first with `recommended: true`; context for the human goes below a `---` line, in any Markdown. One fence per question, each self-contained, written actor-explicit — never "I" or "you", which flip meaning when the human clicks an option. Frizz registers it when your message lands and draws its card where you wrote it (`frizzctl ask --help` shows the whole grammar). Asking does not end your turn — keep doing what does not depend on the answer, then rest normally: the question IS the handback (no done fence beside it, and do NOT invoke this tool again). The answer arrives as your next user message.',
|
|
36
36
|
},
|
|
37
37
|
}),
|
|
38
38
|
);
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
// instead — frizz NEVER spawns a worker in plan mode (dispatch.ts coerces `--permission-mode plan`
|
|
24
24
|
// → `auto` in both command builders), so a real frizz worker is never in plan mode and this deny
|
|
25
25
|
// only ever meets a SPURIOUS ExitPlanMode call (nothing to exit → deny + redirect is correct). A
|
|
26
|
-
// worker "plans" by writing a durable plan file and asking
|
|
26
|
+
// worker "plans" by writing a durable plan file and asking in a ```question fence,
|
|
27
27
|
// never via interactive plan mode.
|
|
28
28
|
// RESIDUAL GAP (accepted, documented): the deny could softlock only a FOREIGN session that is
|
|
29
29
|
// simultaneously in plan mode AND running with FRIZZ_THREAD set AND this plugin loaded — a combo
|
|
@@ -48,7 +48,7 @@ try {
|
|
|
48
48
|
// the model reads is `additionalContext`, injected as a plain-text system-reminder. Exit 0 with
|
|
49
49
|
// this JSON on stdout (exit 2 would make Claude Code ignore the JSON — never mix).
|
|
50
50
|
const reason =
|
|
51
|
-
'Interactive plan-approval prompts freeze headless workers (no one is at the keyboard to approve). Do NOT present a plan for approval. Instead: if the plan is settled, just proceed with the work. If the plan is the deliverable, write it into a durable plan file — wherever the dispatch or the project\'s conventions name; your scratch directory works when nothing names one. If it needs a human call before you build,
|
|
51
|
+
'Interactive plan-approval prompts freeze headless workers (no one is at the keyboard to approve). Do NOT present a plan for approval. Instead: if the plan is settled, just proceed with the work. If the plan is the deliverable, write it into a durable plan file — wherever the dispatch or the project\'s conventions name; your scratch directory works when nothing names one. If it needs a human call before you build, ask a two-option `kind: choice` question in a ```question fence stating what you need approved, then come to rest — the human reviews it from the frizz queue.';
|
|
52
52
|
|
|
53
53
|
process.stdout.write(
|
|
54
54
|
JSON.stringify({
|
|
@@ -84,8 +84,9 @@ function isDiskWrite(cmd) {
|
|
|
84
84
|
// (`_live_broker_frizzctl.mts`): a bare call, an inline JSON argument, `--input <file>`, `< file`,
|
|
85
85
|
// `frizzctl … && frizzctl …` and a quoted heredoc of PROSE all ran unasked, and a quoted heredoc whose
|
|
86
86
|
// body holds a JSON object raised a prompt — Claude Code's own command checks read the braces and
|
|
87
|
-
// quotes of a body the shell never interprets. That
|
|
88
|
-
// question's options do not fit on a command line
|
|
87
|
+
// quotes of a body the shell never interprets. That was the one shape `ask` most needed, since a
|
|
88
|
+
// question's options do not fit on a command line; `ask` refuses since 2026-10-13 (a question is a
|
|
89
|
+
// ```question fence the worker writes), and the shape stays approved for every other `--input -`.
|
|
89
90
|
//
|
|
90
91
|
// So this recognises exactly that shape, and it is deliberately narrower than the rule it backs up.
|
|
91
92
|
// The first line is `frizzctl`, then words made only of characters the shell does not interpret, then
|
|
@@ -68,7 +68,7 @@ const scratch = sid
|
|
|
68
68
|
// prompt. Trimmed 2026-08-26 (maintainer: "Definitely trim the session seed hook if it's fully
|
|
69
69
|
// repetitive") as part of cutting the per-session token overhead Frizz adds over a plain TUI session.
|
|
70
70
|
const core =
|
|
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
|
|
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), the ```question fence that asks the human (a new `id:` registers a question where you write it; an `id:` alone references one you asked before), 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 — a fence OR a registration (`frizzctl done`, or a question you ask or reference at this rest, which is the sign-off: rest normally). A rest on running work takes the ```awaiting fence with `status: working|watching|needs_input` — `working` and `watching` are quiet parks and need no write-up.\n' +
|
|
72
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.';
|
|
73
73
|
|
|
74
74
|
const grounding =
|