frizz-server 0.15.19 → 0.15.22

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 (102) hide show
  1. package/dist/claude-agent-broker.js +23 -6
  2. package/dist/dev-child.js +536 -441
  3. package/package.json +1 -1
  4. package/runtime/cc-worker/DECISIONS.md +15 -2
  5. package/runtime/cc-worker/bin/frizz-mcp.mjs +108 -11
  6. package/runtime/cc-worker/hooks/agent-dispatch.mjs +3 -2
  7. package/runtime/cc-worker/hooks/perm-policy.mjs +10 -1
  8. package/web-dist/assets/{abnfDiagram-VRR7QNED-B10g-WBv.js → abnfDiagram-VRR7QNED-DqTQZ2Ex.js} +1 -1
  9. package/web-dist/assets/{arc-DuG4e22h.js → arc-t56zg8G8.js} +1 -1
  10. package/web-dist/assets/architecture-TIHT7OUA-Czzg2iAA.js +1 -0
  11. package/web-dist/assets/{architectureDiagram-ZJ3FMSHR-CD5BhbBF.js → architectureDiagram-ZJ3FMSHR-CSdC9-eQ.js} +1 -1
  12. package/web-dist/assets/{blockDiagram-677ZJIJ3-1qyXmTdb.js → blockDiagram-677ZJIJ3-Dmw8EopV.js} +1 -1
  13. package/web-dist/assets/{c4Diagram-LMCZKHZV-4Uu0_x-6.js → c4Diagram-LMCZKHZV-BCRaFnis.js} +1 -1
  14. package/web-dist/assets/channel-CxehNUC2.js +1 -0
  15. package/web-dist/assets/{chunk-32BRIVSS-CymdPtt-.js → chunk-32BRIVSS-DqOJDRw_.js} +1 -1
  16. package/web-dist/assets/{chunk-52WLFC77-BmVEKN_g.js → chunk-52WLFC77-BsibludT.js} +1 -1
  17. package/web-dist/assets/{chunk-C7G6YPKG-CyrPM4Xp.js → chunk-C7G6YPKG-D7Me5JQU.js} +1 -1
  18. package/web-dist/assets/{chunk-EX3LRPZG-BHD_8GRk.js → chunk-EX3LRPZG-CTa4YlOO.js} +1 -1
  19. package/web-dist/assets/{chunk-FWX5IMBZ-BRvdh6eD.js → chunk-FWX5IMBZ-CjqOt5Jn.js} +2 -2
  20. package/web-dist/assets/{chunk-HOUHSVGY-Wi0QbfuK.js → chunk-HOUHSVGY-BDIBDR-8.js} +1 -1
  21. package/web-dist/assets/{chunk-ICXQ74PX-BqvsPM6k.js → chunk-ICXQ74PX-C4exiYRm.js} +1 -1
  22. package/web-dist/assets/{chunk-MOJQB5TN-BSorOCQZ.js → chunk-MOJQB5TN-g8M_GVaO.js} +1 -1
  23. package/web-dist/assets/{chunk-OGEWGWER-YF0UfmEL.js → chunk-OGEWGWER-C_80lLFe.js} +1 -1
  24. package/web-dist/assets/{chunk-PUDLZKDR-CR_yDJey.js → chunk-PUDLZKDR-B73Odmxv.js} +1 -1
  25. package/web-dist/assets/{chunk-Q4XR5HBZ-BAJgyRXc.js → chunk-Q4XR5HBZ-D-VkroM1.js} +1 -1
  26. package/web-dist/assets/{chunk-RYQCIY6F-Dgaq4QYp.js → chunk-RYQCIY6F-DmPJ8s-8.js} +1 -1
  27. package/web-dist/assets/{chunk-V7JOEXUC-DYFzD1Jv.js → chunk-V7JOEXUC-BQKrRLYX.js} +1 -1
  28. package/web-dist/assets/{chunk-VAUOI2AC-BgJghXkI.js → chunk-VAUOI2AC-DRKYvsWa.js} +1 -1
  29. package/web-dist/assets/{chunk-VR4S4FIN-_BgF4nNu.js → chunk-VR4S4FIN-DaMMs6V-.js} +1 -1
  30. package/web-dist/assets/{chunk-WYO6CB5R-Bp_ka9na.js → chunk-WYO6CB5R-CQAWjeZH.js} +1 -1
  31. package/web-dist/assets/{chunk-XXDRQBXY-BoA-vwge.js → chunk-XXDRQBXY-DJvt-abB.js} +1 -1
  32. package/web-dist/assets/{chunk-ZGVPDNZ5-Jv6ULLqq.js → chunk-ZGVPDNZ5-B1v24MrX.js} +1 -1
  33. package/web-dist/assets/classDiagram-OUVF2IWQ-BwIDe0nq.js +1 -0
  34. package/web-dist/assets/classDiagram-v2-EOCWNBFH-BwIDe0nq.js +1 -0
  35. package/web-dist/assets/{cose-bilkent-JH36ORCC-B03Sg422.js → cose-bilkent-JH36ORCC-CeNttASr.js} +1 -1
  36. package/web-dist/assets/{cynefin-VYW2F7L2-B42oamLi.js → cynefin-VYW2F7L2-ClJzZ-Yx.js} +1 -1
  37. package/web-dist/assets/{cynefinDiagram-TSTJHNR4-BnTQYMpQ.js → cynefinDiagram-TSTJHNR4-BCrL5Bu_.js} +1 -1
  38. package/web-dist/assets/{dagre-VKFMJZFB-p3n3nLC3.js → dagre-VKFMJZFB-DO7qy19A.js} +1 -1
  39. package/web-dist/assets/{diagram-FQU43EPY-CRP2cukA.js → diagram-FQU43EPY-KPbJc2w8.js} +1 -1
  40. package/web-dist/assets/{diagram-G47NLZAW-ztUWGy5B.js → diagram-G47NLZAW-9tqHFXzf.js} +1 -1
  41. package/web-dist/assets/{diagram-NH7WQ7WH-EOCWY-Df.js → diagram-NH7WQ7WH-BUbmU0cY.js} +1 -1
  42. package/web-dist/assets/{diagram-OA4YK3LP-cLPz4s0P.js → diagram-OA4YK3LP-QmMo96Qi.js} +1 -1
  43. package/web-dist/assets/{diagram-WEI45ONY-C_slbe-r.js → diagram-WEI45ONY-BYAyhW16.js} +1 -1
  44. package/web-dist/assets/{dist-CRFAJ8CQ.js → dist-Cewx01EF.js} +1 -1
  45. package/web-dist/assets/{ebnfDiagram-CCIWWBDH-DBxCHlHt.js → ebnfDiagram-CCIWWBDH-BIMiEDl1.js} +1 -1
  46. package/web-dist/assets/{erDiagram-Q63AITRT-DwOXrEq_.js → erDiagram-Q63AITRT-aLYQSs2d.js} +1 -1
  47. package/web-dist/assets/eventmodeling-45OFAUF4-jYGf30I4.js +1 -0
  48. package/web-dist/assets/flowDiagram-23GEKE2U-uJJwGAew.js +1 -0
  49. package/web-dist/assets/{ganttDiagram-NO4QXBWP-DuY0nOYK.js → ganttDiagram-NO4QXBWP-Bu6_kuAX.js} +1 -1
  50. package/web-dist/assets/{gitGraph-TEB2WS4Q-YQmgtcHg.js → gitGraph-TEB2WS4Q-yz2DuHDq.js} +1 -1
  51. package/web-dist/assets/{gitGraphDiagram-IHSO6WYX-CB_Ot5Q1.js → gitGraphDiagram-IHSO6WYX-BXfbKaor.js} +1 -1
  52. package/web-dist/assets/{index-BbIe1bSx.js → index-DS1RBTF4.js} +99 -100
  53. package/web-dist/assets/index-DX1b-Y8G.css +2 -0
  54. package/web-dist/assets/{info-DKCQHKI2-D2W41g1Q.js → info-DKCQHKI2-BdItukhP.js} +1 -1
  55. package/web-dist/assets/{infoDiagram-FWYZ7A6U-1kUrfZfi.js → infoDiagram-FWYZ7A6U-DXrq8wS3.js} +1 -1
  56. package/web-dist/assets/{ishikawaDiagram-FXEZZL3T-Cd8vJIC4.js → ishikawaDiagram-FXEZZL3T-iM2fPeJv.js} +1 -1
  57. package/web-dist/assets/{journeyDiagram-5HDEW3XC-Cv34OO50.js → journeyDiagram-5HDEW3XC-DNa58xSH.js} +1 -1
  58. package/web-dist/assets/{kanban-definition-HUTT4EX6-Bdv5tRjm.js → kanban-definition-HUTT4EX6-DhSaBCRv.js} +1 -1
  59. package/web-dist/assets/{line-BNSjkXxa.js → line-CQn0ApgD.js} +1 -1
  60. package/web-dist/assets/{linear-1DfcUKuY.js → linear-DMSasryg.js} +1 -1
  61. package/web-dist/assets/{mermaid-parser.core-DoSxbCDI.js → mermaid-parser.core-BiJ3pVQT.js} +3 -3
  62. package/web-dist/assets/{mermaid.core-BprKkJS0.js → mermaid.core-8ofZrJs5.js} +3 -3
  63. package/web-dist/assets/{mindmap-definition-LN4V7U3C-B1YN0fjH.js → mindmap-definition-LN4V7U3C-BLr4IGuI.js} +1 -1
  64. package/web-dist/assets/{packet-7NZHBO7P-D6A5AWD4.js → packet-7NZHBO7P-D15LrSHU.js} +1 -1
  65. package/web-dist/assets/{pegDiagram-2B236MQR-D7IVXst2.js → pegDiagram-2B236MQR-C9IcvZ_z.js} +1 -1
  66. package/web-dist/assets/{pie-RZYD4A2V-DBV3iaG4.js → pie-RZYD4A2V-79-1CSta.js} +1 -1
  67. package/web-dist/assets/{pieDiagram-ENE6RG2P-CsytOcSt.js → pieDiagram-ENE6RG2P-dm_ORKO7.js} +1 -1
  68. package/web-dist/assets/{quadrantDiagram-ABIIQ3AL-DxeMNT6T.js → quadrantDiagram-ABIIQ3AL-vQkbT0Ej.js} +1 -1
  69. package/web-dist/assets/{radar-I7S5WNFK-CpBdfZ-J.js → radar-I7S5WNFK-B8xvrM0r.js} +1 -1
  70. package/web-dist/assets/{railroad-3IZDKUUU-CB0b9HgI.js → railroad-3IZDKUUU-G0rN-YuN.js} +1 -1
  71. package/web-dist/assets/railroad-abnf-AHOZXSZD-BaCc6741.js +1 -0
  72. package/web-dist/assets/railroad-ebnf-EBAXGLYW-cUMY4WQi.js +1 -0
  73. package/web-dist/assets/railroad-peg-LSFZ7HO6-JS2RjlNP.js +1 -0
  74. package/web-dist/assets/{railroadDiagram-RFXS5EU6-dog6mbEK.js → railroadDiagram-RFXS5EU6-BtGt9H2_.js} +1 -1
  75. package/web-dist/assets/{requirementDiagram-TGXJPOKE-CPrGy_u9.js → requirementDiagram-TGXJPOKE-oHUUvJjC.js} +1 -1
  76. package/web-dist/assets/{sankeyDiagram-HTMAVEWB-BOGmV457.js → sankeyDiagram-HTMAVEWB-BoO0DzUn.js} +1 -1
  77. package/web-dist/assets/{sequenceDiagram-DBY2YBRQ-C72YpVOm.js → sequenceDiagram-DBY2YBRQ-B344KPVn.js} +1 -1
  78. package/web-dist/assets/{src-CS_pkXwT.js → src-BygbIYKj.js} +1 -1
  79. package/web-dist/assets/{stateDiagram-2N3HPSRC-B3MY1_Fn.js → stateDiagram-2N3HPSRC-DMTN-MuE.js} +1 -1
  80. package/web-dist/assets/stateDiagram-v2-6OUMAXLB-4HUOVSEd.js +1 -0
  81. package/web-dist/assets/{swimlanes-5IMT3BWC-an1f8oes.js → swimlanes-5IMT3BWC-DQEhwI0k.js} +1 -1
  82. package/web-dist/assets/swimlanesDiagram-G3AALYLV-PPFuhngt.js +8 -0
  83. package/web-dist/assets/{timeline-definition-FHXFAJF6-smz-DPet.js → timeline-definition-FHXFAJF6-CUoCgDT7.js} +1 -1
  84. package/web-dist/assets/{treeView-QDETBFTQ-CAugNmmU.js → treeView-QDETBFTQ-BTHFGWtv.js} +1 -1
  85. package/web-dist/assets/{treemap-6X3UGDF4-092D5VOe.js → treemap-6X3UGDF4-BI2j1PYm.js} +1 -1
  86. package/web-dist/assets/{vennDiagram-L72KCM5P-ZrLbNHc1.js → vennDiagram-L72KCM5P-Cc3sJIb2.js} +1 -1
  87. package/web-dist/assets/{wardley-OPB4EBWU-B6wmYPTL.js → wardley-OPB4EBWU-kYXYWMgL.js} +1 -1
  88. package/web-dist/assets/{wardleyDiagram-EHGQE667-CZLh6SWT.js → wardleyDiagram-EHGQE667-KHMHPO99.js} +1 -1
  89. package/web-dist/assets/{xychartDiagram-FW5EYKEG-DsSYn7Qp.js → xychartDiagram-FW5EYKEG-DzSZk-Dq.js} +1 -1
  90. package/web-dist/index.html +2 -2
  91. package/web-dist/assets/architecture-TIHT7OUA-j6FK_Pnq.js +0 -1
  92. package/web-dist/assets/channel-tY-f3z4r.js +0 -1
  93. package/web-dist/assets/classDiagram-OUVF2IWQ-CjG-97tN.js +0 -1
  94. package/web-dist/assets/classDiagram-v2-EOCWNBFH-CjG-97tN.js +0 -1
  95. package/web-dist/assets/eventmodeling-45OFAUF4-DrsowDZT.js +0 -1
  96. package/web-dist/assets/flowDiagram-23GEKE2U-BSxVKNg3.js +0 -1
  97. package/web-dist/assets/index-DN7SaNCi.css +0 -2
  98. package/web-dist/assets/railroad-abnf-AHOZXSZD-DQY-MvA7.js +0 -1
  99. package/web-dist/assets/railroad-ebnf-EBAXGLYW-BZ8CtIZS.js +0 -1
  100. package/web-dist/assets/railroad-peg-LSFZ7HO6-DCtmtrza.js +0 -1
  101. package/web-dist/assets/stateDiagram-v2-6OUMAXLB-DFyf64uA.js +0 -1
  102. package/web-dist/assets/swimlanesDiagram-G3AALYLV-CoxA2IjD.js +0 -8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frizz-server",
3
- "version": "0.15.19",
3
+ "version": "0.15.22",
4
4
  "private": false,
5
5
  "description": "Replaceable Frizz server runtime",
6
6
  "license": "MIT",
@@ -271,8 +271,12 @@ being indistinguishable from bypass.
271
271
  THE TABLE ships UNIVERSAL rules only; this plugin loads for every project frizz drives, so a rule that
272
272
  is right for one repo is wrong for the next. `catastrophic-delete` and `raw-disk-write` deny outright
273
273
  (strictly safer than bypass, which would have allowed both). `restrictive-mode` DEFERS whenever
274
- `permission_mode !== "auto"`, which is what makes a genuine lower-permission mode usable: move a thread
275
- to `default` with the live permission control and its prompts come back. `FRIZZ_PERM_POLICY=review`
274
+ `permission_mode` is anything but `auto` or `bypassPermissions`, which is what makes a genuine lower-permission mode usable: move a thread
275
+ to `default` with the live permission control and its prompts come back. (Until 2026-10-10 the test
276
+ was `!== "auto"`, which swept in `bypassPermissions` — the one mode MORE permissive than auto — so a
277
+ bypass thread was handed every prompt Claude Code still raises under bypass, as approval cards an auto
278
+ thread never showed. Bypass now falls through to `worker-autonomy`; any other or unknown mode still
279
+ defers.) `FRIZZ_PERM_POLICY=review`
276
280
  defers everything. Fail-safe INVERTS the old observer's fail-open — for a hook that can APPROVE, any
277
281
  error must fall back to asking, never to allowing.
278
282
 
@@ -1170,3 +1174,12 @@ A Fable helper on `nubjs/nub` ("Investigate Node SEA as container", 118 tool cal
1170
1174
  - **`agent-dispatch.mjs` is the home for the same reason the 2026-07-31 entry gives**: it fires at every depth and is the only seam that reaches a helper, whose dispatch prompt is otherwise whatever its parent thought to write. The root worker contract carries no equivalent — it reaches the one agent that cannot be stranded this way.
1171
1175
  - **The same change CORRECTED the nested-collection sentence**, which had promised since 2026-07-31 that a helper's *"completion is delivered to you automatically"*. It is not, and the experiment is one dispatch: a child told to dispatch one helper and stop the instant the Agent tool returned came back `DISPATCHED: yes / SAW_HELPER_REPLY: no`, and was never resumed to read the reply. That sentence sat four paragraphs below the new rule and is exactly what a helper told not to wait would reason its way back to, so it now reads *"a helper cannot wake you either: a dispatcher that stops is never resumed to read the reply"*. The anti-polling instruction the 2026-07-31 entry wrote it to carry — the `.output` symlink, the unreliable `"type":"result"` record — is untouched; only its false premise is. It also strengthens the 2026-08-04 default-off rule with a mechanism rather than a preference: a child that fans out cannot collect what it dispatched.
1172
1176
  - **Rejected: denying `run_in_background:true` from a sub-agent in `bash-background.mjs`.** The hook input does identify a child (`agent_id`, which `scratchpad.mjs` already reads), so it is available — but a helper launching several builds and collecting them inside one turn is legitimate, and the foreground cap makes a blanket denial actively worse. Same call as the depth-2 DENY rejected on 2026-07-31: too blunt for a hook that exists because helpers are allowed.
1177
+
1178
+ ## 2026-10-09: agents steer each other — `mcp__frizz__steer` between threads, `SendMessage` by agent id inside one
1179
+
1180
+ The maintainer, after a worker asked to send an audit's results to a resting thread spent sixteen tool calls finding the board's `followUp` route, the slug and the session id, and then curled it: *"We need to educate and encourage sub-agents to steer each other. And provide better mechanisms for doing so."*
1181
+
1182
+ - **Between threads: `steer`, a frizz MCP tool over a new `steerThread` RPC.** Claude Code's cross-session `SendMessage` reaches only a session whose process is live, so a resting thread had no channel at all short of the board's own RPC. `steerThread` is the operator's follow-up delivery (one shared `deliverFollowUp` in `router.ts`), so it wakes a resting thread, queues into a running one, and reopens a done one. The server reads the target's current session itself and stamps the sender's name from its own row; the shim takes the sender from its env. The body arrives wrapped in `<thread-message from-thread=… from-title=…>` with a guidance line naming the sender's slug, and the chat draws it as the existing "Message from «thread»" hairline. Same project only, as `spawn_thread` is.
1183
+ - **`spawn_thread` now names the spawner at the end of the child's prompt**, so a spawned thread asked for results can `steer` them back. Its "results NEVER come back to you" premise was true only because nothing could carry them; the doctrine (last resort, do-or-ask first) is unchanged.
1184
+ - **Inside one session: measured, then taught.** Measured live on Claude Code 2.1.295 (2026-10-09, headless `claude -p` sessions, read off the sub-agent transcripts and token files each recipient wrote): a parent's `SendMessage` to a RUNNING child's full agent id is delivered when the child's current tool call returns; a child's `SendMessage` to a running sibling's id is delivered the same way, and to a finished sibling's id resumes it. Only the full id resolves — a prefix, the description or the `subagent_type` answers `No agent named '<x>' is reachable`. Children have no `ListAgents`, so a sibling is reachable only by an id someone hands it, or by replying to the `from=` of a message it received. The epilogue gains one sentence for the sideways channels; the worker contract gains one paragraph under Sub-agents and a short section for `steer`.
1185
+ - **Rejected: a separate tag under the `<frizz-…>` prefix.** That prefix is Frizz's plumbing (`NOISE_PREFIXES`), which the transcript drops whole; the first draft's `<frizz-thread-message>` vanished from the chat entirely.
@@ -54,7 +54,9 @@ const SPAWN_THREAD = {
54
54
  "lands on YOUR card under one review), do that instead; if the human should choose, ASK instead. " +
55
55
  "Spawn a brand-new, separate top-level frizz thread — its own board card, session, and scratchpad, " +
56
56
  "driving INDEPENDENTLY. This is FIRE-AND-FORGET: the new thread reports to the HUMAN on the board via " +
57
- "its own final message, and its results NEVER come back to you, the caller. It is NOT an in-session " +
57
+ "its own final message, and its results come back to you, the caller, only if it sends them with " +
58
+ "`steer` — which its prompt is told it can, and which you must ASK for in that prompt if you need " +
59
+ "them. You cannot wait on it as you wait on a sub-agent. It is NOT an in-session " +
58
60
  "sub-agent. It returns only the new thread's slug and a ready-to-paste markdown link " +
59
61
  "`[title](/thread/<slug>)` that opens the thread in the frizz drawer — put that link in your handoff. " +
60
62
  "USE IT ONLY for a distinct, self-contained effort that belongs on the board in its own right and whose " +
@@ -63,9 +65,10 @@ const SPAWN_THREAD = {
63
65
  "those are in-session sub-agents (Claude: the Agent tool with `run_in_background`; Codex: native " +
64
66
  "delegation), which return their findings to you. Spawning such a helper here STRANDS it — its work lands " +
65
67
  "on another card and never reaches you, so you gain nothing. " +
66
- "Because nothing it learns ever returns to you OR to its siblings, a chain of spawned threads re-derives " +
67
- "the same facts in parallel and nobody notices — measured here: one thread spawned four, three of those " +
68
- "spawned more, and three descendants independently rediscovered the same root cause over twenty hours. " +
68
+ "Because nothing it learns returns to you OR to its siblings unless somebody steers it across, a chain of " +
69
+ "spawned threads re-derives the same facts in parallel and nobody notices — measured here: one thread " +
70
+ "spawned four, three of those spawned more, and three descendants independently rediscovered the same " +
71
+ "root cause over twenty hours. " +
69
72
  "Spawn only when the work genuinely cannot ride on your own card: a different repo, a different long-lived " +
70
73
  "runtime, an effort that must outlive yours. Never spawn merely to clear your own `done` fence. " +
71
74
  "You MUST deliberately choose `model` and `effort` to match the NEW thread's task complexity — they are " +
@@ -502,8 +505,10 @@ function questionSchema(depth) {
502
505
  recommended: {
503
506
  type: "boolean",
504
507
  description:
505
- "Mark the ONE option you would take, and put it first. At most one per question — a " +
506
- "recommendation on two of three choices says nothing. IF YOU CAN MARK ONE, ASK YOURSELF WHY " +
508
+ "Mark the ONE option you would take, and put it first. At most one per pick-one question — a " +
509
+ "recommendation on two of three choices says nothing. ON A `multi`, MARK EVERY OPTION YOU " +
510
+ "WOULD TICK, or none: the human ticks several there, so one mark alone reads as \"pick only " +
511
+ "this\". IF YOU CAN MARK ONE, ASK YOURSELF WHY " +
507
512
  "YOU ARE ASKING: you already know the answer, so implement it and say which way you went. " +
508
513
  "This is for the fork you genuinely cannot take yourself.",
509
514
  },
@@ -690,6 +695,59 @@ const SECRET = {
690
695
  },
691
696
  }
692
697
 
698
+ // STEER (2026-10-09): one thread messaging ANOTHER thread of the same project. Claude Code's own
699
+ // cross-session `SendMessage` reaches a session only while its process is live, so a worker told to hand
700
+ // its results to a resting thread had no tool for it, and went looking for the board's `followUp` route
701
+ // to curl by hand — sixteen tool calls to find the route, the slug and the session id. This is that
702
+ // delivery, as a tool: the server reads the target's current session, wraps the body so the receiver
703
+ // and the chat both know who sent it, and wakes, queues into, or reopens the target as a human
704
+ // follow-up would.
705
+ const STEER = {
706
+ name: "steer",
707
+ description:
708
+ "SEND A MESSAGE TO ANOTHER THREAD on this board, running or resting, and it reads it as its next " +
709
+ "input. A running thread reads it at its next tool boundary; a resting thread is WOKEN by it and " +
710
+ "starts a turn on it; a thread marked done is reopened. The receiver sees which thread sent it and " +
711
+ "can answer with this same tool.\n\n" +
712
+ "USE IT INSTEAD OF RELAYING THROUGH THE HUMAN. Whenever another thread needs what you have, send it " +
713
+ "there yourself: results a thread is waiting on (\"when the audit is done, send the results to " +
714
+ "<thread>\"), a finding that changes another thread's work (it is chasing the bug you just fixed, it " +
715
+ "depends on a commit you just landed, it is about to redo what you already did), or the answer to a " +
716
+ "message another thread sent you. A finding that sits in your handoff until the human copies it " +
717
+ "across costs them a trip and the other thread hours; sending it costs one call. A thread you spawned " +
718
+ "with `spawn_thread`, or the one that spawned you, is reachable the same way.\n\n" +
719
+ "WRITE IT TO BE READ COLD. The receiver has none of your context: say what you found or what you " +
720
+ "need, with the evidence, paths, commits and links it needs to act — in one complete message, not a " +
721
+ "drip of partial ones. Every steer costs the receiver a turn on its full context, so do not send " +
722
+ "progress chatter, and do not send what it did not need.\n\n" +
723
+ "IT IS A COLLEAGUE'S MESSAGE, NOT THE HUMAN'S: it does not override the human's instructions to that " +
724
+ "thread, and it is not a way to hand off work the human did not ask for. Nothing waits on a reply " +
725
+ "unless your message asks for one, and you do not need to rest waiting for it: a reply wakes you " +
726
+ "whenever it comes, even after `done`.\n\n" +
727
+ "NOT FOR YOUR OWN SUB-AGENTS — those are inside your session; reach them with `SendMessage` to " +
728
+ "their agent id. Not for your own thread, and not across projects: `to` names a thread on THIS " +
729
+ "project's board.",
730
+ inputSchema: {
731
+ type: "object",
732
+ properties: {
733
+ to: {
734
+ type: "string",
735
+ description:
736
+ "The thread to message: its slug (`fix-queue-focus`), or any link naming it — the " +
737
+ "`[title](/thread/<slug>)` link `spawn_thread` returns, or a full board URL such as " +
738
+ "`http://localhost:9393/project/frizz/thread/<slug>/full`.",
739
+ },
740
+ message: {
741
+ type: "string",
742
+ description:
743
+ "The message, as markdown. Self-contained: the receiver has none of your context. It arrives " +
744
+ "wrapped with your thread's name and slug, so do not sign it.",
745
+ },
746
+ },
747
+ required: ["to", "message"],
748
+ },
749
+ }
750
+
693
751
  const DONE = {
694
752
  name: "done",
695
753
  description:
@@ -818,9 +876,10 @@ const UNLINK = {
818
876
  },
819
877
  }
820
878
 
821
- // WATCH_ISSUE rides at the END (2026-09-14): the tool list is read by position in frizz-mcp.test.ts, and a
822
- // worker's runtime reads it by name, so the order costs nothing and appending breaks nothing.
823
- const TOOLS = [SPAWN_THREAD, GOAL, TIMER, WATCH_PR, WATCH, UNWATCH, ASK, UNASK, DONE, TITLE, ACTIVITY, LINK, UNLINK, WATCH_ISSUE, SECRET]
879
+ // WATCH_ISSUE rides at the END (2026-09-14), and SECRET and STEER after it: the tool list is read by position
880
+ // in frizz-mcp.test.ts, and a worker's runtime reads it by name, so the order costs nothing and appending
881
+ // breaks nothing.
882
+ const TOOLS = [SPAWN_THREAD, GOAL, TIMER, WATCH_PR, WATCH, UNWATCH, ASK, UNASK, DONE, TITLE, ACTIVITY, LINK, UNLINK, WATCH_ISSUE, SECRET, STEER]
824
883
 
825
884
  /** @type {Record<string, (args: Record<string, unknown>) => Promise<string>>} */
826
885
  const HANDLERS = {
@@ -839,6 +898,35 @@ const HANDLERS = {
839
898
  [ACTIVITY.name]: activity,
840
899
  [LINK.name]: link,
841
900
  [UNLINK.name]: unlink,
901
+ [STEER.name]: steer,
902
+ }
903
+
904
+ // The slug out of whatever a worker has in hand for a thread: the slug itself, the `[title](/thread/<slug>)`
905
+ // link spawn_thread returns, or a board URL (`…/project/<p>/thread/<slug>/full`).
906
+ const THREAD_LINK = /\/thread\/([^/?#)\s]+)/
907
+
908
+ /** The `steer` handler: deliver a message into ANOTHER thread of this project.
909
+ * @param {Record<string, unknown>} args @returns {Promise<string>} */
910
+ async function steer(args) {
911
+ const raw = typeof args.to === "string" ? args.to.trim() : ""
912
+ const message = typeof args.message === "string" ? args.message.trim() : ""
913
+ if (!raw) throw new Error("`to` is required — the slug of the thread to message, or a link naming it")
914
+ if (!message) throw new Error("`message` is required and must be a non-empty string")
915
+ const to = decodeURIComponent(THREAD_LINK.exec(raw)?.[1] ?? raw)
916
+ // THE SENDER IS THE ENV'S, never the model's: the receiver is told which thread sent this, and that
917
+ // has to be true.
918
+ const result = (await callRpc("steerThread", { from: threadSlug(), to, message }))?.result
919
+ if (!result?.slug) throw new Error(`steerThread returned no receipt: ${JSON.stringify(result)?.slice(0, 300)}`)
920
+ const how = result.delivery === "running"
921
+ ? "It is mid-turn, so it reads this at its next tool boundary."
922
+ : result.delivery === "reopened"
923
+ ? "It had been marked done; this message reopened it and started a turn."
924
+ : "It was resting; this message woke it and started a turn."
925
+ return (
926
+ `Delivered to «${result.title}» (\`${result.slug}\`). ${how}\n\n` +
927
+ "Its reply, if it sends one, arrives as your next input and wakes you — do not rest waiting for it. " +
928
+ `Link for your handoff: [${result.title}](/thread/${result.slug})`
929
+ )
842
930
  }
843
931
 
844
932
  /** @param {Record<string, unknown>} args @returns {Promise<string>} */
@@ -1120,8 +1208,15 @@ async function spawnThread(args) {
1120
1208
  const effort = typeof args.effort === "string" ? args.effort.trim() : ""
1121
1209
  if (!effort) throw new Error("`effort` is required — choose one by complexity (low/medium/high/xhigh/max). There is no default.")
1122
1210
 
1211
+ // THE WAY BACK. A spawned thread starts with nothing but this prompt, so without its spawner's slug it
1212
+ // could not `steer` anything back even when asked to — the footer names it, once, at the end.
1213
+ const parent = process.env.FRIZZ_THREAD_SLUG || process.env.FRIZZ_THREAD
1214
+ const footer = parent
1215
+ ? `\n\n---\nSpawned by the Frizz thread \`${parent}\`. If this prompt asks for results back, or you find ` +
1216
+ `something that thread must know, send it there with the frizz \`steer\` tool (\`to: "${parent}"\`).`
1217
+ : ""
1123
1218
  /** @type {Record<string, unknown>} */
1124
- const body = { prompt, model, effort }
1219
+ const body = { prompt: prompt + footer, model, effort }
1125
1220
  if (typeof args.title === "string" && args.title.trim()) body.title = args.title.trim()
1126
1221
  if (args.backend === "claude" || args.backend === "codex") body.backend = args.backend
1127
1222
 
@@ -1153,7 +1248,9 @@ async function spawnThread(args) {
1153
1248
  const label = typeof body.title === "string" ? body.title : slug
1154
1249
  return (
1155
1250
  `Spawned a new frizz thread \`${slug}\`. It is now on the board driving independently — it reports ` +
1156
- `to the human via its own final message, NOT back to you, so do not wait on a result from it.\n\n` +
1251
+ `to the human via its own final message, so do not wait on a result from it. It knows your slug: if ` +
1252
+ `its prompt asked for results back, they arrive as a \`steer\` that wakes you. You can message it ` +
1253
+ `the same way, with \`steer\` and \`to: "${slug}"\`.\n\n` +
1157
1254
  `Paste this link to let the human open it in the drawer:\n\n[${label}](/thread/${slug})`
1158
1255
  )
1159
1256
  }
@@ -8,7 +8,8 @@
8
8
  // wrong and never returns cleanly), so scrub both silently.
9
9
  // 3) AUTO-APPEND a short ORCHESTRATION EPILOGUE carrying only what a helper cannot discover on
10
10
  // its own: that its final message is the return value, that nothing can WAKE it so it must not
11
- // end a turn on a waiter, the `SendMessage({to: "main"})` upward channel, the own-file rule for
11
+ // end a turn on a waiter, the `SendMessage({to: "main"})` upward channel and its sideways forms (a
12
+ // sibling by agent id, another thread by `mcp__frizz__steer`), the own-file rule for
12
13
  // the scratch directory, no fan-out of its own unless asked, and how a helper it DID dispatch
13
14
  // is collected. It carries no handoff format and no build, test, git or process policy — the
14
15
  // maintainer had the handoff-format doctrine cut on 2026-08-26.
@@ -70,7 +71,7 @@ const EPILOGUE = `
70
71
  [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: what you did, what you verified, what remains.
71
72
  NOTHING CAN WAKE YOU — ending your turn IS your return. A job you backgrounded (Bash \`run_in_background:true\` above all) reports to your DISPATCHER, never to you, so a turn that ends while one is outstanding hands back unfinished work and leaves its result somewhere you will never read. So never end a turn waiting for something to finish: run long commands in the FOREGROUND, and where one would outrun the foreground limit, make the command itself loop until its own terminal condition rather than backgrounding it. If you did background something, collect it in the SAME turn. And if your dispatcher named a scratch directory, write anything you would not want to lose into your own file there AS YOU GO — a turn that ends early takes with it everything you had neither written down nor said.
72
73
  If the worker names its scratch directory: Write your OWN file there — never edit or delete a file another agent wrote. That file is Frizz coordination state, not a project deliverable or source edit, so it stays allowed under limits such as "write only <path>" or "do not modify the repo"; never classify it as unauthorized or roll it back. Every other file is governed by your delegated authority; its location alone neither permits nor forbids editing. Do not edit other \`.frizz/\` state unless your prompt asks.
73
- Upward channel: \`SendMessage({to: "main", summary: "<5-10 words>", message: "…"})\` reaches your dispatcher while you work (load it first with ToolSearch \`select:SendMessage\` if it is deferred). Use it only when the dispatcher acting before you finish would change the outcome — a blocker, a milestone another task needs, instructions that should change — not for progress updates.
74
+ Upward channel: \`SendMessage({to: "main", summary: "<5-10 words>", message: "…"})\` reaches your dispatcher while you work (load it first with ToolSearch \`select:SendMessage\` if it is deferred). Use it only when the dispatcher acting before you finish would change the outcome — a blocker, a milestone another task needs, instructions that should change — not for progress updates. The same tool reaches a SIBLING sub-agent by the full agent id your prompt gives you (a message from one arrives as \`<agent-message from="<id>">\`; reply to that id), and \`mcp__frizz__steer\` reaches another Frizz THREAD by its slug: when your prompt says your result belongs to another thread or sibling, send it there yourself before you return, and say in your final message that you did.
74
75
  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.
75
76
  If your prompt DOES ask you to dispatch a helper, the rule above still binds — a helper cannot wake you either: a dispatcher that stops is never resumed to read the reply. So collect it before your turn ends, or do not dispatch it. Never hand-roll a wait loop over a helper's transcript or \`.output\` path: that path is a SYMLINK (\`stat\` without \`-L\` reports the link's own ~150-byte size and frozen mtime) and the \`"type":"result"\` record is not reliably written, so a helper working hard reads as tiny, stale and dead, and you will discard live work and redo it. Judge a helper only by what it actually returns to you, and give it a \`description\` naming its narrower slice.`;
76
77
 
@@ -94,8 +94,17 @@ const RULES = [
94
94
  // `default`/`plan` got there because a human moved it there (the live per-thread permission
95
95
  // control), and auto-approving would silently overrule that intent. This is what makes a genuine
96
96
  // lower-permission mode usable today: switch a thread to `default` and its prompts come back.
97
+ //
98
+ // `bypassPermissions` IS NOT ONE OF THEM. It is the one mode MORE permissive than `auto`, and the
99
+ // operator chose it (Settings, or the same per-thread control) precisely to stop being asked — but
100
+ // Claude Code still raises a prompt for some commands under bypass, and this rule read "not auto"
101
+ // as "restrictive", so a bypass thread parked on approval cards an auto thread never showed
102
+ // (maintainer 2026-10-10: all four markers on the machine that day were bypass-mode defers). It
103
+ // falls through to `worker-autonomy` now, behind the two refusals above. Any OTHER mode string,
104
+ // including one this table has never heard of, still defers: unknown must mean ask.
97
105
  id: 'restrictive-mode',
98
- test: (i) => typeof i.permission_mode === 'string' && i.permission_mode !== 'auto',
106
+ test: (i) =>
107
+ typeof i.permission_mode === 'string' && i.permission_mode !== 'auto' && i.permission_mode !== 'bypassPermissions',
99
108
  decision: 'defer',
100
109
  reason: 'The thread is in a restrictive permission mode, so this request is left for a human to answer.',
101
110
  },
@@ -1 +1 @@
1
- import{m as e,t}from"./mermaid-parser.core-DoSxbCDI.js";import{n}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as r}from"./src-CS_pkXwT.js";import"./chunk-WYO6CB5R-Bp_ka9na.js";import"./chunk-VAUOI2AC-BgJghXkI.js";import{n as i,r as a,t as o}from"./chunk-MOJQB5TN-BSorOCQZ.js";import{t as s}from"./chunk-JWPE2WC7-DVXcaiue.js";var c=e().RailroadAbnf.parser.LangiumParser,l=n(e=>{let t=e.alternatives.map(u);return t.length===1?t[0]:{type:`choice`,alternatives:t}},`transformAlternation`),u=n(e=>{let t=e.elements.map(f);return t.length===1?t[0]:{type:`sequence`,elements:t}},`transformConcatenation`),d=n(e=>{if(e.includes(`*`)){let[t,n]=e.split(`*`);return{min:t?parseInt(t,10):0,max:n?parseInt(n,10):1/0}}let t=parseInt(e,10);return{min:t,max:t}},`parseRepeat`),f=n(e=>{let t=p(e.primary);if(!e.repeat)return t;let{min:n,max:r}=d(e.repeat);return n===0&&r===1?{type:`optional`,element:t}:{type:`repetition`,element:t,min:n,max:r}},`transformElement`),p=n(e=>{switch(e.$type){case`AbnfStringLiteral`:return{type:`terminal`,value:e.value};case`AbnfNumVal`:return{type:`terminal`,value:e.value};case`AbnfRuleName`:return{type:`nonterminal`,name:e.name};case`AbnfGroup`:return l(e.element);case`AbnfOptionalGroup`:return{type:`optional`,element:l(e.element)};default:throw Error(`Unsupported ABNF primary node: ${e.$type}`)}},`transformPrimary`),m=n(e=>({name:e.name,definition:l(e.definition)}),`transformRule`),h=n(e=>{s(e,o),e.title&&o.setTitle(e.title),e.rules.map(e=>o.addRule(m(e)))},`populateDb`),g={parser:{parse:n(e=>{o.clear(),r.debug(`[ABNF Parser] Starting Langium parse`);let n=c.parse(e);if(n.lexerErrors.length>0||n.parserErrors.length>0)throw new t(n);let i=n.value;r.debug(`[ABNF Parser] Parsed rules:`,i.rules.length),h(i),r.debug(`[ABNF Parser] Parse complete`)},`parse`),parser:{yy:o}},db:o,renderer:a,styles:i};export{g as diagram};
1
+ import{m as e,t}from"./mermaid-parser.core-BiJ3pVQT.js";import{n}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as r}from"./src-BygbIYKj.js";import"./chunk-WYO6CB5R-CQAWjeZH.js";import"./chunk-VAUOI2AC-DRKYvsWa.js";import{n as i,r as a,t as o}from"./chunk-MOJQB5TN-g8M_GVaO.js";import{t as s}from"./chunk-JWPE2WC7-DVXcaiue.js";var c=e().RailroadAbnf.parser.LangiumParser,l=n(e=>{let t=e.alternatives.map(u);return t.length===1?t[0]:{type:`choice`,alternatives:t}},`transformAlternation`),u=n(e=>{let t=e.elements.map(f);return t.length===1?t[0]:{type:`sequence`,elements:t}},`transformConcatenation`),d=n(e=>{if(e.includes(`*`)){let[t,n]=e.split(`*`);return{min:t?parseInt(t,10):0,max:n?parseInt(n,10):1/0}}let t=parseInt(e,10);return{min:t,max:t}},`parseRepeat`),f=n(e=>{let t=p(e.primary);if(!e.repeat)return t;let{min:n,max:r}=d(e.repeat);return n===0&&r===1?{type:`optional`,element:t}:{type:`repetition`,element:t,min:n,max:r}},`transformElement`),p=n(e=>{switch(e.$type){case`AbnfStringLiteral`:return{type:`terminal`,value:e.value};case`AbnfNumVal`:return{type:`terminal`,value:e.value};case`AbnfRuleName`:return{type:`nonterminal`,name:e.name};case`AbnfGroup`:return l(e.element);case`AbnfOptionalGroup`:return{type:`optional`,element:l(e.element)};default:throw Error(`Unsupported ABNF primary node: ${e.$type}`)}},`transformPrimary`),m=n(e=>({name:e.name,definition:l(e.definition)}),`transformRule`),h=n(e=>{s(e,o),e.title&&o.setTitle(e.title),e.rules.map(e=>o.addRule(m(e)))},`populateDb`),g={parser:{parse:n(e=>{o.clear(),r.debug(`[ABNF Parser] Starting Langium parse`);let n=c.parse(e);if(n.lexerErrors.length>0||n.parserErrors.length>0)throw new t(n);let i=n.value;r.debug(`[ABNF Parser] Parsed rules:`,i.rules.length),h(i),r.debug(`[ABNF Parser] Parse complete`)},`parse`),parser:{yy:o}},db:o,renderer:a,styles:i};export{g as diagram};
@@ -1 +1 @@
1
- import{n as e,t}from"./path-BWPyau1x.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-CRFAJ8CQ.js";function m(e){return e.innerRadius}function h(e){return e.outerRadius}function g(e){return e.startAngle}function _(e){return e.endAngle}function v(e){return e&&e.padAngle}function y(e,t,n,r,i,a,o,s){var c=n-e,l=r-t,u=o-i,d=s-a,f=d*c-u*l;if(!(f*f<1e-12))return f=(u*(t-a)-d*(e-i))/f,[e+f*c,t+f*l]}function b(e,t,n,r,i,a,o){var c=e-n,l=t-r,u=(o?a:-a)/d(c*c+l*l),f=u*l,p=-u*c,m=e+f,h=t+p,g=n+f,_=r+p,v=(m+g)/2,y=(h+_)/2,b=g-m,x=_-h,S=b*b+x*x,C=i-a,w=m*_-g*h,T=(x<0?-1:1)*d(s(0,C*C*S-w*w)),E=(w*x-b*T)/S,D=(-w*b-x*T)/S,O=(w*x+b*T)/S,k=(-w*b+x*T)/S,A=E-v,j=D-y,M=O-v,N=k-y;return A*A+j*j>M*M+N*N&&(E=O,D=k),{cx:E,cy:D,x01:-f,y01:-p,x11:E*(i/C-1),y11:D*(i/C-1)}}function x(){var s=m,x=h,S=e(0),C=null,w=g,T=_,E=v,D=null,O=t(k);function k(){var e,t,m=+s.apply(this,arguments),h=+x.apply(this,arguments),g=w.apply(this,arguments)-r,_=T.apply(this,arguments)-r,v=l(_-g),k=_>g;if(D||=e=O(),h<m&&(t=h,h=m,m=t),!(h>1e-12))D.moveTo(0,0);else if(v>c-1e-12)D.moveTo(h*u(g),h*a(g)),D.arc(0,0,h,g,_,!k),m>1e-12&&(D.moveTo(m*u(_),m*a(_)),D.arc(0,0,m,_,g,k));else{var A=g,j=_,M=g,N=_,P=v,F=v,I=E.apply(this,arguments)/2,L=I>1e-12&&(C?+C.apply(this,arguments):d(m*m+h*h)),R=p(l(h-m)/2,+S.apply(this,arguments)),z=R,B=R,V,H;if(L>1e-12){var U=o(L/m*a(I)),W=o(L/h*a(I));(P-=U*2)>1e-12?(U*=k?1:-1,M+=U,N-=U):(P=0,M=N=(g+_)/2),(F-=W*2)>1e-12?(W*=k?1:-1,A+=W,j-=W):(F=0,A=j=(g+_)/2)}var G=h*u(A),K=h*a(A),q=m*u(N),J=m*a(N);if(R>1e-12){var Y=h*u(j),X=h*a(j),Z=m*u(M),Q=m*a(M),$;if(v<i)if($=y(G,K,Z,Q,Y,X,q,J)){var ee=G-$[0],te=K-$[1],ne=Y-$[0],re=X-$[1],ie=1/a(f((ee*ne+te*re)/(d(ee*ee+te*te)*d(ne*ne+re*re)))/2),ae=d($[0]*$[0]+$[1]*$[1]);z=p(R,(m-ae)/(ie-1)),B=p(R,(h-ae)/(ie+1))}else z=B=0}F>1e-12?B>1e-12?(V=b(Z,Q,G,K,h,B,k),H=b(Y,X,q,J,h,B,k),D.moveTo(V.cx+V.x01,V.cy+V.y01),B<R?D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,h,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),!k),D.arc(H.cx,H.cy,B,n(H.y11,H.x11),n(H.y01,H.x01),!k))):(D.moveTo(G,K),D.arc(0,0,h,A,j,!k)):D.moveTo(G,K),!(m>1e-12)||!(P>1e-12)?D.lineTo(q,J):z>1e-12?(V=b(q,J,Y,X,m,-z,k),H=b(G,K,Z,Q,m,-z,k),D.lineTo(V.cx+V.x01,V.cy+V.y01),z<R?D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,m,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),k),D.arc(H.cx,H.cy,z,n(H.y11,H.x11),n(H.y01,H.x01),!k))):D.arc(0,0,m,N,M,k)}if(D.closePath(),e)return D=null,e+``||null}return k.centroid=function(){var e=(+s.apply(this,arguments)+ +x.apply(this,arguments))/2,t=(+w.apply(this,arguments)+ +T.apply(this,arguments))/2-i/2;return[u(t)*e,a(t)*e]},k.innerRadius=function(t){return arguments.length?(s=typeof t==`function`?t:e(+t),k):s},k.outerRadius=function(t){return arguments.length?(x=typeof t==`function`?t:e(+t),k):x},k.cornerRadius=function(t){return arguments.length?(S=typeof t==`function`?t:e(+t),k):S},k.padRadius=function(t){return arguments.length?(C=t==null?null:typeof t==`function`?t:e(+t),k):C},k.startAngle=function(t){return arguments.length?(w=typeof t==`function`?t:e(+t),k):w},k.endAngle=function(t){return arguments.length?(T=typeof t==`function`?t:e(+t),k):T},k.padAngle=function(t){return arguments.length?(E=typeof t==`function`?t:e(+t),k):E},k.context=function(e){return arguments.length?(D=e??null,k):D},k}export{x as t};
1
+ import{n as e,t}from"./path-BWPyau1x.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-Cewx01EF.js";function m(e){return e.innerRadius}function h(e){return e.outerRadius}function g(e){return e.startAngle}function _(e){return e.endAngle}function v(e){return e&&e.padAngle}function y(e,t,n,r,i,a,o,s){var c=n-e,l=r-t,u=o-i,d=s-a,f=d*c-u*l;if(!(f*f<1e-12))return f=(u*(t-a)-d*(e-i))/f,[e+f*c,t+f*l]}function b(e,t,n,r,i,a,o){var c=e-n,l=t-r,u=(o?a:-a)/d(c*c+l*l),f=u*l,p=-u*c,m=e+f,h=t+p,g=n+f,_=r+p,v=(m+g)/2,y=(h+_)/2,b=g-m,x=_-h,S=b*b+x*x,C=i-a,w=m*_-g*h,T=(x<0?-1:1)*d(s(0,C*C*S-w*w)),E=(w*x-b*T)/S,D=(-w*b-x*T)/S,O=(w*x+b*T)/S,k=(-w*b+x*T)/S,A=E-v,j=D-y,M=O-v,N=k-y;return A*A+j*j>M*M+N*N&&(E=O,D=k),{cx:E,cy:D,x01:-f,y01:-p,x11:E*(i/C-1),y11:D*(i/C-1)}}function x(){var s=m,x=h,S=e(0),C=null,w=g,T=_,E=v,D=null,O=t(k);function k(){var e,t,m=+s.apply(this,arguments),h=+x.apply(this,arguments),g=w.apply(this,arguments)-r,_=T.apply(this,arguments)-r,v=l(_-g),k=_>g;if(D||=e=O(),h<m&&(t=h,h=m,m=t),!(h>1e-12))D.moveTo(0,0);else if(v>c-1e-12)D.moveTo(h*u(g),h*a(g)),D.arc(0,0,h,g,_,!k),m>1e-12&&(D.moveTo(m*u(_),m*a(_)),D.arc(0,0,m,_,g,k));else{var A=g,j=_,M=g,N=_,P=v,F=v,I=E.apply(this,arguments)/2,L=I>1e-12&&(C?+C.apply(this,arguments):d(m*m+h*h)),R=p(l(h-m)/2,+S.apply(this,arguments)),z=R,B=R,V,H;if(L>1e-12){var U=o(L/m*a(I)),W=o(L/h*a(I));(P-=U*2)>1e-12?(U*=k?1:-1,M+=U,N-=U):(P=0,M=N=(g+_)/2),(F-=W*2)>1e-12?(W*=k?1:-1,A+=W,j-=W):(F=0,A=j=(g+_)/2)}var G=h*u(A),K=h*a(A),q=m*u(N),J=m*a(N);if(R>1e-12){var Y=h*u(j),X=h*a(j),Z=m*u(M),Q=m*a(M),$;if(v<i)if($=y(G,K,Z,Q,Y,X,q,J)){var ee=G-$[0],te=K-$[1],ne=Y-$[0],re=X-$[1],ie=1/a(f((ee*ne+te*re)/(d(ee*ee+te*te)*d(ne*ne+re*re)))/2),ae=d($[0]*$[0]+$[1]*$[1]);z=p(R,(m-ae)/(ie-1)),B=p(R,(h-ae)/(ie+1))}else z=B=0}F>1e-12?B>1e-12?(V=b(Z,Q,G,K,h,B,k),H=b(Y,X,q,J,h,B,k),D.moveTo(V.cx+V.x01,V.cy+V.y01),B<R?D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,h,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),!k),D.arc(H.cx,H.cy,B,n(H.y11,H.x11),n(H.y01,H.x01),!k))):(D.moveTo(G,K),D.arc(0,0,h,A,j,!k)):D.moveTo(G,K),!(m>1e-12)||!(P>1e-12)?D.lineTo(q,J):z>1e-12?(V=b(q,J,Y,X,m,-z,k),H=b(G,K,Z,Q,m,-z,k),D.lineTo(V.cx+V.x01,V.cy+V.y01),z<R?D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,m,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),k),D.arc(H.cx,H.cy,z,n(H.y11,H.x11),n(H.y01,H.x01),!k))):D.arc(0,0,m,N,M,k)}if(D.closePath(),e)return D=null,e+``||null}return k.centroid=function(){var e=(+s.apply(this,arguments)+ +x.apply(this,arguments))/2,t=(+w.apply(this,arguments)+ +T.apply(this,arguments))/2-i/2;return[u(t)*e,a(t)*e]},k.innerRadius=function(t){return arguments.length?(s=typeof t==`function`?t:e(+t),k):s},k.outerRadius=function(t){return arguments.length?(x=typeof t==`function`?t:e(+t),k):x},k.cornerRadius=function(t){return arguments.length?(S=typeof t==`function`?t:e(+t),k):S},k.padRadius=function(t){return arguments.length?(C=t==null?null:typeof t==`function`?t:e(+t),k):C},k.startAngle=function(t){return arguments.length?(w=typeof t==`function`?t:e(+t),k):w},k.endAngle=function(t){return arguments.length?(T=typeof t==`function`?t:e(+t),k):T},k.padAngle=function(t){return arguments.length?(E=typeof t==`function`?t:e(+t),k):E},k.context=function(e){return arguments.length?(D=e??null,k):D},k}export{x as t};
@@ -0,0 +1 @@
1
+ import"./chunk-KEIR6QF5-BfrZ3jm6.js";import{M as e}from"./mermaid-parser.core-BiJ3pVQT.js";export{e as createArchitectureServices};