@windyroad/risk-scorer 0.19.15 → 0.19.16
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.
|
@@ -43,6 +43,11 @@ function transportRegistrationPath(sessionId, role, target) {
|
|
|
43
43
|
return join(transportDir(), `registration-${transportId(sessionId, role, target)}.json`);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
function registeredPath(registered) {
|
|
47
|
+
const target = registered.source === "subagent-start" ? `native:${registered.target}` : registered.target;
|
|
48
|
+
return transportRegistrationPath(registered.parentSession, registered.role, target);
|
|
49
|
+
}
|
|
50
|
+
|
|
46
51
|
function transportReceiptPath(sessionId, role, target, suffix = "") {
|
|
47
52
|
return join(transportDir(), `risk-receipt-${transportId(sessionId, role, target)}.json${suffix}`);
|
|
48
53
|
}
|
|
@@ -145,9 +150,49 @@ function spawnTarget(input) {
|
|
|
145
150
|
return result.agent_id ?? result.task_name;
|
|
146
151
|
}
|
|
147
152
|
|
|
153
|
+
function nativePipelinePath(sessionId) {
|
|
154
|
+
return join(riskDir(sessionId), "native-pipeline-transport");
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Native lifecycle events carry the runtime-owned parent session and agent ID.
|
|
158
|
+
// They do not depend on the spawn tool being visible to PostToolUse.
|
|
159
|
+
function rememberNativePipeline(input) {
|
|
160
|
+
if (input.agent_type !== "wr-risk-scorer:pipeline" ||
|
|
161
|
+
typeof input.agent_id !== "string" || !/^[A-Za-z0-9-]+$/.test(input.agent_id)) return;
|
|
162
|
+
const bound = directoryBinding(input.cwd);
|
|
163
|
+
if (!bound) return;
|
|
164
|
+
const policy = policyBinding(bound.root);
|
|
165
|
+
if (!policy) return;
|
|
166
|
+
const target = input.agent_id;
|
|
167
|
+
if (existsSync(statePath(input, target, ".done")) ||
|
|
168
|
+
existsSync(transportReceiptPath(input.session_id, input.agent_type, target, ".done"))) return;
|
|
169
|
+
const registered = {
|
|
170
|
+
source: "subagent-start", parentSession: input.session_id,
|
|
171
|
+
role: input.agent_type, target, ...bound, policy, createdAt: Date.now(),
|
|
172
|
+
};
|
|
173
|
+
mkdirSync(transportDir(), { recursive: true, mode: 0o700 });
|
|
174
|
+
const path = registeredPath(registered);
|
|
175
|
+
try {
|
|
176
|
+
writeFileSync(path, JSON.stringify(registered), { flag: "wx", mode: 0o600 });
|
|
177
|
+
} catch (error) {
|
|
178
|
+
if (error?.code !== "EEXIST") throw error;
|
|
179
|
+
const previous = JSON.parse(readFileSync(path, "utf8"));
|
|
180
|
+
for (const key of ["source", "parentSession", "role", "target", "root", "physical"]) {
|
|
181
|
+
if (previous[key] !== registered[key]) return;
|
|
182
|
+
}
|
|
183
|
+
if (JSON.stringify(previous.policy) !== JSON.stringify(policy)) return;
|
|
184
|
+
}
|
|
185
|
+
// This records transport availability, not assessment authorization. Keep it
|
|
186
|
+
// after receipt cleanup so delayed legacy delivery cannot refresh scores.
|
|
187
|
+
mkdirSync(riskDir(input.session_id), { recursive: true });
|
|
188
|
+
try { writeFileSync(nativePipelinePath(input.session_id), "", { flag: "wx", mode: 0o600 }); }
|
|
189
|
+
catch (error) { if (error?.code !== "EEXIST") throw error; }
|
|
190
|
+
}
|
|
191
|
+
|
|
148
192
|
function rememberSpawn(input) {
|
|
149
193
|
reapRegisteredTransport();
|
|
150
194
|
const role = input.tool_input?.agent_type;
|
|
195
|
+
if (role === "wr-risk-scorer:pipeline" && existsSync(nativePipelinePath(input.session_id))) return;
|
|
151
196
|
const target = spawnTarget(input);
|
|
152
197
|
if (typeof target !== "string" || !target) return;
|
|
153
198
|
mkdirSync(riskDir(input.session_id), { recursive: true });
|
|
@@ -265,6 +310,7 @@ function markTarget(input, target, output) {
|
|
|
265
310
|
if (!existsSync(state)) return;
|
|
266
311
|
const role = readFileSync(state, "utf8");
|
|
267
312
|
if (!riskAgentRoles.has(role)) return;
|
|
313
|
+
if (role === "wr-risk-scorer:pipeline" && existsSync(nativePipelinePath(input.session_id))) return;
|
|
268
314
|
const claim = claimTarget(input, target);
|
|
269
315
|
if (!claim) return;
|
|
270
316
|
|
|
@@ -352,16 +398,23 @@ function registrationCandidates(input, role, target) {
|
|
|
352
398
|
try {
|
|
353
399
|
const registered = JSON.parse(readFileSync(path, "utf8"));
|
|
354
400
|
if (registered.role !== role) return [];
|
|
401
|
+
if (role === "wr-risk-scorer:pipeline" && existsSync(nativePipelinePath(input.session_id)) &&
|
|
402
|
+
registered.source !== "subagent-start") return [];
|
|
403
|
+
if (registered.source === "subagent-start" &&
|
|
404
|
+
(registered.parentSession !== input.session_id || registered.target !== input.agent_id)) return [];
|
|
355
405
|
if (role !== "wr-risk-scorer:pipeline" && (!current || registered.root !== current.root || registered.physical !== current.physical)) return [];
|
|
356
406
|
return [{ path, registered }];
|
|
357
407
|
} catch { return []; }
|
|
358
408
|
});
|
|
409
|
+
const native = registrations.filter(({ registered }) => registered.source === "subagent-start");
|
|
410
|
+
if (native.length) return native;
|
|
359
411
|
const exact = registrations.filter(({ registered }) => registered.target === target);
|
|
360
412
|
if (exact.length) return exact;
|
|
361
413
|
// Current Codex returns a task name at spawn and a child UUID at stop.
|
|
362
414
|
// The runtime parent session plus one invoking-checkout registration binds them.
|
|
363
415
|
if (input.hook_event_name !== "SubagentStop" || !current) return [];
|
|
364
416
|
return registrations.filter(({ registered }) =>
|
|
417
|
+
registered.source !== "subagent-start" &&
|
|
365
418
|
registered.parentSession === input.session_id &&
|
|
366
419
|
registered.root === current.root && registered.physical === current.physical);
|
|
367
420
|
}
|
|
@@ -473,6 +526,7 @@ function consumeRegisteredPending(input) {
|
|
|
473
526
|
let pending;
|
|
474
527
|
try { pending = JSON.parse(readFileSync(path, "utf8")); } catch { continue; }
|
|
475
528
|
if (pending.parentSession !== input.session_id || !riskAgentRoles.has(pending.role)) continue;
|
|
529
|
+
if (pending.role === "wr-risk-scorer:pipeline" && existsSync(nativePipelinePath(input.session_id)) && pending.source !== "subagent-start") continue;
|
|
476
530
|
if (!registrationValid(input, pending)) continue;
|
|
477
531
|
if (pending.role === "wr-risk-scorer:pipeline") {
|
|
478
532
|
if (!current || checkoutId(current.root) !== pending.checkoutId || stateHash(current.root) !== pending.stateHash) continue;
|
|
@@ -492,7 +546,7 @@ function consumeRegisteredPending(input) {
|
|
|
492
546
|
if (!targetClaim) {
|
|
493
547
|
if (existsSync(statePath(targetInput, pending.target, ".done"))) {
|
|
494
548
|
renameSync(path, `${path}.done`);
|
|
495
|
-
rmSync(
|
|
549
|
+
rmSync(registeredPath(pending), { force: true });
|
|
496
550
|
}
|
|
497
551
|
continue;
|
|
498
552
|
}
|
|
@@ -508,7 +562,7 @@ function consumeRegisteredPending(input) {
|
|
|
508
562
|
for (const marker of markerPaths(pending.role, pending.parentSession, pending)) if (existsSync(marker)) utimesSync(marker, assessedAt, assessedAt);
|
|
509
563
|
renameSync(targetClaim.claim, targetClaim.done);
|
|
510
564
|
renameSync(path, `${path}.done`);
|
|
511
|
-
rmSync(
|
|
565
|
+
rmSync(registeredPath(pending), { force: true });
|
|
512
566
|
rmSync(statePath(targetInput, pending.target), { force: true });
|
|
513
567
|
} finally {
|
|
514
568
|
if (targetClaim) rmSync(targetClaim.claim, { force: true });
|
|
@@ -518,6 +572,10 @@ function consumeRegisteredPending(input) {
|
|
|
518
572
|
}
|
|
519
573
|
|
|
520
574
|
function markSubagentStop(input) {
|
|
575
|
+
if (input.agent_type === "wr-risk-scorer:pipeline" && existsSync(nativePipelinePath(input.session_id))) {
|
|
576
|
+
persistRegisteredPending(input);
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
521
579
|
const state = typeof input.agent_id === "string" ? statePath(input, input.agent_id) : "";
|
|
522
580
|
if (state && existsSync(state)) {
|
|
523
581
|
markTarget(input, input.agent_id, input.last_assistant_message);
|
|
@@ -551,6 +609,7 @@ try {
|
|
|
551
609
|
} else if (!/^[A-Za-z0-9-]+$/.test(input.session_id || "")) {
|
|
552
610
|
if (process.argv.includes("--subagent-stop")) diagnoseSubagentStop(input, "rejected", "invalid-session-id");
|
|
553
611
|
} else {
|
|
612
|
+
if (input.hook_event_name === "SubagentStart") rememberNativePipeline(input);
|
|
554
613
|
if (SPAWN_TOOLS.has(input.tool_name)) rememberSpawn(input);
|
|
555
614
|
if (CLOSE_TOOLS.has(input.tool_name)) markClose(input);
|
|
556
615
|
if (WAIT_TOOLS.has(input.tool_name)) markWait(input);
|
package/hooks/hooks.json
CHANGED
|
@@ -12,6 +12,9 @@
|
|
|
12
12
|
"PostToolUse": [
|
|
13
13
|
{ "matcher": "Agent|Bash|Edit|Skill|Write|collaboration\\.spawn_agent|collaboration\\.wait_agent|collaboration\\.interrupt_agent|collaborationspawn_agent|collaborationwait_agent|collaborationinterrupt_agent|spawn_agent|wait_agent|interrupt_agent|close_agent|multi_agent_v1__spawn_agent|multi_agent_v1__wait_agent|multi_agent_v1__close_agent", "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/hooks/risk-scorer-dispatch.sh post-tool" }] }
|
|
14
14
|
],
|
|
15
|
+
"SubagentStart": [
|
|
16
|
+
{ "matcher": "^wr-risk-scorer:pipeline$", "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/hooks/risk-scorer-dispatch.sh subagent-start" }] }
|
|
17
|
+
],
|
|
15
18
|
"SubagentStop": [
|
|
16
19
|
{ "matcher": "^wr-risk-scorer:", "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/hooks/risk-scorer-dispatch.sh subagent-stop" }] }
|
|
17
20
|
]
|
|
@@ -98,6 +98,9 @@ if messages:
|
|
|
98
98
|
;;
|
|
99
99
|
esac
|
|
100
100
|
;;
|
|
101
|
+
subagent-start)
|
|
102
|
+
printf '%s' "$INPUT" | node "$SCRIPT_DIR/codex-agent-completion.mjs" --subagent-start
|
|
103
|
+
;;
|
|
101
104
|
subagent-stop)
|
|
102
105
|
printf '%s' "$INPUT" | node "$SCRIPT_DIR/codex-agent-completion.mjs" --subagent-stop
|
|
103
106
|
;;
|
package/package.json
CHANGED