@windyroad/risk-scorer 0.18.16 → 0.18.17

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.
@@ -310,5 +310,5 @@
310
310
  }
311
311
  },
312
312
  "name": "wr-risk-scorer",
313
- "version": "0.18.16"
313
+ "version": "0.18.17"
314
314
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wr-risk-scorer",
3
- "version": "0.18.16",
3
+ "version": "0.18.17",
4
4
  "description": "Pipeline risk scoring, commit/push gates, and secret leak detection",
5
5
  "author": {
6
6
  "name": "Windy Road Technology",
@@ -182,7 +182,22 @@ function freshReceipt(path) {
182
182
  return Date.now() - statSync(path).mtimeMs < ttl;
183
183
  }
184
184
 
185
+ function reapExpiredReceipts() {
186
+ if (!existsSync(pendingDir())) return;
187
+ const receipt = /^[0-9a-f]{64}-[0-9a-f]{32}-[0-9a-f]{64}(?:\.claim|\.done)?$/;
188
+ for (const name of readdirSync(pendingDir())) {
189
+ if (!receipt.test(name)) continue;
190
+ const path = join(pendingDir(), name);
191
+ try {
192
+ if (!freshReceipt(path)) rmSync(path, { force: true });
193
+ } catch {
194
+ // A concurrent consumer may have renamed or removed it.
195
+ }
196
+ }
197
+ }
198
+
185
199
  function persistPendingPipeline(input) {
200
+ reapExpiredReceipts();
186
201
  diagnoseSubagentStop(input, "received", "pipeline-receipt-attempt");
187
202
  if (input.agent_type !== "wr-risk-scorer:pipeline") {
188
203
  diagnoseSubagentStop(input, "rejected", "unexpected-agent-type");
@@ -302,6 +317,7 @@ function markSubagentStop(input) {
302
317
 
303
318
  function consumePending(input) {
304
319
  if (!/^[A-Za-z0-9-]+$/.test(input.session_id || "")) return;
320
+ reapExpiredReceipts();
305
321
  let root;
306
322
  try {
307
323
  root = realpathSync(process.cwd());
@@ -49,9 +49,18 @@ check_risk_gate() {
49
49
 
50
50
  # Scores and bypasses belong to the physical checkout that was assessed.
51
51
  # Fail closed for legacy markers that predate this binding.
52
+ if [ ! -s "$CHECKOUT_FILE" ]; then
53
+ RISK_GATE_CATEGORY="drift"
54
+ RISK_GATE_REASON="Risk assessment checkout binding is missing. Delegate to wr-risk-scorer:pipeline (subagent_type: 'wr-risk-scorer:pipeline') to rescore this checkout."
55
+ return 1
56
+ fi
52
57
  if ! _checkout_matches "$CHECKOUT_FILE"; then
53
58
  RISK_GATE_CATEGORY="drift"
54
- RISK_GATE_REASON="Risk assessment checkout binding is missing or does not match the current Git checkout. Delegate to wr-risk-scorer:pipeline (subagent_type: 'wr-risk-scorer:pipeline') to rescore this checkout."
59
+ if [ -n "${CODEX_THREAD_ID:-}" ]; then
60
+ RISK_GATE_REASON="Risk assessment checkout binding does not match the checkout visible to this hook. Retry the same command with an explicit leading \`cd /absolute/path/to/the/assessed-checkout && ...\`; the valid score was preserved, so do not rescore unless that checkout changed."
61
+ else
62
+ RISK_GATE_REASON="Risk assessment checkout binding is missing or does not match the current Git checkout. Delegate to wr-risk-scorer:pipeline (subagent_type: 'wr-risk-scorer:pipeline') to rescore this checkout."
63
+ fi
55
64
  return 1
56
65
  fi
57
66
 
@@ -29,10 +29,11 @@ case "$EVENT" in
29
29
  NUDGE_OUTPUT=""
30
30
  fi
31
31
  if [ -n "${CODEX_THREAD_ID:-}" ]; then
32
- AGENT_OUTPUT="$AGENT_OUTPUT" NUDGE_OUTPUT="$NUDGE_OUTPUT" python3 -c '
32
+ CODEX_CWD_OUTPUT='{"systemMessage":"Codex checkout safety: for git commit, npm run push:watch, npm run release:watch, and changeset commands, put an explicit leading `cd /absolute/git/root &&` inside the command. A tool workdir alone may be hidden from checkout-binding hooks."}'
33
+ AGENT_OUTPUT="$AGENT_OUTPUT" NUDGE_OUTPUT="$NUDGE_OUTPUT" CODEX_CWD_OUTPUT="$CODEX_CWD_OUTPUT" python3 -c '
33
34
  import json, os
34
35
  messages = []
35
- for name in ("AGENT_OUTPUT", "NUDGE_OUTPUT"):
36
+ for name in ("AGENT_OUTPUT", "NUDGE_OUTPUT", "CODEX_CWD_OUTPUT"):
36
37
  try:
37
38
  message = json.loads(os.environ[name]).get("systemMessage", "")
38
39
  except (json.JSONDecodeError, AttributeError):
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windyroad/risk-scorer",
3
- "version": "0.18.16",
3
+ "version": "0.18.17",
4
4
  "description": "Pipeline risk scoring, commit/push gates, and secret leak detection",
5
5
  "scripts": {
6
6
  "prepack": "node scripts/sync-codex-skills.mjs --pack",
@@ -37,11 +37,19 @@ const pipelineCodexInstructions = `
37
37
 
38
38
  ## Codex assessed-checkout binding
39
39
 
40
+ You are the endpoint pipeline scorer. Score the supplied state directly. Do
41
+ not invoke the \`wr-risk-scorer:pipeline\` skill and do not spawn or delegate to
42
+ another pipeline scorer; that wrapper exists for callers, not for this agent.
43
+
40
44
  The request must contain exactly one \`RISK_CWD: <absolute Git root>\` line.
41
45
  Repeat that exact line once after the structured risk output so the completion
42
46
  bridge can bind marker generation to the checkout that was assessed. Do not
43
47
  repeat the path elsewhere. If the request omits the line or provides more than
44
- one, do not emit \`RISK_SCORES\`; report that the assessed checkout is unbound.`;
48
+ one, do not emit \`RISK_SCORES\`; report that the assessed checkout is unbound.
49
+
50
+ The returned \`RISK_CWD\` is also the caller's command root. Subsequent governed
51
+ commands must put \`cd <RISK_CWD> &&\` inside the command itself; a Codex tool
52
+ \`workdir\` alone may be hidden from checkout-binding hooks.`;
45
53
 
46
54
  export const riskAgentSpecs = [
47
55
  ["pipeline", "Scores pipeline actions for cumulative residual risk."],