frizz-server 0.15.20 → 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.
- package/dist/claude-agent-broker.js +24 -12
- package/dist/dev-child.js +111 -45
- package/package.json +1 -1
- package/runtime/cc-worker/DECISIONS.md +6 -2
- package/runtime/cc-worker/bin/frizz-mcp.mjs +4 -2
- package/runtime/cc-worker/hooks/perm-policy.mjs +10 -1
- package/web-dist/assets/{abnfDiagram-VRR7QNED-B61nQEjt.js → abnfDiagram-VRR7QNED-DqTQZ2Ex.js} +1 -1
- package/web-dist/assets/{arc-CR8_qWI3.js → arc-t56zg8G8.js} +1 -1
- package/web-dist/assets/architecture-TIHT7OUA-Czzg2iAA.js +1 -0
- package/web-dist/assets/{architectureDiagram-ZJ3FMSHR-6sc4SDOh.js → architectureDiagram-ZJ3FMSHR-CSdC9-eQ.js} +1 -1
- package/web-dist/assets/{blockDiagram-677ZJIJ3-p-DPTDGB.js → blockDiagram-677ZJIJ3-Dmw8EopV.js} +1 -1
- package/web-dist/assets/{c4Diagram-LMCZKHZV-cqvAqZE2.js → c4Diagram-LMCZKHZV-BCRaFnis.js} +1 -1
- package/web-dist/assets/channel-CxehNUC2.js +1 -0
- package/web-dist/assets/{chunk-32BRIVSS-BNnoKILR.js → chunk-32BRIVSS-DqOJDRw_.js} +1 -1
- package/web-dist/assets/{chunk-52WLFC77-BmHIWiVu.js → chunk-52WLFC77-BsibludT.js} +1 -1
- package/web-dist/assets/{chunk-C7G6YPKG-D7XYFno8.js → chunk-C7G6YPKG-D7Me5JQU.js} +1 -1
- package/web-dist/assets/{chunk-EX3LRPZG-BUViIha7.js → chunk-EX3LRPZG-CTa4YlOO.js} +1 -1
- package/web-dist/assets/{chunk-FWX5IMBZ-3x5Zky3W.js → chunk-FWX5IMBZ-CjqOt5Jn.js} +2 -2
- package/web-dist/assets/{chunk-HOUHSVGY-C6_RBSov.js → chunk-HOUHSVGY-BDIBDR-8.js} +1 -1
- package/web-dist/assets/{chunk-ICXQ74PX-NbVxQ4i1.js → chunk-ICXQ74PX-C4exiYRm.js} +1 -1
- package/web-dist/assets/{chunk-MOJQB5TN-nRMfcSHe.js → chunk-MOJQB5TN-g8M_GVaO.js} +1 -1
- package/web-dist/assets/{chunk-OGEWGWER-BbSXfbEB.js → chunk-OGEWGWER-C_80lLFe.js} +1 -1
- package/web-dist/assets/{chunk-PUDLZKDR-Byubn9VY.js → chunk-PUDLZKDR-B73Odmxv.js} +1 -1
- package/web-dist/assets/{chunk-Q4XR5HBZ-DLq-aZ3t.js → chunk-Q4XR5HBZ-D-VkroM1.js} +1 -1
- package/web-dist/assets/{chunk-RYQCIY6F-Dbt66M6V.js → chunk-RYQCIY6F-DmPJ8s-8.js} +1 -1
- package/web-dist/assets/{chunk-V7JOEXUC-DNFTmXz6.js → chunk-V7JOEXUC-BQKrRLYX.js} +1 -1
- package/web-dist/assets/{chunk-VAUOI2AC-QWrszv3X.js → chunk-VAUOI2AC-DRKYvsWa.js} +1 -1
- package/web-dist/assets/{chunk-VR4S4FIN-CJdyjwam.js → chunk-VR4S4FIN-DaMMs6V-.js} +1 -1
- package/web-dist/assets/{chunk-WYO6CB5R-D_786t-3.js → chunk-WYO6CB5R-CQAWjeZH.js} +1 -1
- package/web-dist/assets/{chunk-XXDRQBXY-Bd_2jBj_.js → chunk-XXDRQBXY-DJvt-abB.js} +1 -1
- package/web-dist/assets/{chunk-ZGVPDNZ5-DklPG-LG.js → chunk-ZGVPDNZ5-B1v24MrX.js} +1 -1
- package/web-dist/assets/classDiagram-OUVF2IWQ-BwIDe0nq.js +1 -0
- package/web-dist/assets/classDiagram-v2-EOCWNBFH-BwIDe0nq.js +1 -0
- package/web-dist/assets/{cose-bilkent-JH36ORCC-C4MtSvEs.js → cose-bilkent-JH36ORCC-CeNttASr.js} +1 -1
- package/web-dist/assets/{cynefin-VYW2F7L2-Dr0CmMQz.js → cynefin-VYW2F7L2-ClJzZ-Yx.js} +1 -1
- package/web-dist/assets/{cynefinDiagram-TSTJHNR4-BpHXKyDO.js → cynefinDiagram-TSTJHNR4-BCrL5Bu_.js} +1 -1
- package/web-dist/assets/{dagre-VKFMJZFB-CWAtKn43.js → dagre-VKFMJZFB-DO7qy19A.js} +1 -1
- package/web-dist/assets/{diagram-FQU43EPY-B_6PhpPG.js → diagram-FQU43EPY-KPbJc2w8.js} +1 -1
- package/web-dist/assets/{diagram-G47NLZAW-DPNrX-3a.js → diagram-G47NLZAW-9tqHFXzf.js} +1 -1
- package/web-dist/assets/{diagram-NH7WQ7WH-BL4nqAUm.js → diagram-NH7WQ7WH-BUbmU0cY.js} +1 -1
- package/web-dist/assets/{diagram-OA4YK3LP-CcFbtuCf.js → diagram-OA4YK3LP-QmMo96Qi.js} +1 -1
- package/web-dist/assets/{diagram-WEI45ONY-Bkl0nXre.js → diagram-WEI45ONY-BYAyhW16.js} +1 -1
- package/web-dist/assets/{dist-krVNNn4H.js → dist-Cewx01EF.js} +1 -1
- package/web-dist/assets/{ebnfDiagram-CCIWWBDH-C_51YQqw.js → ebnfDiagram-CCIWWBDH-BIMiEDl1.js} +1 -1
- package/web-dist/assets/{erDiagram-Q63AITRT-D8oBhiQB.js → erDiagram-Q63AITRT-aLYQSs2d.js} +1 -1
- package/web-dist/assets/eventmodeling-45OFAUF4-jYGf30I4.js +1 -0
- package/web-dist/assets/flowDiagram-23GEKE2U-uJJwGAew.js +1 -0
- package/web-dist/assets/{ganttDiagram-NO4QXBWP-BOJJvkcQ.js → ganttDiagram-NO4QXBWP-Bu6_kuAX.js} +1 -1
- package/web-dist/assets/{gitGraph-TEB2WS4Q-DrZGs6X0.js → gitGraph-TEB2WS4Q-yz2DuHDq.js} +1 -1
- package/web-dist/assets/{gitGraphDiagram-IHSO6WYX-C0pqDVhD.js → gitGraphDiagram-IHSO6WYX-BXfbKaor.js} +1 -1
- package/web-dist/assets/{index-BwC7xvWu.js → index-DS1RBTF4.js} +37 -37
- package/web-dist/assets/index-DX1b-Y8G.css +2 -0
- package/web-dist/assets/{info-DKCQHKI2-0OcIuVxc.js → info-DKCQHKI2-BdItukhP.js} +1 -1
- package/web-dist/assets/{infoDiagram-FWYZ7A6U-CRAc-N7_.js → infoDiagram-FWYZ7A6U-DXrq8wS3.js} +1 -1
- package/web-dist/assets/{ishikawaDiagram-FXEZZL3T-D_bHCCxh.js → ishikawaDiagram-FXEZZL3T-iM2fPeJv.js} +1 -1
- package/web-dist/assets/{journeyDiagram-5HDEW3XC-Dbvh7D1e.js → journeyDiagram-5HDEW3XC-DNa58xSH.js} +1 -1
- package/web-dist/assets/{kanban-definition-HUTT4EX6-CxOWhFpB.js → kanban-definition-HUTT4EX6-DhSaBCRv.js} +1 -1
- package/web-dist/assets/{line-BGqbhtvK.js → line-CQn0ApgD.js} +1 -1
- package/web-dist/assets/{linear-DRvKJ3WJ.js → linear-DMSasryg.js} +1 -1
- package/web-dist/assets/{mermaid-parser.core-C5lIBam8.js → mermaid-parser.core-BiJ3pVQT.js} +3 -3
- package/web-dist/assets/{mermaid.core-ChLUqNEE.js → mermaid.core-8ofZrJs5.js} +3 -3
- package/web-dist/assets/{mindmap-definition-LN4V7U3C-BfPv_GOf.js → mindmap-definition-LN4V7U3C-BLr4IGuI.js} +1 -1
- package/web-dist/assets/{packet-7NZHBO7P-CH3B2i7_.js → packet-7NZHBO7P-D15LrSHU.js} +1 -1
- package/web-dist/assets/{pegDiagram-2B236MQR-DLuCHUaK.js → pegDiagram-2B236MQR-C9IcvZ_z.js} +1 -1
- package/web-dist/assets/{pie-RZYD4A2V-C-hDlp0h.js → pie-RZYD4A2V-79-1CSta.js} +1 -1
- package/web-dist/assets/{pieDiagram-ENE6RG2P-CKVu3PTC.js → pieDiagram-ENE6RG2P-dm_ORKO7.js} +1 -1
- package/web-dist/assets/{quadrantDiagram-ABIIQ3AL--tZ3JdyA.js → quadrantDiagram-ABIIQ3AL-vQkbT0Ej.js} +1 -1
- package/web-dist/assets/{radar-I7S5WNFK-C10EMwWx.js → radar-I7S5WNFK-B8xvrM0r.js} +1 -1
- package/web-dist/assets/{railroad-3IZDKUUU-BYegvtJS.js → railroad-3IZDKUUU-G0rN-YuN.js} +1 -1
- package/web-dist/assets/railroad-abnf-AHOZXSZD-BaCc6741.js +1 -0
- package/web-dist/assets/railroad-ebnf-EBAXGLYW-cUMY4WQi.js +1 -0
- package/web-dist/assets/railroad-peg-LSFZ7HO6-JS2RjlNP.js +1 -0
- package/web-dist/assets/{railroadDiagram-RFXS5EU6-CfpRdkA8.js → railroadDiagram-RFXS5EU6-BtGt9H2_.js} +1 -1
- package/web-dist/assets/{requirementDiagram-TGXJPOKE-CUajgDbc.js → requirementDiagram-TGXJPOKE-oHUUvJjC.js} +1 -1
- package/web-dist/assets/{sankeyDiagram-HTMAVEWB-DRs5oKTx.js → sankeyDiagram-HTMAVEWB-BoO0DzUn.js} +1 -1
- package/web-dist/assets/{sequenceDiagram-DBY2YBRQ-BTeEqLFC.js → sequenceDiagram-DBY2YBRQ-B344KPVn.js} +1 -1
- package/web-dist/assets/{src-Cf1DXZ3M.js → src-BygbIYKj.js} +1 -1
- package/web-dist/assets/{stateDiagram-2N3HPSRC-BPcqMj-B.js → stateDiagram-2N3HPSRC-DMTN-MuE.js} +1 -1
- package/web-dist/assets/stateDiagram-v2-6OUMAXLB-4HUOVSEd.js +1 -0
- package/web-dist/assets/{swimlanes-5IMT3BWC-CJTd58TJ.js → swimlanes-5IMT3BWC-DQEhwI0k.js} +1 -1
- package/web-dist/assets/swimlanesDiagram-G3AALYLV-PPFuhngt.js +8 -0
- package/web-dist/assets/{timeline-definition-FHXFAJF6-CqbaBVpe.js → timeline-definition-FHXFAJF6-CUoCgDT7.js} +1 -1
- package/web-dist/assets/{treeView-QDETBFTQ-B2OQ8r59.js → treeView-QDETBFTQ-BTHFGWtv.js} +1 -1
- package/web-dist/assets/{treemap-6X3UGDF4-DGpAdWTA.js → treemap-6X3UGDF4-BI2j1PYm.js} +1 -1
- package/web-dist/assets/{vennDiagram-L72KCM5P-BAS_eWHm.js → vennDiagram-L72KCM5P-Cc3sJIb2.js} +1 -1
- package/web-dist/assets/{wardley-OPB4EBWU-DpNHIH3W.js → wardley-OPB4EBWU-kYXYWMgL.js} +1 -1
- package/web-dist/assets/{wardleyDiagram-EHGQE667-2N7X1vj8.js → wardleyDiagram-EHGQE667-KHMHPO99.js} +1 -1
- package/web-dist/assets/{xychartDiagram-FW5EYKEG-C8mfLCei.js → xychartDiagram-FW5EYKEG-DzSZk-Dq.js} +1 -1
- package/web-dist/index.html +2 -2
- package/web-dist/assets/architecture-TIHT7OUA-CXyjbDft.js +0 -1
- package/web-dist/assets/channel-uFMfT294.js +0 -1
- package/web-dist/assets/classDiagram-OUVF2IWQ-D1koMbqS.js +0 -1
- package/web-dist/assets/classDiagram-v2-EOCWNBFH-D1koMbqS.js +0 -1
- package/web-dist/assets/eventmodeling-45OFAUF4-tWFB9ALb.js +0 -1
- package/web-dist/assets/flowDiagram-23GEKE2U-Dz_Opd7B.js +0 -1
- package/web-dist/assets/index-CuXKWysP.css +0 -2
- package/web-dist/assets/railroad-abnf-AHOZXSZD-DLmknJDm.js +0 -1
- package/web-dist/assets/railroad-ebnf-EBAXGLYW-BoZF0VpA.js +0 -1
- package/web-dist/assets/railroad-peg-LSFZ7HO6-Dib7YVqg.js +0 -1
- package/web-dist/assets/stateDiagram-v2-6OUMAXLB-DiV9dOER.js +0 -1
- package/web-dist/assets/swimlanesDiagram-G3AALYLV-BDeobZmn.js +0 -8
|
@@ -26081,11 +26081,6 @@ var LEGACY_DIR_NAME = ".frizz";
|
|
|
26081
26081
|
function legacyFrizzRoot(home = homedir()) {
|
|
26082
26082
|
return join2(home, LEGACY_DIR_NAME);
|
|
26083
26083
|
}
|
|
26084
|
-
function isLegacyStateRoot(root, exists) {
|
|
26085
|
-
if (!exists(root)) return false;
|
|
26086
|
-
if (!exists(join2(root, ".id")) && !exists(join2(root, ".gitignore"))) return true;
|
|
26087
|
-
return exists(join2(root, "projects")) || exists(join2(root, "registry.json"));
|
|
26088
|
-
}
|
|
26089
26084
|
function xdg(env, name) {
|
|
26090
26085
|
const value = env[name];
|
|
26091
26086
|
return value && (value.startsWith("/") || /^[A-Za-z]:[\\/]/u.test(value)) ? value : void 0;
|
|
@@ -26128,7 +26123,7 @@ function frizzPaths(options = {}) {
|
|
|
26128
26123
|
const home = options.home ?? homedir();
|
|
26129
26124
|
const exists = options.exists ?? existsSync2;
|
|
26130
26125
|
const legacyRoot = legacyFrizzRoot(home);
|
|
26131
|
-
if (
|
|
26126
|
+
if (exists(legacyRoot)) {
|
|
26132
26127
|
return { data: legacyRoot, state: legacyRoot, cache: legacyRoot, legacy: true };
|
|
26133
26128
|
}
|
|
26134
26129
|
const explicit = {
|
|
@@ -28401,7 +28396,6 @@ function startLazyMcpHost(options) {
|
|
|
28401
28396
|
// packages/server/src/backend/types.ts
|
|
28402
28397
|
var CLAUDE_WORKER_ENV = {
|
|
28403
28398
|
CLAUDE_CODE_TOTAL_TOKENS_REMINDER: "infinite",
|
|
28404
|
-
BASH_DEFAULT_TIMEOUT_MS: "60000",
|
|
28405
28399
|
BASH_MAX_TIMEOUT_MS: String(24 * 60 * 60 * 1e3)
|
|
28406
28400
|
};
|
|
28407
28401
|
var CLAUDE_AUTO_COMPACT_WINDOW_ENV = "CLAUDE_CODE_AUTO_COMPACT_WINDOW";
|
|
@@ -28469,6 +28463,7 @@ function createClaudeBrokerExitWriter(path, meta, now = () => /* @__PURE__ */ ne
|
|
|
28469
28463
|
// packages/server/src/backend/claude-agent-broker.ts
|
|
28470
28464
|
var BROKER_CAPABILITIES = [CLAUDE_BROKER_CAPABILITY_SUBAGENT_STEER, CLAUDE_BROKER_CAPABILITY_CANCEL_INPUT, CLAUDE_BROKER_CAPABILITY_STOP_TASK, CLAUDE_BROKER_CAPABILITY_RELOAD_PLUGINS, CLAUDE_BROKER_CAPABILITY_RENAME, CLAUDE_BROKER_CAPABILITY_LIST_SKILLS, CLAUDE_BROKER_CAPABILITY_INPUT_ACK];
|
|
28471
28465
|
var IDLE_EXIT_MS = 6 * 60 * 60 * 1e3;
|
|
28466
|
+
var PERMISSION_SHOW_HOLD_MS = 250;
|
|
28472
28467
|
var REACHABILITY_CHECK_MS = 3e4;
|
|
28473
28468
|
var REACHABILITY_STRIKES = 2;
|
|
28474
28469
|
var EVENT_ERROR_TOLERANCE = 5;
|
|
@@ -28551,16 +28546,30 @@ function runClaudeBroker(config, options = {}) {
|
|
|
28551
28546
|
const requestId = `perm-${++permSeq}`;
|
|
28552
28547
|
return await new Promise((resolve3) => {
|
|
28553
28548
|
let settled = false;
|
|
28549
|
+
let showTimer;
|
|
28550
|
+
const entry = { request, shown: false, resolve: (decision) => settle(decision) };
|
|
28554
28551
|
const settle = (decision) => {
|
|
28555
28552
|
if (settled) return;
|
|
28556
28553
|
settled = true;
|
|
28554
|
+
clearTimeout(showTimer);
|
|
28557
28555
|
pendingPermissions.delete(requestId);
|
|
28558
28556
|
resolve3(decision);
|
|
28559
28557
|
};
|
|
28560
|
-
|
|
28561
|
-
|
|
28562
|
-
|
|
28563
|
-
|
|
28558
|
+
const withdraw = () => {
|
|
28559
|
+
const wasShown = entry.shown;
|
|
28560
|
+
settle({ behavior: "deny", message: "The turn was interrupted before this was answered." });
|
|
28561
|
+
if (wasShown && client) write(client, { t: "permission-withdrawn", requestId });
|
|
28562
|
+
};
|
|
28563
|
+
pendingPermissions.set(requestId, entry);
|
|
28564
|
+
if (context.signal.aborted) withdraw();
|
|
28565
|
+
else context.signal.addEventListener("abort", withdraw, { once: true });
|
|
28566
|
+
if (!settled) {
|
|
28567
|
+
showTimer = setTimeout(() => {
|
|
28568
|
+
if (settled || entry.shown || !client) return;
|
|
28569
|
+
entry.shown = true;
|
|
28570
|
+
write(client, { t: "permission-request", requestId, request });
|
|
28571
|
+
}, PERMISSION_SHOW_HOLD_MS);
|
|
28572
|
+
}
|
|
28564
28573
|
});
|
|
28565
28574
|
},
|
|
28566
28575
|
onDiagnostic: (diagnostic) => {
|
|
@@ -28612,7 +28621,10 @@ function runClaudeBroker(config, options = {}) {
|
|
|
28612
28621
|
client = sock;
|
|
28613
28622
|
clearTimeout(idleTimer);
|
|
28614
28623
|
write(sock, { t: "hello", sessionId: handle.sessionId, generation });
|
|
28615
|
-
for (const [requestId,
|
|
28624
|
+
for (const [requestId, entry] of pendingPermissions) {
|
|
28625
|
+
entry.shown = true;
|
|
28626
|
+
write(sock, { t: "permission-request", requestId, request: entry.request });
|
|
28627
|
+
}
|
|
28616
28628
|
while (eventBacklog.length) sock.write(eventBacklog.shift());
|
|
28617
28629
|
eventBacklogBytes = 0;
|
|
28618
28630
|
let buf = "";
|
package/dist/dev-child.js
CHANGED
|
@@ -46,11 +46,6 @@ import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
|
46
46
|
function legacyFrizzRoot(home = homedir()) {
|
|
47
47
|
return join(home, LEGACY_DIR_NAME);
|
|
48
48
|
}
|
|
49
|
-
function isLegacyStateRoot(root, exists) {
|
|
50
|
-
if (!exists(root)) return false;
|
|
51
|
-
if (!exists(join(root, ".id")) && !exists(join(root, ".gitignore"))) return true;
|
|
52
|
-
return exists(join(root, "projects")) || exists(join(root, "registry.json"));
|
|
53
|
-
}
|
|
54
49
|
function xdg(env, name) {
|
|
55
50
|
const value = env[name];
|
|
56
51
|
return value && (value.startsWith("/") || /^[A-Za-z]:[\\/]/u.test(value)) ? value : void 0;
|
|
@@ -93,7 +88,7 @@ function frizzPaths(options = {}) {
|
|
|
93
88
|
const home = options.home ?? homedir();
|
|
94
89
|
const exists = options.exists ?? existsSync;
|
|
95
90
|
const legacyRoot = legacyFrizzRoot(home);
|
|
96
|
-
if (
|
|
91
|
+
if (exists(legacyRoot)) {
|
|
97
92
|
return { data: legacyRoot, state: legacyRoot, cache: legacyRoot, legacy: true };
|
|
98
93
|
}
|
|
99
94
|
const explicit = {
|
|
@@ -119,6 +114,9 @@ function frizzTempDir(name, key) {
|
|
|
119
114
|
function projectStateDir(projectId, home) {
|
|
120
115
|
return join(home ? frizzPaths({ home }).data : frizzRoots().data, "projects", projectId);
|
|
121
116
|
}
|
|
117
|
+
function launchHostDir(home) {
|
|
118
|
+
return join(home ? frizzPaths({ home }).data : frizzRoots().data, "host");
|
|
119
|
+
}
|
|
122
120
|
function isPromptAttachmentPath(path3, home) {
|
|
123
121
|
const data = home ? frizzPaths({ home }).data : frizzRoots().data;
|
|
124
122
|
const rel = relative(join(data, "projects"), resolve(path3));
|
|
@@ -746,13 +744,6 @@ function isHomeDirectory(dir, home = homedir3()) {
|
|
|
746
744
|
return false;
|
|
747
745
|
}
|
|
748
746
|
}
|
|
749
|
-
function isStateRootHome(dir, home = homedir3()) {
|
|
750
|
-
return isHomeDirectory(dir, home) && frizzPaths({ home }).legacy;
|
|
751
|
-
}
|
|
752
|
-
function refuseStateRootHome(dir, home = homedir3()) {
|
|
753
|
-
if (isStateRootHome(dir, home))
|
|
754
|
-
throw new Error("Frizz keeps its own files in ~/.frizz on this machine, so the home folder cannot be a project here \u2014 choose a folder inside it.");
|
|
755
|
-
}
|
|
756
747
|
function isWorldWritable(dir, platform3 = process.platform) {
|
|
757
748
|
if (platform3 === "win32") return false;
|
|
758
749
|
try {
|
|
@@ -786,7 +777,7 @@ function discoverProjectRoot(cwd = process.cwd(), home = homedir3()) {
|
|
|
786
777
|
const stop2 = resolve3(home);
|
|
787
778
|
const filesystemRoot = parse(dir).root;
|
|
788
779
|
for (let at2 = dir; ; at2 = dirname3(at2)) {
|
|
789
|
-
if (at2 === stop2 || at2 === filesystemRoot
|
|
780
|
+
if (at2 === stop2 || at2 === filesystemRoot) break;
|
|
790
781
|
if (existsSync2(projectIdPath(at2))) return at2;
|
|
791
782
|
if (hasAny(at2, REPO_MARKERS)) return at2;
|
|
792
783
|
if (hasAny(at2, PROJECT_MARKERS)) return at2;
|
|
@@ -803,7 +794,6 @@ var FRIZZ_DIR, ID_FILE, SELF_IGNORE, REPO_MARKERS, PROJECT_MARKERS;
|
|
|
803
794
|
var init_project_root = __esm({
|
|
804
795
|
"packages/server/src/project-root.ts"() {
|
|
805
796
|
"use strict";
|
|
806
|
-
init_frizz_paths();
|
|
807
797
|
init_project_identity();
|
|
808
798
|
FRIZZ_DIR = ".frizz";
|
|
809
799
|
ID_FILE = ".id";
|
|
@@ -13820,7 +13810,7 @@ function askedQuestionFaults(q2) {
|
|
|
13820
13810
|
if (node.secret && options.length > 0) faults.push(`${path3}: a secret request takes no options \u2014 it is one masked box`);
|
|
13821
13811
|
if (node.secret && path3 !== "question") faults.push(`${path3}: a secret request cannot be a follow-up \u2014 register it on its own`);
|
|
13822
13812
|
if (node.kind === "multi" && options.length === 0) faults.push(`${path3}: \`kind: "multi"\` needs options \u2014 a question with none is free text`);
|
|
13823
|
-
if (options.filter((o) => o.recommended).length > 1) faults.push(`${path3}: only ONE option may be \`recommended\` \u2014 a recommendation on two of three choices says nothing`);
|
|
13813
|
+
if (node.kind !== "multi" && options.filter((o) => o.recommended).length > 1) faults.push(`${path3}: only ONE option may be \`recommended\` on a pick-one question \u2014 a recommendation on two of three choices says nothing (a \`multi\` may mark every option worth ticking)`);
|
|
13824
13814
|
for (const [i, option] of options.entries()) {
|
|
13825
13815
|
if ((option.followUps ?? []).length > 0 && node.kind === "multi") {
|
|
13826
13816
|
faults.push(`${path3}: a \`multi\` option cannot carry follow-ups \u2014 several picked options would open several branches at once`);
|
|
@@ -14252,7 +14242,7 @@ var init_src = __esm({
|
|
|
14252
14242
|
"running",
|
|
14253
14243
|
// process alive, turn in flight
|
|
14254
14244
|
"perm-prompt",
|
|
14255
|
-
// process alive,
|
|
14245
|
+
// process alive, parked on a permission request a person has not answered yet
|
|
14256
14246
|
"turn-idle",
|
|
14257
14247
|
// process alive, waiting at the prompt
|
|
14258
14248
|
"exited"
|
|
@@ -16471,6 +16461,7 @@ function canonicalPath(dir) {
|
|
|
16471
16461
|
}
|
|
16472
16462
|
function registerProject(input, home = homedir4()) {
|
|
16473
16463
|
input = { ...input, dir: canonicalPath(input.dir) };
|
|
16464
|
+
if (input.dir === canonicalPath(launchHostDir(home))) return { action: "unlisted" };
|
|
16474
16465
|
const registry = readRegistry(home);
|
|
16475
16466
|
if (registry.forgotten) {
|
|
16476
16467
|
registry.forgotten = registry.forgotten.filter((id2) => id2 !== input.id);
|
|
@@ -17210,7 +17201,6 @@ function projectFromRegistryEntry(entry, home = homedir5()) {
|
|
|
17210
17201
|
function resolveProject(cwd = process.cwd(), home = homedir5(), env = process.env) {
|
|
17211
17202
|
const root = resolveProjectDir(cwd);
|
|
17212
17203
|
refuseWorldWritableProject(root);
|
|
17213
|
-
refuseStateRootHome(root, home);
|
|
17214
17204
|
const identity = resolveProjectIdentity(root, home);
|
|
17215
17205
|
const dir = identity.root;
|
|
17216
17206
|
const id2 = registerAndReconcile(dir, identity.id, home);
|
|
@@ -19302,6 +19292,12 @@ function createInteractionStore(db2, options = {}) {
|
|
|
19302
19292
|
SELECT COUNT(*) AS count FROM interaction_journal
|
|
19303
19293
|
WHERE project_id = ? AND thread_slug = ? AND session_id = ? AND lifecycle = 'pending'
|
|
19304
19294
|
`);
|
|
19295
|
+
const terminalSince = db2.prepare(`
|
|
19296
|
+
SELECT EXISTS (
|
|
19297
|
+
SELECT 1 FROM interaction_journal
|
|
19298
|
+
WHERE project_id = ? AND thread_slug = ? AND session_id = ? AND lifecycle != 'pending' AND completed_at >= ?
|
|
19299
|
+
) AS found
|
|
19300
|
+
`);
|
|
19305
19301
|
const insert = db2.prepare(`
|
|
19306
19302
|
INSERT INTO interaction_journal (
|
|
19307
19303
|
id, schema_version, project_id, thread_slug, session_id, session_epoch, capability_revision,
|
|
@@ -19921,6 +19917,13 @@ function createInteractionStore(db2, options = {}) {
|
|
|
19921
19917
|
cancelSessionDeliveriesStmt.run({ threadSlug, sessionId, at: at2 });
|
|
19922
19918
|
return before.map((row) => rowToRecord(byId.get(row.id)));
|
|
19923
19919
|
});
|
|
19920
|
+
const withdrawTxn = db2.transaction((scope, interactionId) => {
|
|
19921
|
+
const row = byScopedId.get(interactionId, scope.projectId, scope.threadSlug, scope.sessionId);
|
|
19922
|
+
if (!row || row.lifecycle !== "pending") return void 0;
|
|
19923
|
+
if (deliveryByInteraction.get(row.id)) throw new InteractionStoreError("invalid-response", "a provider-delivered interaction is withdrawn through invalidateProviderRequest");
|
|
19924
|
+
if (providerCancelStmt.run({ id: row.id, at: iso(now) }).changes !== 1) return void 0;
|
|
19925
|
+
return rowToRecord(byId.get(row.id));
|
|
19926
|
+
});
|
|
19924
19927
|
const expireTxn = db2.transaction((at2) => {
|
|
19925
19928
|
const before = dueStmt.all(at2);
|
|
19926
19929
|
if (before.length === 0) return [];
|
|
@@ -19955,6 +19958,10 @@ function createInteractionStore(db2, options = {}) {
|
|
|
19955
19958
|
emit2(expired);
|
|
19956
19959
|
return listPendingStmt.all(scope.projectId, scope.threadSlug, scope.sessionId, INTERACTION_LIST_MAX).map(rowToRecord);
|
|
19957
19960
|
},
|
|
19961
|
+
settledSince(scope, since) {
|
|
19962
|
+
if ((pendingCount.get(scope.projectId, scope.threadSlug, scope.sessionId)?.count ?? 0) > 0) return false;
|
|
19963
|
+
return terminalSince.get(scope.projectId, scope.threadSlug, scope.sessionId, since)?.found === 1;
|
|
19964
|
+
},
|
|
19958
19965
|
resolve(scope, input) {
|
|
19959
19966
|
const expired = expireTxn(iso(now));
|
|
19960
19967
|
emit2(expired);
|
|
@@ -20009,6 +20016,11 @@ function createInteractionStore(db2, options = {}) {
|
|
|
20009
20016
|
if (result.effect === "cancelled") emit2([result.interaction]);
|
|
20010
20017
|
return result;
|
|
20011
20018
|
},
|
|
20019
|
+
withdraw(scope, interactionId) {
|
|
20020
|
+
const record = withdrawTxn.immediate(scope, interactionId);
|
|
20021
|
+
if (record) emit2([record]);
|
|
20022
|
+
return record;
|
|
20023
|
+
},
|
|
20012
20024
|
cancelForSession(threadSlug, sessionId, reason) {
|
|
20013
20025
|
const parsedReason = InteractionCancellationReason.safeParse(reason);
|
|
20014
20026
|
if (!parsedReason.success || parsedReason.data === "expired") {
|
|
@@ -22413,7 +22425,6 @@ var init_types2 = __esm({
|
|
|
22413
22425
|
WORKER_MAX_CONCURRENT_SUBAGENTS = 100;
|
|
22414
22426
|
CLAUDE_WORKER_ENV = {
|
|
22415
22427
|
CLAUDE_CODE_TOTAL_TOKENS_REMINDER: "infinite",
|
|
22416
|
-
BASH_DEFAULT_TIMEOUT_MS: "60000",
|
|
22417
22428
|
BASH_MAX_TIMEOUT_MS: String(24 * 60 * 60 * 1e3)
|
|
22418
22429
|
};
|
|
22419
22430
|
CLAUDE_AUTO_COMPACT_WINDOW_ENV = "CLAUDE_CODE_AUTO_COMPACT_WINDOW";
|
|
@@ -26535,16 +26546,21 @@ ${ask}`;
|
|
|
26535
26546
|
if (!Number.isFinite(at2)) return false;
|
|
26536
26547
|
if (priorGeneration(at2)) return false;
|
|
26537
26548
|
const last = state.lastActivityAt ? Date.parse(state.lastActivityAt) : Number.NEGATIVE_INFINITY;
|
|
26538
|
-
|
|
26549
|
+
if (at2 <= last) return false;
|
|
26550
|
+
try {
|
|
26551
|
+
if (deps.permissionSettled?.(row.slug, row.session_id, new Date(at2).toISOString())) return false;
|
|
26552
|
+
} catch {
|
|
26553
|
+
}
|
|
26554
|
+
return true;
|
|
26539
26555
|
}
|
|
26540
26556
|
function sniffPane(state, row, turn, nowMs, backend) {
|
|
26541
26557
|
void nowMs;
|
|
26542
26558
|
void backend;
|
|
26543
|
-
|
|
26544
|
-
|
|
26545
|
-
|
|
26546
|
-
|
|
26547
|
-
return
|
|
26559
|
+
return { permPrompt: permBlocked(state, row, turn) };
|
|
26560
|
+
}
|
|
26561
|
+
function permBlocked(state, row, turn) {
|
|
26562
|
+
if (state.foreign) return false;
|
|
26563
|
+
return turn === "in-flight" && row.backend !== "codex" && row.backend !== "acp" && permMarkerBlocks(state, row);
|
|
26548
26564
|
}
|
|
26549
26565
|
function drainUnretiredOps(state, row) {
|
|
26550
26566
|
if (!state.unretiredOps?.size) return;
|
|
@@ -27361,6 +27377,12 @@ ${detail2}
|
|
|
27361
27377
|
state.permissionMode = permissionMode;
|
|
27362
27378
|
}
|
|
27363
27379
|
},
|
|
27380
|
+
permissionAnswered(slug) {
|
|
27381
|
+
const state = states.get(slug);
|
|
27382
|
+
if (!state?.primed || !state.permPrompt) return;
|
|
27383
|
+
const row = currentRowFor(state);
|
|
27384
|
+
if (row) state.permPrompt = permBlocked(state, row, state.turn);
|
|
27385
|
+
},
|
|
27364
27386
|
start(onPrimeProgress) {
|
|
27365
27387
|
if (timer) return;
|
|
27366
27388
|
stopped = false;
|
|
@@ -37889,15 +37911,16 @@ exactly ONE of them.
|
|
|
37889
37911
|
- the auth audit found the one issue worth deciding on before the rest land
|
|
37890
37912
|
\`\`\`
|
|
37891
37913
|
|
|
37892
|
-
And when the human must DO something you cannot \u2014 here, the
|
|
37914
|
+
And when the human must DO something you cannot \u2014 here, you started the npm sign-in yourself, and
|
|
37915
|
+
the one act left needs their account:
|
|
37893
37916
|
|
|
37894
37917
|
\`\`\`awaiting
|
|
37895
|
-
title:
|
|
37918
|
+
title: Approve the npm sign-in so the release can publish
|
|
37896
37919
|
steps:
|
|
37897
|
-
-
|
|
37898
|
-
- Approve the
|
|
37920
|
+
- Open [the npm sign-in this thread started](https://www.npmjs.com/login?next=/login/cli/9f3c2a71) and sign in with the maintainer account.
|
|
37921
|
+
- Approve the request with that account's security key or one-time code, and wait for the page to say the CLI is signed in.
|
|
37899
37922
|
---
|
|
37900
|
-
|
|
37923
|
+
\`npm login --auth-type=web\` is running in this thread and waiting on that approval. The publish follows as soon as it lands.
|
|
37901
37924
|
\`\`\`
|
|
37902
37925
|
|
|
37903
37926
|
- **\`status:\` \u2014 REQUIRED: where does the thread sit while the work runs?** One of three values, one
|
|
@@ -37976,10 +37999,25 @@ exactly ONE of them.
|
|
|
37976
37999
|
followed COLD by someone who has read nothing else; frizz reads them verbatim. Steps NAME THE HUMAN
|
|
37977
38000
|
as the wait, so the fence needs no other name and no \`for:\` (add one only if you want to be woken
|
|
37978
38001
|
to re-check), and it always puts the thread in their queue \u2014 \`status:\` may be left out. Their
|
|
37979
|
-
card shows the steps over one **Done** button, and its click comes
|
|
37980
|
-
\`Done\`, the same as anything they type; anything else they need to
|
|
37981
|
-
the account they used \u2014 comes as a message of their own. An act is not a decision: never ask
|
|
38002
|
+
card, headed **Awaiting human**, shows the steps over one **Done** button, and its click comes
|
|
38003
|
+
back to you as their reply, \`Done\`, the same as anything they type; anything else they need to
|
|
38004
|
+
tell you \u2014 a step that failed, the account they used \u2014 comes as a message of their own. An act is not a decision: never ask
|
|
37982
38005
|
WHETHER they will do it, and never call \`done\` while it is still owed.
|
|
38006
|
+
**THE FIRST TEST OF EVERY STEP: COULD YOU DO IT YOURSELF? THEN IT IS NOT A STEP \u2014 DO IT.** This
|
|
38007
|
+
outranks every rule below. Steps are what is LEFT after you have done all you can: a command you
|
|
38008
|
+
can run is yours to run \u2014 an install, a build, a key generated, a \`git config\`, a file written \u2014
|
|
38009
|
+
and so is an act a CLI or an API performs as well as the page does (\`gh ssh-key add\`, not "open
|
|
38010
|
+
GitHub's settings and paste the key"). A step is only what needs the human's BODY or the human's
|
|
38011
|
+
IDENTITY: a fingerprint, a 2FA or OS permission prompt, a sign-in, a button behind a session you
|
|
38012
|
+
do not hold, an act a guardrail refuses you. TRY before you conclude you cannot \u2014 "I may lack
|
|
38013
|
+
access" is not a blocker until a command has been refused. Doubt about whether you MAY, not
|
|
38014
|
+
whether you can, is a decision: \`mcp__frizz__ask\` it, and run the command yourself on a yes.
|
|
38015
|
+
And ORDER the work so they are interrupted for their own acts alone: do everything up to the
|
|
38016
|
+
first one, hand over only that, and do what follows yourself when their reply wakes you \u2014 a
|
|
38017
|
+
command of yours never becomes their step 5 because it comes after their step 4.
|
|
38018
|
+
(Maintainer 2026-10-10, of a six-step card that opened with \`brew install rust\`, a \`cargo build\`
|
|
38019
|
+
and a \`git config\`: *"The number one criterion for the to-do block is that it should never tell
|
|
38020
|
+
the user to do something that the agent can do itself."*)
|
|
37983
38021
|
**EVERY STEP IS CLICKABLE AND COMPLETE \u2014 A STEP THAT MAKES THE HUMAN GO LOOKING IS A BROKEN STEP.**
|
|
37984
38022
|
The steps are the most actionable thing you hand over, so write each one to be DONE, not
|
|
37985
38023
|
researched: every page it names is a real Markdown link to that exact page (the settings screen,
|
|
@@ -38169,9 +38207,10 @@ so, which?" without asking it of somebody who said no. Written out, one registra
|
|
|
38169
38207
|
Each question must stand alone: the specific question on ONE line, options each with a one-line
|
|
38170
38208
|
trade-off, and enough context to answer cold. The card numbers the options 1, 2, 3 in the order you
|
|
38171
38209
|
give them \u2014 the human picks one by pressing its number \u2014 so put the one you would take FIRST and mark
|
|
38172
|
-
it \`recommended\`; mark exactly one
|
|
38173
|
-
|
|
38174
|
-
|
|
38210
|
+
it \`recommended\`; mark exactly one \u2014 except on a \`multi\`, where the mark goes on EVERY option you
|
|
38211
|
+
would tick, since one mark alone reads as "pick only this". Several independent questions are several
|
|
38212
|
+
entries of ONE \`ask\` call, never one bundled question. A bare "which approach?" with no options is
|
|
38213
|
+
a broken handoff.
|
|
38175
38214
|
|
|
38176
38215
|
NO "I" AND NO "you" ANYWHERE IN A QUESTION \u2014 the question, its options, or any interactive prompt.
|
|
38177
38216
|
Clicking an option is the HUMAN speaking, so first and second person flip between writer and reader: in
|
|
@@ -38436,8 +38475,8 @@ sub-agent alone does not.
|
|
|
38436
38475
|
\`mcp__frizz__watch_pr\`; for a GitHub issue, \`mcp__frizz__watch_issue\`; for anything else dispatch a
|
|
38437
38476
|
SUB-AGENT to own the wait. It runs the watcher
|
|
38438
38477
|
to completion in its own foreground and returns the verdict, and its return re-invokes you; rest on
|
|
38439
|
-
it with \`status: watching\`. A Bash call that names no \`timeout\` moves to the background
|
|
38440
|
-
|
|
38478
|
+
it with \`status: watching\`. A Bash call that names no \`timeout\` moves to the background at the
|
|
38479
|
+
tool's default, so the watcher names one sized to the wait (up to 24h) and loops until its terminal
|
|
38441
38480
|
condition. A helper must not hand back while its own watcher is still live.
|
|
38442
38481
|
- **Working alongside a process you launched** (dev server, log tail) \u2192 \`Bash\` with
|
|
38443
38482
|
\`run_in_background: true\`. Never put shell job control (\`&\`, \`nohup \u2026 &\`, \`disown\`) inside the
|
|
@@ -38912,6 +38951,9 @@ function connectClaudeBroker(socketPath, handlers, options = {}) {
|
|
|
38912
38951
|
case "permission-request":
|
|
38913
38952
|
handlers.onPermissionRequest?.(frame.requestId, frame.request);
|
|
38914
38953
|
break;
|
|
38954
|
+
case "permission-withdrawn":
|
|
38955
|
+
handlers.onPermissionWithdrawn?.(frame.requestId);
|
|
38956
|
+
break;
|
|
38915
38957
|
case "diagnostic":
|
|
38916
38958
|
handlers.onDiagnostic?.(frame.diagnostic);
|
|
38917
38959
|
break;
|
|
@@ -39465,6 +39507,17 @@ function createClaudeAgentBrokerBridge(deps) {
|
|
|
39465
39507
|
}
|
|
39466
39508
|
pendingPerms.set(id2, { client, requestId, scope, ...ask ? { ask } : {} });
|
|
39467
39509
|
};
|
|
39510
|
+
const withdrawPermission = (slug, sessionId, requestId) => {
|
|
39511
|
+
if (!deps.interactions) return;
|
|
39512
|
+
for (const [interactionId, pending] of pendingPerms) {
|
|
39513
|
+
if (pending.requestId !== requestId || pending.scope.threadSlug !== slug || pending.scope.sessionId !== sessionId) continue;
|
|
39514
|
+
pendingPerms.delete(interactionId);
|
|
39515
|
+
try {
|
|
39516
|
+
deps.interactions.withdraw(pending.scope, interactionId);
|
|
39517
|
+
} catch {
|
|
39518
|
+
}
|
|
39519
|
+
}
|
|
39520
|
+
};
|
|
39468
39521
|
const unsubInteractions = deps.interactions?.subscribe((change) => {
|
|
39469
39522
|
const pending = pendingPerms.get(change.interactionId);
|
|
39470
39523
|
if (!pending || change.lifecycle === "pending") return;
|
|
@@ -39517,7 +39570,8 @@ function createClaudeAgentBrokerBridge(deps) {
|
|
|
39517
39570
|
return;
|
|
39518
39571
|
}
|
|
39519
39572
|
void (deps.decidePermission?.(slug, sessionId, request) ?? Promise.resolve({ behavior: "allow" })).then((decision2) => client.answerPermission(requestId, decision2)).catch(() => client.answerPermission(requestId, { behavior: "deny", message: "permission decision failed" }));
|
|
39520
|
-
}
|
|
39573
|
+
},
|
|
39574
|
+
onPermissionWithdrawn: (requestId) => withdrawPermission(slug, sessionId, requestId)
|
|
39521
39575
|
});
|
|
39522
39576
|
const session = { slug, sessionId, cwd, generation: record.generation, client, acksInput: record.capabilities?.includes(CLAUDE_BROKER_CAPABILITY_INPUT_ACK) === true };
|
|
39523
39577
|
sessions.set(slug, session);
|
|
@@ -39528,7 +39582,7 @@ function createClaudeAgentBrokerBridge(deps) {
|
|
|
39528
39582
|
const we2 = deps.workerEnv;
|
|
39529
39583
|
const workerEnv = {
|
|
39530
39584
|
FRIZZ_THREAD: slug,
|
|
39531
|
-
// Every Claude worker's environment — the token budget, the bash
|
|
39585
|
+
// Every Claude worker's environment — the token budget, the bash timeout ceiling, and the lifted
|
|
39532
39586
|
// web-search / sub-agent caps — as ONE record, so a cap added there cannot miss this path. It
|
|
39533
39587
|
// used to spread CLAUDE_WORKER_ENV, which carried the first two and not the caps, and since the
|
|
39534
39588
|
// broker is the only transport that meant no worker ever received a lift (fixed 2026-08-19; see
|
|
@@ -39624,7 +39678,7 @@ function createClaudeAgentBrokerBridge(deps) {
|
|
|
39624
39678
|
input.permissionMode ?? "default",
|
|
39625
39679
|
{ resume: true, appendSystemPrompt: input.appendSystemPrompt, model: input.model, effort: input.effort }
|
|
39626
39680
|
);
|
|
39627
|
-
retirePendingFor(input.threadSlug, input.sessionId, "user-cancelled");
|
|
39681
|
+
if (!input.keepOpenCards) retirePendingFor(input.threadSlug, input.sessionId, "user-cancelled");
|
|
39628
39682
|
await deliver(session, message);
|
|
39629
39683
|
},
|
|
39630
39684
|
interruptTurn(input) {
|
|
@@ -40646,7 +40700,7 @@ function appServerTurnStalled(liveness, lastActivityAt, nowMs) {
|
|
|
40646
40700
|
function deriveRuntime(slug, row, storage, turn, permPrompt, appServerStalled = false, headlessLostWork = false) {
|
|
40647
40701
|
if (!row) return "none";
|
|
40648
40702
|
if (isHeadlessRow(row)) {
|
|
40649
|
-
if (permPrompt) return "perm-prompt";
|
|
40703
|
+
if (permPrompt && !appServerStalled) return "perm-prompt";
|
|
40650
40704
|
if (headlessLostWork) return "exited";
|
|
40651
40705
|
if (turn === "idle") return "turn-idle";
|
|
40652
40706
|
return appServerStalled ? "exited" : "running";
|
|
@@ -73190,7 +73244,11 @@ function deliverClaudeBrokerWake(deps) {
|
|
|
73190
73244
|
appendSystemPrompt,
|
|
73191
73245
|
model: row.model ?? void 0,
|
|
73192
73246
|
effort: row.effort ?? void 0,
|
|
73193
|
-
freshProcess
|
|
73247
|
+
freshProcess,
|
|
73248
|
+
// A wake is not the operator answering: an approval or question card open on this thread stays open,
|
|
73249
|
+
// and the wake is read once they have answered it. Without this a timer coming due, a schedule beat
|
|
73250
|
+
// or a report held past the mid-turn ceiling DENIED the open approval on the operator's behalf.
|
|
73251
|
+
keepOpenCards: true
|
|
73194
73252
|
});
|
|
73195
73253
|
}
|
|
73196
73254
|
function projectContextCleanups(get) {
|
|
@@ -73260,6 +73318,7 @@ function createContextUnchecked(opts, resources) {
|
|
|
73260
73318
|
const transcriptChange = new Emitter();
|
|
73261
73319
|
const bootId = randomUUID16();
|
|
73262
73320
|
let board;
|
|
73321
|
+
let permissionAnswered;
|
|
73263
73322
|
const contextUnsubscribers = [];
|
|
73264
73323
|
let subscriptionsStopped = false;
|
|
73265
73324
|
const stopSubscriptions = () => {
|
|
@@ -73293,6 +73352,7 @@ function createContextUnchecked(opts, resources) {
|
|
|
73293
73352
|
lifecycle: change.lifecycle,
|
|
73294
73353
|
recordRevision: change.recordRevision
|
|
73295
73354
|
});
|
|
73355
|
+
if (change.lifecycle !== "pending") permissionAnswered?.(change.threadSlug);
|
|
73296
73356
|
board?.interactionChanged?.(change);
|
|
73297
73357
|
}));
|
|
73298
73358
|
storage.interactions.expireDue();
|
|
@@ -73496,6 +73556,9 @@ function createContextUnchecked(opts, resources) {
|
|
|
73496
73556
|
codexModels: () => readCodexModels(void 0, opts.codexVersion),
|
|
73497
73557
|
onChange: () => board.refresh(),
|
|
73498
73558
|
onTranscriptChange: (slugs) => transcriptChange.emit(slugs),
|
|
73559
|
+
// The journal's word on whether a deferred permission request has been answered — the transcript
|
|
73560
|
+
// only says so once the approved tool call returns.
|
|
73561
|
+
permissionSettled: (slug, sessionId, markerAt) => storage.interactions.settledSince({ projectId: project.id, threadSlug: slug, sessionId }, markerAt),
|
|
73499
73562
|
// The SDK's own reading of a headless broker session: its turn (so the fold's 5s unknown-stop_reason
|
|
73500
73563
|
// guess need not run out before a finished turn reaches the queue) and its event count (so a tick
|
|
73501
73564
|
// can tell the provider has reported activity its own disk write has not caught up with yet).
|
|
@@ -73515,6 +73578,7 @@ function createContextUnchecked(opts, resources) {
|
|
|
73515
73578
|
});
|
|
73516
73579
|
resources.tailer = tailer;
|
|
73517
73580
|
opts.startup?.afterPhase?.("tailer");
|
|
73581
|
+
permissionAnswered = (slug) => tailer.permissionAnswered?.(slug);
|
|
73518
73582
|
board = createBoard(project, storage, bus, tailer, bootId, {
|
|
73519
73583
|
codexTurnLiveness: (slug, sessionId) => codexAppServer?.turnLiveness(slug, sessionId),
|
|
73520
73584
|
// Headless-stall signal for a broker row: the ownerless daemon's record. Absent bridge ⇒ default
|
|
@@ -80529,7 +80593,7 @@ function addProjectAtPath(input, home = homedir18()) {
|
|
|
80529
80593
|
}
|
|
80530
80594
|
if (!stats.isDirectory()) throw new Error(`That is a file, not a folder: ${absolute}`);
|
|
80531
80595
|
const root = chosenProjectRoot(absolute, home);
|
|
80532
|
-
if (isHomeDirectory(root, home)) throw new Error("The home folder cannot be
|
|
80596
|
+
if (isHomeDirectory(root, home)) throw new Error("The home folder cannot be a project \u2014 choose a folder inside it.");
|
|
80533
80597
|
refuseWorldWritableProject(root);
|
|
80534
80598
|
const id2 = ensureProjectIdFile(root, home, existingProjectId(root));
|
|
80535
80599
|
const remoteOwner = resolveProjectLabel(root)?.split("/")[0];
|
|
@@ -81036,7 +81100,9 @@ ${gapNote}` : input.message;
|
|
|
81036
81100
|
// Claude's `default` — see coldResumePermission.
|
|
81037
81101
|
permissionMode: coldResumePermission(row, ctx.getSettings()),
|
|
81038
81102
|
model: row.model ?? void 0,
|
|
81039
|
-
effort: row.effort ?? void 0
|
|
81103
|
+
effort: row.effort ?? void 0,
|
|
81104
|
+
// Frizz's own notice, not the operator's reply to anything: an open card stays open.
|
|
81105
|
+
keepOpenCards: true
|
|
81040
81106
|
});
|
|
81041
81107
|
return null;
|
|
81042
81108
|
} catch (error) {
|
package/package.json
CHANGED
|
@@ -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
|
|
275
|
-
to `default` with the live permission control and its prompts come back.
|
|
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
|
|
|
@@ -505,8 +505,10 @@ function questionSchema(depth) {
|
|
|
505
505
|
recommended: {
|
|
506
506
|
type: "boolean",
|
|
507
507
|
description:
|
|
508
|
-
"Mark the ONE option you would take, and put it first. At most one per question — a " +
|
|
509
|
-
"recommendation on two of three choices says nothing.
|
|
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 " +
|
|
510
512
|
"YOU ARE ASKING: you already know the answer, so implement it and say which way you went. " +
|
|
511
513
|
"This is for the fork you genuinely cannot take yourself.",
|
|
512
514
|
},
|
|
@@ -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) =>
|
|
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
|
},
|
package/web-dist/assets/{abnfDiagram-VRR7QNED-B61nQEjt.js → abnfDiagram-VRR7QNED-DqTQZ2Ex.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{m as e,t}from"./mermaid-parser.core-
|
|
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-
|
|
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};
|