@windyroad/risk-scorer 0.17.2 → 0.17.3
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/.agents/plugins/marketplace.json +20 -0
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/bin/install.mjs +31 -3
- package/hooks/hooks.json +1 -1
- package/hooks/risk-scorer-dispatch.sh +3 -0
- package/hooks/test/risk-scorer-hook-dispatch.bats +32 -0
- package/hooks/test/wip-risk-mark.bats +64 -0
- package/hooks/wip-risk-mark.sh +42 -7
- package/package.json +6 -1
- package/scripts/sync-codex-skills.mjs +87 -0
- package/skills/assess-external-comms/SKILL.md +8 -4
- package/skills/assess-inbound-report/SKILL.md +12 -8
- package/skills/assess-release/SKILL.md +7 -3
- package/skills/assess-wip/SKILL.md +6 -2
- package/skills/bootstrap-catalog/SKILL.md +5 -1
- package/skills/create-risk/SKILL.md +10 -6
- package/skills/external-comms/SKILL.md +5 -1
- package/skills/pipeline/SKILL.md +5 -1
- package/skills/update-policy/SKILL.md +10 -6
- package/skills/wip/SKILL.md +4 -0
- package/skills/assess-inbound-report/test/assess-inbound-report-contract.bats +0 -132
- package/skills/assess-release/test/assess-skills-delegate-via-skill-tool.bats +0 -162
- package/skills/bootstrap-catalog/test/bootstrap-catalog.bats +0 -168
- package/skills/create-risk/test/create-risk-flag-driven.bats +0 -136
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "windyroad-local",
|
|
3
|
+
"interface": {
|
|
4
|
+
"displayName": "Windy Road Risk Scorer"
|
|
5
|
+
},
|
|
6
|
+
"plugins": [
|
|
7
|
+
{
|
|
8
|
+
"name": "wr-risk-scorer",
|
|
9
|
+
"source": {
|
|
10
|
+
"source": "local",
|
|
11
|
+
"path": "."
|
|
12
|
+
},
|
|
13
|
+
"policy": {
|
|
14
|
+
"installation": "AVAILABLE",
|
|
15
|
+
"authentication": "ON_INSTALL"
|
|
16
|
+
},
|
|
17
|
+
"category": "Developer Tools"
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|
package/bin/install.mjs
CHANGED
|
@@ -8,6 +8,7 @@ const utils = await import(resolve(__dirname, "../lib/install-utils.mjs"));
|
|
|
8
8
|
|
|
9
9
|
const PLUGIN = "wr-risk-scorer";
|
|
10
10
|
const DEPS = [];
|
|
11
|
+
const PACKAGE_ROOT = resolve(__dirname, "..");
|
|
11
12
|
|
|
12
13
|
const flags = utils.parseStandardArgs(process.argv);
|
|
13
14
|
|
|
@@ -35,10 +36,37 @@ if (flags.dryRun) {
|
|
|
35
36
|
|
|
36
37
|
utils.checkPrerequisites({ runtime: flags.runtime });
|
|
37
38
|
|
|
39
|
+
function codexInstall() {
|
|
40
|
+
utils.run(`codex plugin marketplace add ${PACKAGE_ROOT}`, "Codex marketplace: windyroad-local");
|
|
41
|
+
utils.run(`codex plugin add ${PLUGIN}@windyroad-local`, PLUGIN);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function codexUninstall() {
|
|
45
|
+
utils.run(`codex plugin remove ${PLUGIN}`, `Removing ${PLUGIN}`);
|
|
46
|
+
}
|
|
47
|
+
|
|
38
48
|
if (flags.uninstall) {
|
|
39
|
-
|
|
49
|
+
if (flags.runtime === "claude" || flags.runtime === "both") {
|
|
50
|
+
utils.uninstallPackage(PLUGIN, { runtime: "claude" });
|
|
51
|
+
}
|
|
52
|
+
if (flags.runtime === "codex" || flags.runtime === "both") {
|
|
53
|
+
codexUninstall();
|
|
54
|
+
}
|
|
40
55
|
} else if (flags.update) {
|
|
41
|
-
|
|
56
|
+
if (flags.runtime === "claude" || flags.runtime === "both") {
|
|
57
|
+
utils.updatePackage(PLUGIN, { scope: flags.scope, runtime: "claude" });
|
|
58
|
+
}
|
|
59
|
+
if (flags.runtime === "codex" || flags.runtime === "both") {
|
|
60
|
+
codexInstall();
|
|
61
|
+
}
|
|
62
|
+
} else if (flags.runtime === "codex") {
|
|
63
|
+
console.log(`\nInstalling @windyroad/risk-scorer (${flags.scope} scope)...\n`);
|
|
64
|
+
codexInstall();
|
|
65
|
+
console.log("\nDone! Restart Codex to activate.\n");
|
|
66
|
+
} else if (flags.runtime === "both") {
|
|
67
|
+
utils.installPackage(PLUGIN, { deps: DEPS, scope: flags.scope, runtime: "claude" });
|
|
68
|
+
codexInstall();
|
|
69
|
+
console.log("\nDone! Restart Claude Code and Codex to activate.\n");
|
|
42
70
|
} else {
|
|
43
|
-
utils.installPackage(PLUGIN, { deps: DEPS, scope: flags.scope, runtime:
|
|
71
|
+
utils.installPackage(PLUGIN, { deps: DEPS, scope: flags.scope, runtime: "claude" });
|
|
44
72
|
}
|
package/hooks/hooks.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
{ "matcher": "Bash|Edit|Write|ExitPlanMode|EnterPlanMode", "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/hooks/risk-scorer-dispatch.sh pre-tool" }] }
|
|
11
11
|
],
|
|
12
12
|
"PostToolUse": [
|
|
13
|
-
{ "matcher": "Agent|Bash|Skill", "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/hooks/risk-scorer-dispatch.sh post-tool" }] }
|
|
13
|
+
{ "matcher": "Agent|Bash|Edit|Skill|Write", "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/hooks/risk-scorer-dispatch.sh post-tool" }] }
|
|
14
14
|
]
|
|
15
15
|
}
|
|
16
16
|
}
|
|
@@ -43,3 +43,35 @@ PY
|
|
|
43
43
|
[[ "$output" == *"deny"* ]]
|
|
44
44
|
[[ "$output" == *"AWS access key"* ]]
|
|
45
45
|
}
|
|
46
|
+
|
|
47
|
+
@test "dispatcher routes PostToolUse Write through the WIP nudge" {
|
|
48
|
+
local dir input orig
|
|
49
|
+
dir="$(mktemp -d)"
|
|
50
|
+
orig="$PWD"
|
|
51
|
+
mkdir -p "$dir/repo" "$dir/tmp"
|
|
52
|
+
cd "$dir/repo"
|
|
53
|
+
git init -q
|
|
54
|
+
git config user.email test@example.com
|
|
55
|
+
git config user.name "Test User"
|
|
56
|
+
printf 'base\n' > base.txt
|
|
57
|
+
git add base.txt
|
|
58
|
+
git commit -q -m initial
|
|
59
|
+
mkdir -p src
|
|
60
|
+
printf 'one\n' > src/one.txt
|
|
61
|
+
printf 'two\n' > src/two.txt
|
|
62
|
+
printf 'three\n' > src/three.txt
|
|
63
|
+
input="$(python3 - <<'PY'
|
|
64
|
+
import json
|
|
65
|
+
print(json.dumps({
|
|
66
|
+
"tool_name": "Write",
|
|
67
|
+
"session_id": "dispatch-wip",
|
|
68
|
+
"tool_input": {"file_path": "src/three.txt"},
|
|
69
|
+
}))
|
|
70
|
+
PY
|
|
71
|
+
)"
|
|
72
|
+
run env TMPDIR="$dir/tmp" bash "$HOOKS/risk-scorer-dispatch.sh" post-tool <<<"$input"
|
|
73
|
+
cd "$orig"
|
|
74
|
+
rm -rf "$dir"
|
|
75
|
+
[ "$status" -eq 0 ]
|
|
76
|
+
[[ "$output" == *"Batching risk rising"* ]]
|
|
77
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
#!/usr/bin/env bats
|
|
2
|
+
|
|
3
|
+
setup() {
|
|
4
|
+
REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../../.." && pwd)"
|
|
5
|
+
HOOK="$REPO_ROOT/packages/risk-scorer/hooks/wip-risk-mark.sh"
|
|
6
|
+
ORIG_DIR="$PWD"
|
|
7
|
+
TEST_DIR="$(mktemp -d)"
|
|
8
|
+
TMPDIR="$TEST_DIR/tmp"
|
|
9
|
+
export TMPDIR
|
|
10
|
+
mkdir -p "$TMPDIR"
|
|
11
|
+
mkdir -p "$TEST_DIR/repo"
|
|
12
|
+
cd "$TEST_DIR/repo"
|
|
13
|
+
git init -q
|
|
14
|
+
git config user.email test@example.com
|
|
15
|
+
git config user.name "Test User"
|
|
16
|
+
printf 'base\n' > base.txt
|
|
17
|
+
git add base.txt
|
|
18
|
+
git commit -q -m initial
|
|
19
|
+
SESSION_ID="wip-mark-$$"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
teardown() {
|
|
23
|
+
cd "$ORIG_DIR"
|
|
24
|
+
rm -rf "$TEST_DIR"
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
run_hook() {
|
|
28
|
+
python3 - "$SESSION_ID" <<'PY' | bash "$HOOK"
|
|
29
|
+
import json
|
|
30
|
+
import sys
|
|
31
|
+
print(json.dumps({
|
|
32
|
+
"tool_name": "Write",
|
|
33
|
+
"session_id": sys.argv[1],
|
|
34
|
+
"tool_input": {"file_path": "src/example.txt"},
|
|
35
|
+
}))
|
|
36
|
+
PY
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@test "wip-risk-mark nudges once when accumulated WIP crosses the small-batch threshold" {
|
|
40
|
+
mkdir -p src
|
|
41
|
+
printf 'one\n' > src/one.txt
|
|
42
|
+
printf 'two\n' > src/two.txt
|
|
43
|
+
printf 'three\n' > src/three.txt
|
|
44
|
+
|
|
45
|
+
run run_hook
|
|
46
|
+
[ "$status" -eq 0 ]
|
|
47
|
+
[[ "$output" == *"Batching risk rising: 3 changed files"* ]]
|
|
48
|
+
[[ "$output" == *"committing a coherent slice now"* ]]
|
|
49
|
+
[[ "$output" == *"push and release small batches"* ]]
|
|
50
|
+
|
|
51
|
+
run run_hook
|
|
52
|
+
[ "$status" -eq 0 ]
|
|
53
|
+
[ -z "$output" ]
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@test "wip-risk-mark stays silent below threshold" {
|
|
57
|
+
mkdir -p src
|
|
58
|
+
printf 'one\n' > src/one.txt
|
|
59
|
+
printf 'two\n' > src/two.txt
|
|
60
|
+
|
|
61
|
+
run run_hook
|
|
62
|
+
[ "$status" -eq 0 ]
|
|
63
|
+
[ -z "$output" ]
|
|
64
|
+
}
|
package/hooks/wip-risk-mark.sh
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# PostToolUse hook:
|
|
3
|
-
# - After Edit/Write on non-doc files: clears the marker (blocks next edit)
|
|
4
|
-
# - After Agent (risk-scorer) completion: creates the marker (unblocks next edit)
|
|
2
|
+
# PostToolUse hook: soft nudge for accumulated WIP.
|
|
5
3
|
|
|
6
4
|
set -euo pipefail
|
|
7
5
|
|
|
@@ -15,10 +13,47 @@ TOOL_NAME=$(_get_tool_name)
|
|
|
15
13
|
SESSION_ID=$(_get_session_id)
|
|
16
14
|
[ -n "$SESSION_ID" ] || exit 0
|
|
17
15
|
|
|
18
|
-
|
|
16
|
+
case "$TOOL_NAME" in
|
|
17
|
+
Edit|Write) ;;
|
|
18
|
+
*) exit 0 ;;
|
|
19
|
+
esac
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
ROOT=$(git rev-parse --show-toplevel 2>/dev/null || true)
|
|
22
|
+
[ -n "$ROOT" ] || exit 0
|
|
23
|
+
cd "$ROOT"
|
|
24
|
+
|
|
25
|
+
STATUS_COUNT=$(git status --short --untracked-files=all 2>/dev/null | wc -l | tr -d ' ')
|
|
26
|
+
SHORTSTAT=$(git diff HEAD --shortstat 2>/dev/null || true)
|
|
27
|
+
INSERTIONS=$(printf '%s' "$SHORTSTAT" | sed -n 's/.* \([0-9][0-9]*\) insertion.*/\1/p')
|
|
28
|
+
DELETIONS=$(printf '%s' "$SHORTSTAT" | sed -n 's/.* \([0-9][0-9]*\) deletion.*/\1/p')
|
|
29
|
+
INSERTIONS=${INSERTIONS:-0}
|
|
30
|
+
DELETIONS=${DELETIONS:-0}
|
|
31
|
+
TOTAL_LINES=$((INSERTIONS + DELETIONS))
|
|
32
|
+
|
|
33
|
+
# ponytail: fixed early nudge threshold; make project-configurable only after real false positives.
|
|
34
|
+
if [ "$STATUS_COUNT" -lt 3 ] && [ "$TOTAL_LINES" -lt 80 ]; then
|
|
35
|
+
exit 0
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
RDIR=$(_risk_dir "$SESSION_ID")
|
|
39
|
+
KEY="${STATUS_COUNT}:${INSERTIONS}:${DELETIONS}"
|
|
40
|
+
KEY_FILE="${RDIR}/wip-nudge-key"
|
|
41
|
+
if [ -f "$KEY_FILE" ] && [ "$(cat "$KEY_FILE" 2>/dev/null || true)" = "$KEY" ]; then
|
|
42
|
+
exit 0
|
|
43
|
+
fi
|
|
44
|
+
printf '%s\n' "$KEY" > "$KEY_FILE"
|
|
45
|
+
|
|
46
|
+
python3 - "$STATUS_COUNT" "$INSERTIONS" "$DELETIONS" <<'PY'
|
|
47
|
+
import json
|
|
48
|
+
import sys
|
|
49
|
+
|
|
50
|
+
files, insertions, deletions = sys.argv[1:4]
|
|
51
|
+
print(json.dumps({
|
|
52
|
+
"systemMessage": (
|
|
53
|
+
f"Batching risk rising: {files} changed files, +{insertions}/-{deletions} since HEAD. "
|
|
54
|
+
"Keep risk low by committing a coherent slice now; push and release small batches instead of accumulating them."
|
|
55
|
+
)
|
|
56
|
+
}))
|
|
57
|
+
PY
|
|
23
58
|
|
|
24
59
|
exit 0
|
package/package.json
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@windyroad/risk-scorer",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.3",
|
|
4
4
|
"description": "Pipeline risk scoring, commit/push gates, and secret leak detection",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"prepack": "node scripts/sync-codex-skills.mjs --pack",
|
|
7
|
+
"postpack": "node scripts/sync-codex-skills.mjs --restore-pack"
|
|
8
|
+
},
|
|
5
9
|
"bin": {
|
|
6
10
|
"windyroad-risk-scorer": "./bin/install.mjs"
|
|
7
11
|
},
|
|
@@ -23,6 +27,7 @@
|
|
|
23
27
|
"agents/",
|
|
24
28
|
"hooks/",
|
|
25
29
|
"skills/",
|
|
30
|
+
".agents/",
|
|
26
31
|
".claude-plugin/",
|
|
27
32
|
".codex-plugin/",
|
|
28
33
|
"lib/",
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
existsSync,
|
|
5
|
+
mkdirSync,
|
|
6
|
+
readdirSync,
|
|
7
|
+
readFileSync,
|
|
8
|
+
renameSync,
|
|
9
|
+
rmSync,
|
|
10
|
+
writeFileSync,
|
|
11
|
+
} from "node:fs";
|
|
12
|
+
import { dirname, join, resolve } from "node:path";
|
|
13
|
+
import { fileURLToPath } from "node:url";
|
|
14
|
+
|
|
15
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
16
|
+
const __dirname = dirname(__filename);
|
|
17
|
+
const packageRoot = resolve(__dirname, "..");
|
|
18
|
+
const skillsRoot = join(packageRoot, "skills");
|
|
19
|
+
const backupRoot = join(packageRoot, ".pack-claude-skills");
|
|
20
|
+
const mode = process.argv.includes("--check") ? "check" : "sync";
|
|
21
|
+
const packMode = process.argv.includes("--pack");
|
|
22
|
+
const restoreMode = process.argv.includes("--restore-pack");
|
|
23
|
+
|
|
24
|
+
const preamble = `<!-- Generated from packages/risk-scorer/skills/*/SKILL.md by packages/risk-scorer/scripts/sync-codex-skills.mjs during npm pack. Do not edit packaged output directly. -->
|
|
25
|
+
|
|
26
|
+
> Codex runtime note: use \`request_user_input\` where this skill needs structured user input. If a step refers to Claude-style agent dispatch or \`subagent_type\`, invoke the matching installed Codex agent when available; in \`codex exec\` or any runtime without custom-agent dispatch, perform the same review inline from the plugin's sibling \`agents/*.md\` instructions and preserve the structured verdict blocks.
|
|
27
|
+
|
|
28
|
+
`;
|
|
29
|
+
|
|
30
|
+
function transform(text) {
|
|
31
|
+
return preamble + text
|
|
32
|
+
.replaceAll("AskUserQuestion", "request_user_input")
|
|
33
|
+
.replaceAll("`.claude/agents/risk-scorer-pipeline.md`", "`agents/pipeline.md`");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function generatedFiles(sourceRoot, targetRoot) {
|
|
37
|
+
const entries = readdirSync(sourceRoot, { withFileTypes: true })
|
|
38
|
+
.filter((entry) => entry.isDirectory())
|
|
39
|
+
.map((entry) => entry.name)
|
|
40
|
+
.sort();
|
|
41
|
+
|
|
42
|
+
const generated = [];
|
|
43
|
+
for (const entry of entries) {
|
|
44
|
+
const source = join(sourceRoot, entry, "SKILL.md");
|
|
45
|
+
if (!existsSync(source)) {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
generated.push({
|
|
49
|
+
path: join(targetRoot, entry, "SKILL.md"),
|
|
50
|
+
text: transform(readFileSync(source, "utf8")),
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return generated;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function writeGenerated(sourceRoot, targetRoot) {
|
|
57
|
+
const generated = generatedFiles(sourceRoot, targetRoot);
|
|
58
|
+
rmSync(targetRoot, { recursive: true, force: true });
|
|
59
|
+
for (const { path, text } of generated) {
|
|
60
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
61
|
+
writeFileSync(path, text, "utf8");
|
|
62
|
+
}
|
|
63
|
+
return generated.length;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (restoreMode) {
|
|
67
|
+
if (existsSync(backupRoot)) {
|
|
68
|
+
rmSync(skillsRoot, { recursive: true, force: true });
|
|
69
|
+
renameSync(backupRoot, skillsRoot);
|
|
70
|
+
console.log("Restored Claude skill source after pack.");
|
|
71
|
+
}
|
|
72
|
+
process.exit(0);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (packMode) {
|
|
76
|
+
if (existsSync(backupRoot)) {
|
|
77
|
+
console.error(`Refusing to pack: backup already exists at ${backupRoot}`);
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
renameSync(skillsRoot, backupRoot);
|
|
81
|
+
const count = writeGenerated(backupRoot, skillsRoot);
|
|
82
|
+
console.log(`Packed ${count} Codex-facing risk-scorer skill file(s).`);
|
|
83
|
+
process.exit(0);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
console.error("Usage: sync-codex-skills.mjs --pack | --restore-pack");
|
|
87
|
+
process.exit(mode === "check" ? 0 : 2);
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
<!-- Generated from packages/risk-scorer/skills/*/SKILL.md by packages/risk-scorer/scripts/sync-codex-skills.mjs during npm pack. Do not edit packaged output directly. -->
|
|
2
|
+
|
|
3
|
+
> Codex runtime note: use `request_user_input` where this skill needs structured user input. If a step refers to Claude-style agent dispatch or `subagent_type`, invoke the matching installed Codex agent when available; in `codex exec` or any runtime without custom-agent dispatch, perform the same review inline from the plugin's sibling `agents/*.md` instructions and preserve the structured verdict blocks.
|
|
4
|
+
|
|
1
5
|
---
|
|
2
6
|
name: wr-risk-scorer:assess-external-comms
|
|
3
7
|
description: On-demand external-comms risk review. Reviews a draft of an outbound prose tool call (gh issue/pr body, security advisory, npm publish content, or .changeset/*.md body) for confidential-information leaks per RISK-POLICY.md. Delegates to wr-risk-scorer:external-comms and pre-satisfies the external-comms-gate marker for the current session.
|
|
4
|
-
allowed-tools: Read, Glob, Grep, Bash,
|
|
8
|
+
allowed-tools: Read, Glob, Grep, Bash, request_user_input, Skill
|
|
5
9
|
---
|
|
6
10
|
|
|
7
11
|
# External-Comms Risk Assessment Skill
|
|
@@ -32,11 +36,11 @@ If both draft and surface are present, proceed to step 3. If either is missing,
|
|
|
32
36
|
|
|
33
37
|
### 2. Resolve missing context
|
|
34
38
|
|
|
35
|
-
If the draft is missing, use `
|
|
39
|
+
If the draft is missing, use `request_user_input`:
|
|
36
40
|
|
|
37
41
|
> "What draft do you want me to review? Paste the body verbatim — I will pass it to the external-comms reviewer."
|
|
38
42
|
|
|
39
|
-
If the surface is missing AND cannot be inferred from context (e.g. user just said "before I post this comment"), use `
|
|
43
|
+
If the surface is missing AND cannot be inferred from context (e.g. user just said "before I post this comment"), use `request_user_input`:
|
|
40
44
|
|
|
41
45
|
- header: "Target surface"
|
|
42
46
|
- options:
|
|
@@ -94,7 +98,7 @@ Present the full review report to the user. Highlight:
|
|
|
94
98
|
|
|
95
99
|
### 6. Above-appetite handling (ADR-013 Rule 6)
|
|
96
100
|
|
|
97
|
-
If the verdict is FAIL, do NOT auto-rewrite the draft. Use `
|
|
101
|
+
If the verdict is FAIL, do NOT auto-rewrite the draft. Use `request_user_input`:
|
|
98
102
|
|
|
99
103
|
- header: "Leak detected — next step"
|
|
100
104
|
- options:
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
<!-- Generated from packages/risk-scorer/skills/*/SKILL.md by packages/risk-scorer/scripts/sync-codex-skills.mjs during npm pack. Do not edit packaged output directly. -->
|
|
2
|
+
|
|
3
|
+
> Codex runtime note: use `request_user_input` where this skill needs structured user input. If a step refers to Claude-style agent dispatch or `subagent_type`, invoke the matching installed Codex agent when available; in `codex exec` or any runtime without custom-agent dispatch, perform the same review inline from the plugin's sibling `agents/*.md` instructions and preserve the structured verdict blocks.
|
|
4
|
+
|
|
1
5
|
---
|
|
2
6
|
name: wr-risk-scorer:assess-inbound-report
|
|
3
7
|
description: On-demand inbound-report risk review. Reviews a third-party submission against this repo's intake (problem-report issue body, Q&A discussion, security-advisory body) for Request-risk (info-extraction / backdoor request / malicious-code injection) and Fix-risk (privilege escalation / removal of load-bearing safety check / adopter-attack-surface expansion) per RISK-POLICY.md. Delegates to wr-risk-scorer:inbound-report and emits the structured verdict consumed by ADR-062's assessment-pipeline branch routing.
|
|
4
|
-
allowed-tools: Read, Glob, Grep, Bash,
|
|
8
|
+
allowed-tools: Read, Glob, Grep, Bash, request_user_input, Skill
|
|
5
9
|
---
|
|
6
10
|
|
|
7
11
|
# Inbound-Report Risk Assessment Skill
|
|
@@ -39,13 +43,13 @@ If the body is missing AND a `gh issue URL` / `<repo>#<issue-number>` reference
|
|
|
39
43
|
gh issue view "$ref" --json body,author,title,labels --jq '.'
|
|
40
44
|
```
|
|
41
45
|
|
|
42
|
-
Cache the JSON for downstream steps. Fail-soft on GH API errors — surface the error to the user and fall back to
|
|
46
|
+
Cache the JSON for downstream steps. Fail-soft on GH API errors — surface the error to the user and fall back to request_user_input.
|
|
43
47
|
|
|
44
|
-
If the body is still missing, use `
|
|
48
|
+
If the body is still missing, use `request_user_input`:
|
|
45
49
|
|
|
46
50
|
> "What report do you want me to review? Paste the body verbatim, or give me a `gh issue URL`."
|
|
47
51
|
|
|
48
|
-
If the surface is missing AND cannot be inferred (from the URL pattern or context), use `
|
|
52
|
+
If the surface is missing AND cannot be inferred (from the URL pattern or context), use `request_user_input`:
|
|
49
53
|
|
|
50
54
|
- header: "Inbound surface"
|
|
51
55
|
- options:
|
|
@@ -86,9 +90,9 @@ Present the full review report to the user. Highlight:
|
|
|
86
90
|
|
|
87
91
|
### 6. Above-appetite handling (ADR-013 Rule 6 + ADR-062 mechanical-stage carve-out)
|
|
88
92
|
|
|
89
|
-
The branch decision itself is **mechanical** per ADR-062 § Mechanical-stage carve-out (P132). When invoked as a pipeline pre-satisfier, this skill does NOT use `
|
|
93
|
+
The branch decision itself is **mechanical** per ADR-062 § Mechanical-stage carve-out (P132). When invoked as a pipeline pre-satisfier, this skill does NOT use `request_user_input` to ask the maintainer "which branch?" — the verdict + class determine the branch deterministically. The maintainer's role is to accept or override the verdict via re-running with corrections, not to pick the branch.
|
|
90
94
|
|
|
91
|
-
When invoked manually as an on-demand pre-flight (NOT as a pipeline pre-satisfier), surface a single `
|
|
95
|
+
When invoked manually as an on-demand pre-flight (NOT as a pipeline pre-satisfier), surface a single `request_user_input` for what the maintainer wants to do next:
|
|
92
96
|
|
|
93
97
|
- header: "Next step"
|
|
94
98
|
- options:
|
|
@@ -110,14 +114,14 @@ This skill and the assessment-pipeline (ADR-062 § Decision Outcome) invoke the
|
|
|
110
114
|
| Branch decision | Per ADR-062 § Decision Outcome; mechanical | Same |
|
|
111
115
|
| Audit-log append | Yes (via PostToolUse hook) | Yes (via PostToolUse hook) |
|
|
112
116
|
| README rankings impact | None (skill is read-only) | Refreshes `## Inbound Upstream Reports` section in `docs/problems/README.md` Step 9e |
|
|
113
|
-
|
|
|
117
|
+
| request_user_input authority | step 6 above (manual only) | None (mechanical-stage carve-out per P132) |
|
|
114
118
|
|
|
115
119
|
## ADR cross-references
|
|
116
120
|
|
|
117
121
|
- **ADR-062** (Inbound upstream-report discovery + assessment pipeline) — § Sibling subagent + § Mechanical-stage carve-out.
|
|
118
122
|
- **ADR-015** (On-demand assessment skills) — § Scope table extended with the `assess-inbound-report` row; § Naming Convention `assess-<artifact>` pattern; § Gate Marker Interaction (no skill-side marker writes).
|
|
119
123
|
- **ADR-009** (Gate marker lifecycle) — per-report marker TTL + drift discipline; same as the existing `external-comms-gate` marker.
|
|
120
|
-
- **ADR-013 Rule 1** + Rule 6 — `
|
|
124
|
+
- **ADR-013 Rule 1** + Rule 6 — `request_user_input` only at maintainer-direction branches; mechanical-stage carve-out applies to pipeline invocations.
|
|
121
125
|
- **ADR-014** — assessment skills are read-only and exempt from commit obligation.
|
|
122
126
|
- **ADR-028** (External-comms gate, amended) — the pushback / clear-malicious-verdict comments the assessment-pipeline posts after this skill's FAIL verdict ride the P064 + P038 evaluator halves.
|
|
123
127
|
- **ADR-029** (Diagnose before implement) — verdict follows hypothesis / evidence / structured-verdict discipline.
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
<!-- Generated from packages/risk-scorer/skills/*/SKILL.md by packages/risk-scorer/scripts/sync-codex-skills.mjs during npm pack. Do not edit packaged output directly. -->
|
|
2
|
+
|
|
3
|
+
> Codex runtime note: use `request_user_input` where this skill needs structured user input. If a step refers to Claude-style agent dispatch or `subagent_type`, invoke the matching installed Codex agent when available; in `codex exec` or any runtime without custom-agent dispatch, perform the same review inline from the plugin's sibling `agents/*.md` instructions and preserve the structured verdict blocks.
|
|
4
|
+
|
|
1
5
|
---
|
|
2
6
|
name: wr-risk-scorer:assess-release
|
|
3
7
|
description: On-demand release risk assessment. Scores commit, push, and release risk for the current unpushed changes. Delegates to wr-risk-scorer:pipeline and satisfies the commit gate for the current session.
|
|
4
|
-
allowed-tools: Read, Glob, Grep, Bash,
|
|
8
|
+
allowed-tools: Read, Glob, Grep, Bash, request_user_input, Skill
|
|
5
9
|
---
|
|
6
10
|
|
|
7
11
|
# Release Risk Assessment Skill
|
|
@@ -44,7 +48,7 @@ Summarise what you find:
|
|
|
44
48
|
|
|
45
49
|
### 3. Resolve ambiguity
|
|
46
50
|
|
|
47
|
-
If the scope is genuinely ambiguous (e.g., no unpushed commits but the user said "assess the release"), use `
|
|
51
|
+
If the scope is genuinely ambiguous (e.g., no unpushed commits but the user said "assess the release"), use `request_user_input` to ask:
|
|
48
52
|
|
|
49
53
|
> "I don't see any unpushed commits. What scope should I assess?
|
|
50
54
|
> (a) All commits since the last git tag
|
|
@@ -82,6 +86,6 @@ Present the full risk report to the user. Highlight:
|
|
|
82
86
|
- Any risks above appetite (score ≥ 5 per RISK-POLICY.md)
|
|
83
87
|
- Whether the gate is now pre-satisfied for the current session (i.e., a subsequent `git commit` will reuse the bypass marker without re-triggering the scorer)
|
|
84
88
|
|
|
85
|
-
If any score is above appetite, the action is **framework-mediated, not a user decision** (P377/RFC-029; ADR-044 category-3 explicitly excludes above-appetite). Per **ADR-042 Rule 1**: auto-apply scorer remediations incrementally until residual risk is within appetite, OR halt per ADR-042 Rule 5 if the scorer cannot converge. **MUST NOT commit/push/release above appetite, and MUST NOT use `
|
|
89
|
+
If any score is above appetite, the action is **framework-mediated, not a user decision** (P377/RFC-029; ADR-044 category-3 explicitly excludes above-appetite). Per **ADR-042 Rule 1**: auto-apply scorer remediations incrementally until residual risk is within appetite, OR halt per ADR-042 Rule 5 if the scorer cannot converge. **MUST NOT commit/push/release above appetite, and MUST NOT use `request_user_input` to ask whether to proceed anyway** — there is no "proceed anyway (bypass)" option; the answer is always reduce-risk-or-halt. The only sanctioned non-blocking path is the risk-reducing path (a genuinely risk-reducing change clears via the `reducing` bypass). Under non-interactive contexts the ADR-013 Rule 6 fail-safe is the terminal fallback: skip the action and report the uncommitted/unreleased state.
|
|
86
90
|
|
|
87
91
|
$ARGUMENTS
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
<!-- Generated from packages/risk-scorer/skills/*/SKILL.md by packages/risk-scorer/scripts/sync-codex-skills.mjs during npm pack. Do not edit packaged output directly. -->
|
|
2
|
+
|
|
3
|
+
> Codex runtime note: use `request_user_input` where this skill needs structured user input. If a step refers to Claude-style agent dispatch or `subagent_type`, invoke the matching installed Codex agent when available; in `codex exec` or any runtime without custom-agent dispatch, perform the same review inline from the plugin's sibling `agents/*.md` instructions and preserve the structured verdict blocks.
|
|
4
|
+
|
|
1
5
|
---
|
|
2
6
|
name: wr-risk-scorer:assess-wip
|
|
3
7
|
description: On-demand WIP risk nudge. Scores the current uncommitted diff for pipeline risk. Use during development to catch high-risk changes before committing.
|
|
4
|
-
allowed-tools: Read, Glob, Grep, Bash,
|
|
8
|
+
allowed-tools: Read, Glob, Grep, Bash, request_user_input, Skill
|
|
5
9
|
---
|
|
6
10
|
|
|
7
11
|
# WIP Risk Assessment Skill
|
|
@@ -65,6 +69,6 @@ Present the WIP risk nudge to the user. The wip subagent provides guidance and r
|
|
|
65
69
|
> "The uncommitted changes look like completed governance work. Commit now to reduce WIP and feed the pipeline."
|
|
66
70
|
> *Reason: `<RISK_COMMIT_REASON from subagent>`*
|
|
67
71
|
|
|
68
|
-
Use `
|
|
72
|
+
Use `request_user_input` to offer: "Commit completed governance work now?" — Yes (user confirms and runs `git commit`) or "Not yet" (user defers).
|
|
69
73
|
|
|
70
74
|
$ARGUMENTS
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
<!-- Generated from packages/risk-scorer/skills/*/SKILL.md by packages/risk-scorer/scripts/sync-codex-skills.mjs during npm pack. Do not edit packaged output directly. -->
|
|
2
|
+
|
|
3
|
+
> Codex runtime note: use `request_user_input` where this skill needs structured user input. If a step refers to Claude-style agent dispatch or `subagent_type`, invoke the matching installed Codex agent when available; in `codex exec` or any runtime without custom-agent dispatch, perform the same review inline from the plugin's sibling `agents/*.md` instructions and preserve the structured verdict blocks.
|
|
4
|
+
|
|
1
5
|
---
|
|
2
6
|
name: wr-risk-scorer:bootstrap-catalog
|
|
3
7
|
description: Bootstrap docs/risks/ standing-risk catalog from existing .risk-reports/ corpus. Walks reports, dedupes by ADR-056 slug, emits one R<NNN>-<slug>.active.md per unique slug with ## Source Evidence block citing originating reports. Idempotent — re-runs are no-ops by file-existence per slug. One-shot per project lifetime; install-updates Step 6.5 auto-triggers when catalog is empty AND .risk-reports/ is non-empty AND RISK-POLICY.md is present.
|
|
@@ -158,7 +162,7 @@ ADR-026 (grounding sentinel), ADR-047 (Phase 1 directory scaffold
|
|
|
158
162
|
parent), P168 (driver).
|
|
159
163
|
```
|
|
160
164
|
|
|
161
|
-
The commit goes through architect / JTBD / risk-scorer review per ADR-014. Per ADR-013 Rule 5, the bootstrap action is policy-authorised silent proceed — no `
|
|
165
|
+
The commit goes through architect / JTBD / risk-scorer review per ADR-014. Per ADR-013 Rule 5, the bootstrap action is policy-authorised silent proceed — no `request_user_input` round-trip needed; the catalog framing in `RISK-POLICY.md` IS the policy authorisation, and the skill's pre-conditions (Step 0) verify the project opted in.
|
|
162
166
|
|
|
163
167
|
### 9. Report
|
|
164
168
|
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
<!-- Generated from packages/risk-scorer/skills/*/SKILL.md by packages/risk-scorer/scripts/sync-codex-skills.mjs during npm pack. Do not edit packaged output directly. -->
|
|
2
|
+
|
|
3
|
+
> Codex runtime note: use `request_user_input` where this skill needs structured user input. If a step refers to Claude-style agent dispatch or `subagent_type`, invoke the matching installed Codex agent when available; in `codex exec` or any runtime without custom-agent dispatch, perform the same review inline from the plugin's sibling `agents/*.md` instructions and preserve the structured verdict blocks.
|
|
4
|
+
|
|
1
5
|
---
|
|
2
6
|
name: wr-risk-scorer:create-risk
|
|
3
7
|
description: Create a new standing-risk entry in docs/risks/. Examines existing risks, gathers impact/likelihood/controls from the user, writes a file using the entry shape inlined in this skill (no TEMPLATE.md dependency — the entry shape is owned by this skill per user direction 2026-05-04), and updates the register index.
|
|
4
|
-
allowed-tools: Read, Write, Edit, Bash, Glob, Grep,
|
|
8
|
+
allowed-tools: Read, Write, Edit, Bash, Glob, Grep, request_user_input
|
|
5
9
|
---
|
|
6
10
|
|
|
7
11
|
# Risk Register Entry Generator
|
|
@@ -57,15 +61,15 @@ Aggregated from N `.risk-reports/` entries (slug: `<slug>`):
|
|
|
57
61
|
Re-rate when human curation lands or when controls change.
|
|
58
62
|
```
|
|
59
63
|
|
|
60
|
-
**Skip
|
|
64
|
+
**Skip request_user_input** under this path entirely. Per CLAUDE.md P132 (inverse-P078): the framework has resolved the decision via ADR-056 queue + ADR-013 Rule 5 policy authorisation. Per-class consent gates re-ask decisions the user already made.
|
|
61
65
|
|
|
62
|
-
**Existing
|
|
66
|
+
**Existing request_user_input path preserved for human invocation** (no `--slug` / `--prefill` flags) — fall through to Step 2 below for full interactive authoring.
|
|
63
67
|
|
|
64
68
|
**README.md update**: under flag-driven path, append a row to `docs/risks/README.md` Register table with stub scoring (`—` em-dash) and Treatment column = `pending`. Same shape as Step 6 below but auto-applied without user prompts.
|
|
65
69
|
|
|
66
70
|
### 2. Gather context from the user
|
|
67
71
|
|
|
68
|
-
You MUST use the
|
|
72
|
+
You MUST use the request_user_input tool to collect context that cannot be derived. Do not proceed to step 3 until you have answers. Apply ADR-013 Rule 6 non-interactive defaults if the tool is unavailable (AFK mode): choose the most conservative option for each question and note auto-selection in the output.
|
|
69
73
|
|
|
70
74
|
Auto-derive where possible (do not ask):
|
|
71
75
|
- **ID number** — next free slot per step 3 (do not ask per `feedback_dont_ask_trivial_id_choices.md`).
|
|
@@ -73,7 +77,7 @@ Auto-derive where possible (do not ask):
|
|
|
73
77
|
- **Category** — infer from description keywords where unambiguous: "token", "secret", "leak" → `infosec`; "install", "hook", "pipeline" → `operational`. Confirm only if ambiguous.
|
|
74
78
|
- **Next review** — default to 6 months from today.
|
|
75
79
|
|
|
76
|
-
Ask the user (one
|
|
80
|
+
Ask the user (one request_user_input call with grouped questions):
|
|
77
81
|
|
|
78
82
|
1. **What is the risk?** A short title and 1-2 paragraph description — what could go wrong, for whom, and why it matters. This is the condition, not the control.
|
|
79
83
|
2. **Impact level (from `RISK-POLICY.md`)?** 1 Negligible · 2 Minor · 3 Moderate · 4 Significant · 5 Severe. Read the policy's Impact table to the user if they need the descriptions.
|
|
@@ -190,7 +194,7 @@ This step is not optional: the README drifts from the register without it, and t
|
|
|
190
194
|
|
|
191
195
|
### 7. Confirm with the user
|
|
192
196
|
|
|
193
|
-
Present the written file path, inherent/residual bands, and any `Within appetite?: No` flag. Ask via
|
|
197
|
+
Present the written file path, inherent/residual bands, and any `Within appetite?: No` flag. Ask via request_user_input:
|
|
194
198
|
|
|
195
199
|
1. Does the description accurately capture the risk?
|
|
196
200
|
2. Are the inherent and residual scores defensible?
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
<!-- Generated from packages/risk-scorer/skills/*/SKILL.md by packages/risk-scorer/scripts/sync-codex-skills.mjs during npm pack. Do not edit packaged output directly. -->
|
|
2
|
+
|
|
3
|
+
> Codex runtime note: use `request_user_input` where this skill needs structured user input. If a step refers to Claude-style agent dispatch or `subagent_type`, invoke the matching installed Codex agent when available; in `codex exec` or any runtime without custom-agent dispatch, perform the same review inline from the plugin's sibling `agents/*.md` instructions and preserve the structured verdict blocks.
|
|
4
|
+
|
|
1
5
|
---
|
|
2
6
|
name: wr-risk-scorer:external-comms
|
|
3
7
|
description: Invokable SKILL wrapper around the wr-risk-scorer:external-comms leak-review agent. Delegates to the agent via the Agent tool and returns the agent's structured EXTERNAL_COMMS_RISK_VERDICT. Internal-use plumbing used by `/wr-risk-scorer:assess-external-comms` per ADR-015's Confirmation literal phrasing. End users should invoke `/wr-risk-scorer:assess-external-comms` instead.
|
|
@@ -8,7 +12,7 @@ allowed-tools: Read, Glob, Grep, Bash, Agent
|
|
|
8
12
|
|
|
9
13
|
This SKILL is an **invokable wrapper** around the `wr-risk-scorer:external-comms` agent. It exists so consumer SKILLs can invoke the leak reviewer via the **Skill tool** with `skill: wr-risk-scorer:external-comms` — matching ADR-015's Confirmation literal phrasing.
|
|
10
14
|
|
|
11
|
-
**End users**: invoke `/wr-risk-scorer:assess-external-comms` instead. This wrapper is internal-use plumbing — calling it directly returns the raw verdict without the structured
|
|
15
|
+
**End users**: invoke `/wr-risk-scorer:assess-external-comms` instead. This wrapper is internal-use plumbing — calling it directly returns the raw verdict without the structured request_user_input above-appetite handling (Rewrite / Move to private channel / Override / Cancel) that `/wr-risk-scorer:assess-external-comms` provides.
|
|
12
16
|
|
|
13
17
|
## Contract
|
|
14
18
|
|
package/skills/pipeline/SKILL.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
<!-- Generated from packages/risk-scorer/skills/*/SKILL.md by packages/risk-scorer/scripts/sync-codex-skills.mjs during npm pack. Do not edit packaged output directly. -->
|
|
2
|
+
|
|
3
|
+
> Codex runtime note: use `request_user_input` where this skill needs structured user input. If a step refers to Claude-style agent dispatch or `subagent_type`, invoke the matching installed Codex agent when available; in `codex exec` or any runtime without custom-agent dispatch, perform the same review inline from the plugin's sibling `agents/*.md` instructions and preserve the structured verdict blocks.
|
|
4
|
+
|
|
1
5
|
---
|
|
2
6
|
name: wr-risk-scorer:pipeline
|
|
3
7
|
description: Invokable SKILL wrapper around the wr-risk-scorer:pipeline scoring agent. Delegates to the agent via the Agent tool and returns the agent's structured RISK_SCORES output. Internal-use plumbing used by `/wr-risk-scorer:assess-release` and any other consumer SKILL that needs Skill-tool-shaped invocation of the pipeline scorer per ADR-015's Confirmation literal phrasing. End users should invoke `/wr-risk-scorer:assess-release` instead.
|
|
@@ -8,7 +12,7 @@ allowed-tools: Read, Glob, Bash, Agent
|
|
|
8
12
|
|
|
9
13
|
This SKILL is an **invokable wrapper** around the `wr-risk-scorer:pipeline` agent. It exists so consumer SKILLs can invoke the pipeline scorer via the **Skill tool** with `skill: wr-risk-scorer:pipeline` — matching ADR-015's Confirmation literal phrasing.
|
|
10
14
|
|
|
11
|
-
**End users**: invoke `/wr-risk-scorer:assess-release` instead. This wrapper is internal-use plumbing — calling it directly returns raw scoring output without the gate-satisfaction wrap-up,
|
|
15
|
+
**End users**: invoke `/wr-risk-scorer:assess-release` instead. This wrapper is internal-use plumbing — calling it directly returns raw scoring output without the gate-satisfaction wrap-up, request_user_input above-appetite handling, or release-context resolution that `/wr-risk-scorer:assess-release` provides.
|
|
12
16
|
|
|
13
17
|
## Contract
|
|
14
18
|
|