claude-raid 0.1.7 → 0.2.1
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/bin/cli.js +13 -1
- package/package.json +1 -1
- package/src/descriptions.js +26 -24
- package/src/init.js +6 -10
- package/src/merge-settings.js +0 -15
- package/src/remove.js +18 -16
- package/src/ui.js +1 -1
- package/src/update.js +28 -13
- package/template/.claude/agents/archer.md +10 -20
- package/template/.claude/agents/rogue.md +11 -21
- package/template/.claude/agents/warrior.md +8 -19
- package/template/.claude/agents/wizard.md +14 -247
- package/template/.claude/dungeon-master-rules.md +210 -0
- package/template/.claude/hooks/raid-lib.sh +29 -2
- package/template/.claude/hooks/raid-pre-compact.sh +12 -1
- package/template/.claude/hooks/raid-session-end.sh +23 -13
- package/template/.claude/hooks/raid-session-start.sh +21 -3
- package/template/.claude/hooks/validate-commit.sh +7 -74
- package/template/.claude/hooks/validate-dungeon.sh +30 -11
- package/template/.claude/hooks/validate-no-placeholders.sh +3 -3
- package/template/.claude/hooks/validate-write-gate.sh +45 -63
- package/template/.claude/{raid-rules.md → party-rules.md} +38 -13
- package/template/.claude/skills/raid-browser-chrome/SKILL.md +1 -1
- package/template/.claude/skills/{raid-design → raid-canonical-design}/SKILL.md +52 -16
- package/template/.claude/skills/{raid-implementation → raid-canonical-implementation}/SKILL.md +41 -14
- package/template/.claude/skills/{raid-implementation-plan → raid-canonical-implementation-plan}/SKILL.md +49 -17
- package/template/.claude/skills/raid-canonical-prd/SKILL.md +133 -0
- package/template/.claude/skills/raid-canonical-protocol/SKILL.md +211 -0
- package/template/.claude/skills/{raid-review → raid-canonical-review}/SKILL.md +78 -17
- package/template/.claude/skills/raid-debugging/SKILL.md +30 -5
- package/template/.claude/skills/raid-init/SKILL.md +130 -0
- package/template/.claude/skills/raid-tdd/SKILL.md +1 -1
- package/template/.claude/skills/raid-wrap-up/SKILL.md +184 -0
- package/template/.claude/hooks/raid-stop.sh +0 -20
- package/template/.claude/hooks/raid-task-completed.sh +0 -42
- package/template/.claude/hooks/validate-bash-writes.sh +0 -157
- package/template/.claude/skills/raid-browser-playwright/SKILL.md +0 -163
- package/template/.claude/skills/raid-finishing/SKILL.md +0 -140
- package/template/.claude/skills/raid-git-worktrees/SKILL.md +0 -96
- package/template/.claude/skills/raid-protocol/SKILL.md +0 -337
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# Raid lifecycle hook: SessionEnd
|
|
3
|
-
#
|
|
3
|
+
# Archives quest dungeon to Vault and cleans up session artifacts.
|
|
4
4
|
set -euo pipefail
|
|
5
5
|
|
|
6
6
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
@@ -15,9 +15,12 @@ if [ "$RAID_LIFECYCLE_SESSION" != "true" ]; then
|
|
|
15
15
|
exit 0
|
|
16
16
|
fi
|
|
17
17
|
|
|
18
|
+
# Determine quest directory
|
|
19
|
+
QUEST_DIR=$(raid_quest_dir)
|
|
20
|
+
|
|
18
21
|
# Create Vault draft directory
|
|
19
22
|
DRAFT_DIR="$RAID_VAULT_PATH/.draft"
|
|
20
|
-
mkdir -p "$DRAFT_DIR
|
|
23
|
+
mkdir -p "$DRAFT_DIR"
|
|
21
24
|
|
|
22
25
|
# --- Generate quest.md ---
|
|
23
26
|
QUEST_FILE="$DRAFT_DIR/quest.md"
|
|
@@ -29,6 +32,7 @@ cat > "$QUEST_FILE" <<EOF
|
|
|
29
32
|
|
|
30
33
|
**Date:** $CURRENT_DATE
|
|
31
34
|
**Mode:** $RAID_MODE
|
|
35
|
+
**Quest Type:** $RAID_QUEST_TYPE
|
|
32
36
|
**Branch:** $BRANCH
|
|
33
37
|
|
|
34
38
|
## Quest Summary
|
|
@@ -39,10 +43,13 @@ cat > "$QUEST_FILE" <<EOF
|
|
|
39
43
|
|
|
40
44
|
EOF
|
|
41
45
|
|
|
42
|
-
# Extract pinned findings from
|
|
43
|
-
if [ -
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
# Extract pinned findings from quest dungeon directory
|
|
47
|
+
if [ -d "$QUEST_DIR" ]; then
|
|
48
|
+
for phase_file in "$QUEST_DIR"/phase-*.md; do
|
|
49
|
+
[ -f "$phase_file" ] || continue
|
|
50
|
+
{ grep -E 'DUNGEON:|FINDING:|DECISION:|BLACKCARD:' "$phase_file" 2>/dev/null || true; } | while IFS= read -r line; do
|
|
51
|
+
echo "- $line" >> "$QUEST_FILE"
|
|
52
|
+
done
|
|
46
53
|
done
|
|
47
54
|
fi
|
|
48
55
|
|
|
@@ -67,6 +74,7 @@ cat >> "$QUEST_FILE" <<'EOF'
|
|
|
67
74
|
"quest": "",
|
|
68
75
|
"date": "",
|
|
69
76
|
"mode": "",
|
|
77
|
+
"questType": "",
|
|
70
78
|
"tags": [],
|
|
71
79
|
"patterns": [],
|
|
72
80
|
"filesChanged": []
|
|
@@ -74,6 +82,11 @@ cat >> "$QUEST_FILE" <<'EOF'
|
|
|
74
82
|
```
|
|
75
83
|
EOF
|
|
76
84
|
|
|
85
|
+
# --- Copy quest dungeon to vault draft ---
|
|
86
|
+
if [ -d "$QUEST_DIR" ]; then
|
|
87
|
+
cp -r "$QUEST_DIR" "$DRAFT_DIR/dungeon/"
|
|
88
|
+
fi
|
|
89
|
+
|
|
77
90
|
# --- Copy specs and plans ---
|
|
78
91
|
if [ -d "$RAID_SPECS_PATH" ]; then
|
|
79
92
|
SPEC_FILE=$({ ls -t "$RAID_SPECS_PATH"/*.md 2>/dev/null || true; } | head -1)
|
|
@@ -89,19 +102,16 @@ if [ -d "$RAID_PLANS_PATH" ]; then
|
|
|
89
102
|
fi
|
|
90
103
|
fi
|
|
91
104
|
|
|
92
|
-
# --- Copy Dungeon phase archives ---
|
|
93
|
-
for phase_file in .claude/raid-dungeon-phase-*.md; do
|
|
94
|
-
[ -f "$phase_file" ] || continue
|
|
95
|
-
cp "$phase_file" "$DRAFT_DIR/dungeon-phases/"
|
|
96
|
-
done
|
|
97
|
-
|
|
98
105
|
# --- Cleanup session artifacts ---
|
|
99
106
|
rm -f .claude/raid-session
|
|
107
|
+
rm -rf "$QUEST_DIR"
|
|
108
|
+
rm -f .claude/raid-last-test-run
|
|
109
|
+
|
|
110
|
+
# Backward compat: clean up old flat dungeon files if they exist
|
|
100
111
|
rm -f .claude/raid-dungeon.md
|
|
101
112
|
rm -f .claude/raid-dungeon-phase-*.md
|
|
102
113
|
rm -f .claude/raid-dungeon-backup.md
|
|
103
114
|
rm -f .claude/raid-dungeon-phase-*-backup.md
|
|
104
|
-
rm -f .claude/raid-last-test-run
|
|
105
115
|
|
|
106
116
|
# --- Output additionalContext ---
|
|
107
117
|
cat <<ENDJSON
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# Raid lifecycle hook: SessionStart
|
|
3
|
-
# Creates raid-session file and offers Vault access.
|
|
3
|
+
# Creates raid-session file, quest directory, and offers Vault access.
|
|
4
4
|
set -euo pipefail
|
|
5
5
|
|
|
6
6
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
@@ -29,11 +29,29 @@ if [ "$SOURCE" = "resume" ] && [ -f ".claude/raid-session" ]; then
|
|
|
29
29
|
exit 0
|
|
30
30
|
fi
|
|
31
31
|
|
|
32
|
-
#
|
|
32
|
+
# Generate quest ID from date
|
|
33
|
+
QUEST_ID="$(date +%Y%m%d)-quest"
|
|
34
|
+
|
|
35
|
+
# Create raid-session file with quest fields
|
|
33
36
|
mkdir -p .claude
|
|
34
37
|
STARTED_AT="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
38
|
+
QUEST_DIR=".claude/dungeon/$QUEST_ID"
|
|
35
39
|
jq -n --arg sid "$SESSION_ID" --arg ts "$STARTED_AT" --arg mode "$MODE" \
|
|
36
|
-
|
|
40
|
+
--arg qid "$QUEST_ID" --arg qdir "$QUEST_DIR" \
|
|
41
|
+
'{
|
|
42
|
+
sessionId: $sid,
|
|
43
|
+
startedAt: $ts,
|
|
44
|
+
phase: "",
|
|
45
|
+
mode: $mode,
|
|
46
|
+
questType: "",
|
|
47
|
+
questId: $qid,
|
|
48
|
+
questDir: $qdir,
|
|
49
|
+
blackCards: [],
|
|
50
|
+
phaseIteration: 1
|
|
51
|
+
}' > .claude/raid-session
|
|
52
|
+
|
|
53
|
+
# Create quest directory
|
|
54
|
+
mkdir -p "$QUEST_DIR"
|
|
37
55
|
|
|
38
56
|
# Offer Vault context if entries exist
|
|
39
57
|
if [ "$RAID_VAULT_ENABLED" = "true" ]; then
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# Raid quality gate:
|
|
2
|
+
# Raid quality gate: commit message format validation
|
|
3
3
|
# PreToolUse hook for Bash commands containing 'git commit'
|
|
4
|
-
#
|
|
5
|
-
#
|
|
4
|
+
# Validates conventional commit format and message length.
|
|
5
|
+
# Test execution gating is handled by the skill layer (raid-verification).
|
|
6
6
|
set -euo pipefail
|
|
7
7
|
|
|
8
8
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
@@ -26,32 +26,29 @@ if echo "$RAID_COMMAND" | grep -qE -- '-m '; then
|
|
|
26
26
|
fi
|
|
27
27
|
fi
|
|
28
28
|
|
|
29
|
-
# Try heredoc pattern
|
|
29
|
+
# Try heredoc pattern
|
|
30
30
|
if [ -z "$MSG" ]; then
|
|
31
31
|
_heredoc_delim=$(echo "$RAID_COMMAND" | grep -oE "<<-?'?\"?([A-Za-z_]+)'?\"?" | head -1 | sed "s/<<-\?['\"]*//" | sed "s/['\"]//g" || true)
|
|
32
32
|
if [ -n "$_heredoc_delim" ]; then
|
|
33
|
-
# Extract lines between the heredoc open and the closing delimiter
|
|
34
33
|
MSG=$(echo "$RAID_COMMAND" | sed -n "/<<.*${_heredoc_delim}/,/^[[:space:]]*${_heredoc_delim}/{ /<<.*${_heredoc_delim}/d; /^[[:space:]]*${_heredoc_delim}/d; p; }" | head -1 | sed 's/^[[:space:]]*//' || true)
|
|
35
34
|
fi
|
|
36
35
|
fi
|
|
37
36
|
|
|
38
|
-
# If no message found
|
|
37
|
+
# If no message found, warn but allow
|
|
39
38
|
if [ -z "$MSG" ]; then
|
|
40
|
-
# Check if this looks like a commit with a message we couldn't parse
|
|
41
39
|
if echo "$RAID_COMMAND" | grep -qE -- '-m |<<'; then
|
|
42
40
|
raid_warn "COMMIT: Could not extract commit message for validation."
|
|
43
41
|
fi
|
|
44
42
|
exit 0
|
|
45
43
|
fi
|
|
46
44
|
|
|
47
|
-
# Use first line only
|
|
45
|
+
# Use first line only
|
|
48
46
|
MSG=$(echo "$MSG" | head -1)
|
|
49
47
|
|
|
50
48
|
# ============================================================
|
|
51
|
-
#
|
|
49
|
+
# Conventional commit format
|
|
52
50
|
# ============================================================
|
|
53
51
|
|
|
54
|
-
# Conventional commit format
|
|
55
52
|
if ! echo "$MSG" | grep -qE '^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?: .+'; then
|
|
56
53
|
raid_block "COMMIT: Message must follow conventional commit format (type(scope): description). Got: '$MSG'"
|
|
57
54
|
fi
|
|
@@ -71,68 +68,4 @@ case "$LOWER_MSG" in
|
|
|
71
68
|
;;
|
|
72
69
|
esac
|
|
73
70
|
|
|
74
|
-
# ============================================================
|
|
75
|
-
# Check 2: Tests pass (Raid-session only)
|
|
76
|
-
# ============================================================
|
|
77
|
-
|
|
78
|
-
if [ "$RAID_ACTIVE" = "true" ] && [ -n "$RAID_TEST_CMD" ]; then
|
|
79
|
-
# TRUST: RAID_TEST_CMD comes from project-local raid.json — user-controlled, not untrusted input
|
|
80
|
-
set +e
|
|
81
|
-
(eval "$RAID_TEST_CMD") > /dev/null 2>&1
|
|
82
|
-
_test_rc=$?
|
|
83
|
-
set -e
|
|
84
|
-
if [ "$_test_rc" -ne 0 ]; then
|
|
85
|
-
raid_block "TESTS: Tests failed. Fix before committing. Command: $RAID_TEST_CMD"
|
|
86
|
-
fi
|
|
87
|
-
# Run browser tests if enabled and Playwright is installed
|
|
88
|
-
if [ "$RAID_BROWSER_ENABLED" = "true" ] && [ -n "$RAID_BROWSER_PW_CONFIG" ] && [ -f "$RAID_BROWSER_PW_CONFIG" ]; then
|
|
89
|
-
set +e
|
|
90
|
-
($RAID_BROWSER_EXEC_CMD playwright test --reporter=list) > /dev/null 2>&1
|
|
91
|
-
_pw_rc=$?
|
|
92
|
-
set -e
|
|
93
|
-
if [ "$_pw_rc" -ne 0 ]; then
|
|
94
|
-
raid_block "BROWSER TESTS: Playwright tests failed. Fix before committing. Command: $RAID_BROWSER_EXEC_CMD playwright test"
|
|
95
|
-
fi
|
|
96
|
-
fi
|
|
97
|
-
|
|
98
|
-
# Write timestamp atomically (only when ALL tests pass — unit AND browser)
|
|
99
|
-
mkdir -p .claude
|
|
100
|
-
date +%s > .claude/raid-last-test-run.tmp && mv .claude/raid-last-test-run.tmp .claude/raid-last-test-run
|
|
101
|
-
fi
|
|
102
|
-
|
|
103
|
-
# ============================================================
|
|
104
|
-
# Check 3: Verification (Raid-session only, completion commits)
|
|
105
|
-
# ============================================================
|
|
106
|
-
|
|
107
|
-
if [ "$RAID_ACTIVE" = "true" ]; then
|
|
108
|
-
HAS_COMPLETION=false
|
|
109
|
-
for WORD in "complete" "done" "finish" "final"; do
|
|
110
|
-
if echo "$LOWER_MSG" | grep -qiw "$WORD"; then
|
|
111
|
-
HAS_COMPLETION=true
|
|
112
|
-
break
|
|
113
|
-
fi
|
|
114
|
-
done
|
|
115
|
-
|
|
116
|
-
if [ "$HAS_COMPLETION" = "true" ]; then
|
|
117
|
-
TIMESTAMP_FILE=".claude/raid-last-test-run"
|
|
118
|
-
MAX_AGE=$(( ${RAID_LIFECYCLE_TEST_WINDOW:-10} * 60 ))
|
|
119
|
-
|
|
120
|
-
if [ ! -f "$TIMESTAMP_FILE" ]; then
|
|
121
|
-
raid_block "VERIFICATION: Commit claims completion but no test run evidence found. Run tests before claiming work is complete."
|
|
122
|
-
fi
|
|
123
|
-
|
|
124
|
-
LAST_RUN=$(cat "$TIMESTAMP_FILE" | tr -d '[:space:]')
|
|
125
|
-
NOW=$(date +%s)
|
|
126
|
-
# Guard against corrupted/non-numeric timestamp
|
|
127
|
-
case "$LAST_RUN" in
|
|
128
|
-
''|*[!0-9]*) raid_block "VERIFICATION: Test run timestamp is corrupted. Run tests again before claiming completion." ;;
|
|
129
|
-
esac
|
|
130
|
-
AGE=$((NOW - LAST_RUN))
|
|
131
|
-
|
|
132
|
-
if [ "$AGE" -gt "$MAX_AGE" ]; then
|
|
133
|
-
raid_block "VERIFICATION: Last test run was $((AGE / 60)) minutes ago. Run tests again before claiming completion."
|
|
134
|
-
fi
|
|
135
|
-
fi
|
|
136
|
-
fi
|
|
137
|
-
|
|
138
71
|
exit 0
|
|
@@ -13,9 +13,15 @@ if [ -z "${RAID_FILE_PATH:-}" ]; then
|
|
|
13
13
|
exit 0
|
|
14
14
|
fi
|
|
15
15
|
|
|
16
|
-
#
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
# Normalize to relative path
|
|
17
|
+
_file="${RAID_FILE_PATH}"
|
|
18
|
+
if [[ "$_file" == /* ]]; then
|
|
19
|
+
_file="${_file#"$PWD"/}"
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
# Only check Dungeon files (quest directory structure + backward compat flat files)
|
|
23
|
+
case "$_file" in
|
|
24
|
+
.claude/dungeon/*/phase-*.md) ;;
|
|
19
25
|
.claude/raid-dungeon.md|.claude/raid-dungeon-phase-*.md) ;;
|
|
20
26
|
*) exit 0 ;;
|
|
21
27
|
esac
|
|
@@ -67,6 +73,11 @@ while IFS= read -r line; do
|
|
|
67
73
|
entry_type="DUNGEON"
|
|
68
74
|
content_after_prefix="${line#*DUNGEON:}"
|
|
69
75
|
;;
|
|
76
|
+
"BLACKCARD:"*|"🃏 BLACKCARD:"*)
|
|
77
|
+
has_prefix=true
|
|
78
|
+
entry_type="BLACKCARD"
|
|
79
|
+
content_after_prefix="${line#*BLACKCARD:}"
|
|
80
|
+
;;
|
|
70
81
|
"UNRESOLVED:"*|"⚠️ UNRESOLVED:"*)
|
|
71
82
|
has_prefix=true
|
|
72
83
|
entry_type="UNRESOLVED"
|
|
@@ -87,9 +98,8 @@ while IFS= read -r line; do
|
|
|
87
98
|
continue
|
|
88
99
|
fi
|
|
89
100
|
|
|
90
|
-
# Layer 2: Evidence check —
|
|
101
|
+
# Layer 2: Evidence check — for pinned entries and black cards
|
|
91
102
|
if [ "$entry_type" = "DUNGEON" ]; then
|
|
92
|
-
# Strip leading whitespace from content after prefix
|
|
93
103
|
content_after_prefix="$(echo "$content_after_prefix" | sed 's/^[[:space:]]*//')"
|
|
94
104
|
content_len=${#content_after_prefix}
|
|
95
105
|
if [ "$content_len" -lt 50 ]; then
|
|
@@ -97,22 +107,31 @@ while IFS= read -r line; do
|
|
|
97
107
|
- Pinned entry too short. Include evidence."
|
|
98
108
|
fi
|
|
99
109
|
|
|
100
|
-
# Check that pinned entries reference at least two agents (
|
|
110
|
+
# Check that pinned entries reference at least two agents (word boundaries)
|
|
101
111
|
agent_count=0
|
|
102
|
-
echo "$content_after_prefix" | grep -
|
|
103
|
-
echo "$content_after_prefix" | grep -
|
|
104
|
-
echo "$content_after_prefix" | grep -
|
|
105
|
-
echo "$content_after_prefix" | grep -
|
|
112
|
+
echo "$content_after_prefix" | grep -qiw "warrior" && agent_count=$((agent_count + 1))
|
|
113
|
+
echo "$content_after_prefix" | grep -qiw "archer" && agent_count=$((agent_count + 1))
|
|
114
|
+
echo "$content_after_prefix" | grep -qiw "rogue" && agent_count=$((agent_count + 1))
|
|
115
|
+
echo "$content_after_prefix" | grep -qiw "wizard" && agent_count=$((agent_count + 1))
|
|
106
116
|
if [ "$agent_count" -lt 2 ]; then
|
|
107
117
|
issues="${issues}
|
|
108
118
|
- Pinned entry must reference at least 2 agents who verified it (e.g., 'verified by @Warrior and @Archer')."
|
|
109
119
|
fi
|
|
110
120
|
fi
|
|
111
121
|
|
|
122
|
+
if [ "$entry_type" = "BLACKCARD" ]; then
|
|
123
|
+
content_after_prefix="$(echo "$content_after_prefix" | sed 's/^[[:space:]]*//')"
|
|
124
|
+
content_len=${#content_after_prefix}
|
|
125
|
+
if [ "$content_len" -lt 80 ]; then
|
|
126
|
+
issues="${issues}
|
|
127
|
+
- Black card entry too short (${content_len} chars, minimum 80). Describe the breaking concern with evidence."
|
|
128
|
+
fi
|
|
129
|
+
fi
|
|
130
|
+
|
|
112
131
|
# Layer 3: Phase consistency
|
|
113
132
|
if [ "$entry_type" = "TASK" ]; then
|
|
114
133
|
case "${RAID_PHASE:-}" in
|
|
115
|
-
design|implementation|review)
|
|
134
|
+
design|implementation|review|prd|wrap-up)
|
|
116
135
|
issues="${issues}
|
|
117
136
|
- TASK entries belong in Plan phase, not ${RAID_PHASE}."
|
|
118
137
|
;;
|
|
@@ -16,7 +16,7 @@ fi
|
|
|
16
16
|
# Only check files in specs or plans directories
|
|
17
17
|
IS_RAID_DOC=false
|
|
18
18
|
case "$RAID_FILE_PATH" in
|
|
19
|
-
"$RAID_SPECS_PATH"/*|"$RAID_PLANS_PATH"
|
|
19
|
+
"$RAID_SPECS_PATH"/*|"$RAID_PLANS_PATH"/*|.claude/dungeon/*/phase-*.md) IS_RAID_DOC=true ;;
|
|
20
20
|
esac
|
|
21
21
|
|
|
22
22
|
if [ "$IS_RAID_DOC" = false ]; then
|
|
@@ -41,8 +41,8 @@ while IFS= read -r line; do
|
|
|
41
41
|
LINE_NUM=$((LINE_NUM + 1))
|
|
42
42
|
LOWER_LINE=$(echo "$line" | tr '[:upper:]' '[:lower:]')
|
|
43
43
|
|
|
44
|
-
for PATTERN in
|
|
45
|
-
if echo "$LOWER_LINE" | grep -
|
|
44
|
+
for PATTERN in '\btbd\b' '\btodo\b' '\bfixme\b' 'implement later' 'add appropriate' 'similar to task' 'handle edge cases' 'fill in'; do
|
|
45
|
+
if echo "$LOWER_LINE" | grep -qiE "$PATTERN"; then
|
|
46
46
|
ISSUES="${ISSUES}Line ${LINE_NUM}: Found '${PATTERN}' — ${line}\n"
|
|
47
47
|
break
|
|
48
48
|
fi
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# Raid write gate:
|
|
3
|
-
#
|
|
2
|
+
# Raid write gate: protects enforcement-critical files from direct agent writes.
|
|
3
|
+
# Phase-aware code enforcement is handled by the skill layer.
|
|
4
|
+
# PreToolUse hook — blocks writes to protected files only.
|
|
4
5
|
set -euo pipefail
|
|
5
6
|
|
|
6
7
|
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
@@ -18,72 +19,53 @@ if [ "$RAID_ACTIVE" = "false" ]; then
|
|
|
18
19
|
exit 0
|
|
19
20
|
fi
|
|
20
21
|
|
|
21
|
-
#
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
# Normalize: resolve .., //, symlinks on PWD, then strip prefix (prevents traversal bypasses)
|
|
26
|
-
if [[ "$_protected_file" != /* ]]; then
|
|
27
|
-
_protected_file="$PWD/$_protected_file"
|
|
28
|
-
fi
|
|
29
|
-
_protected_file=$(echo "$_protected_file" | sed 's|//\{1,\}|/|g' | while read -r _p; do
|
|
30
|
-
while echo "$_p" | grep -q '/[^/][^/]*/\.\./'; do
|
|
31
|
-
_p=$(echo "$_p" | sed 's|/[^/][^/]*/\.\./|/|')
|
|
32
|
-
done
|
|
33
|
-
echo "$_p"
|
|
34
|
-
done)
|
|
35
|
-
# Strip PWD prefix — try both logical and physical PWD (macOS: /var → /private/var)
|
|
36
|
-
_physical_pwd=$(cd "$PWD" && pwd -P)
|
|
37
|
-
_protected_file="${_protected_file#"$PWD"/}"
|
|
38
|
-
_protected_file="${_protected_file#"$_physical_pwd"/}"
|
|
39
|
-
# Also resolve /private prefix mismatch: input may use /var but shell resolves to /private/var
|
|
40
|
-
if [[ "$_protected_file" == /* ]] && [[ -n "$_physical_pwd" ]]; then
|
|
41
|
-
_logical_pwd="${_physical_pwd#/private}"
|
|
42
|
-
_protected_file="${_protected_file#"$_logical_pwd"/}"
|
|
22
|
+
# Normalize absolute paths to relative
|
|
23
|
+
_file="${RAID_FILE_PATH}"
|
|
24
|
+
if [[ "$_file" == /* ]]; then
|
|
25
|
+
_file="${_file#"$PWD"/}"
|
|
43
26
|
fi
|
|
44
|
-
|
|
27
|
+
|
|
28
|
+
# Protect enforcement-critical files from direct agent writes.
|
|
29
|
+
# Hooks and Wizard use Bash-level operations (jq redirect, rm) for these files.
|
|
30
|
+
case "$_file" in
|
|
45
31
|
.claude/raid-session|.claude/raid-last-test-run)
|
|
46
|
-
raid_block "File '${
|
|
32
|
+
raid_block "File '${_file}' is protected. It is managed by hooks and the Wizard."
|
|
47
33
|
;;
|
|
48
34
|
esac
|
|
49
35
|
|
|
50
|
-
#
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
fi
|
|
54
|
-
|
|
55
|
-
# --- Phase-based enforcement on production files ---
|
|
56
|
-
|
|
57
|
-
case "${RAID_PHASE:-}" in
|
|
58
|
-
design)
|
|
59
|
-
raid_block "Read-only phase (design). No implementation code allowed."
|
|
60
|
-
;;
|
|
61
|
-
plan)
|
|
62
|
-
raid_block "Read-only phase (plan). No implementation code allowed."
|
|
63
|
-
;;
|
|
64
|
-
implementation)
|
|
65
|
-
# Scout mode: skip implementer check
|
|
66
|
-
if [ "$RAID_MODE" = "scout" ]; then
|
|
67
|
-
exit 0
|
|
68
|
-
fi
|
|
69
|
-
# Only the designated implementer may write production code
|
|
70
|
-
if [ "$RAID_CURRENT_AGENT" != "$RAID_IMPLEMENTER" ]; then
|
|
71
|
-
raid_block "Only ${RAID_IMPLEMENTER} writes production code this task."
|
|
72
|
-
fi
|
|
36
|
+
# Quest dungeon dir markdown files are always allowed
|
|
37
|
+
case "$_file" in
|
|
38
|
+
.claude/dungeon/*.md)
|
|
73
39
|
exit 0
|
|
74
40
|
;;
|
|
75
|
-
review)
|
|
76
|
-
raid_block "Read-only phase (review). File fixes go through implementation."
|
|
77
|
-
;;
|
|
78
|
-
finishing)
|
|
79
|
-
raid_block "Finishing phase. No new code."
|
|
80
|
-
;;
|
|
81
|
-
"")
|
|
82
|
-
# Empty phase during session bootstrap — allow with warning
|
|
83
|
-
raid_warn "Session active but phase is empty — allowing writes during bootstrap."
|
|
84
|
-
;;
|
|
85
|
-
*)
|
|
86
|
-
# Unknown phase — fail closed
|
|
87
|
-
raid_block "Unknown phase '${RAID_PHASE}'. Cannot determine write permissions."
|
|
88
|
-
;;
|
|
89
41
|
esac
|
|
42
|
+
|
|
43
|
+
# Phase-based enforcement on production files
|
|
44
|
+
# Only block production code in non-implementation phases
|
|
45
|
+
if raid_is_production_file "$RAID_FILE_PATH"; then
|
|
46
|
+
case "${RAID_PHASE:-}" in
|
|
47
|
+
prd)
|
|
48
|
+
raid_block "PRD phase. No implementation code allowed."
|
|
49
|
+
;;
|
|
50
|
+
design)
|
|
51
|
+
raid_block "Design phase. No implementation code allowed."
|
|
52
|
+
;;
|
|
53
|
+
plan)
|
|
54
|
+
raid_block "Plan phase. No implementation code allowed."
|
|
55
|
+
;;
|
|
56
|
+
wrap-up)
|
|
57
|
+
raid_block "Wrap-up phase. No new code."
|
|
58
|
+
;;
|
|
59
|
+
implementation|review)
|
|
60
|
+
# Allow — skill layer handles implementer/fixing enforcement
|
|
61
|
+
exit 0
|
|
62
|
+
;;
|
|
63
|
+
"")
|
|
64
|
+
# Empty phase during session bootstrap — allow
|
|
65
|
+
exit 0
|
|
66
|
+
;;
|
|
67
|
+
*)
|
|
68
|
+
raid_block "Unknown phase '${RAID_PHASE}'. Cannot determine write permissions."
|
|
69
|
+
;;
|
|
70
|
+
esac
|
|
71
|
+
fi
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Party Rules
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Seven pillars. Non-negotiable. Every agent, every phase, every interaction.
|
|
4
4
|
|
|
5
5
|
## Pillar 1: Intellectual Honesty
|
|
6
6
|
|
|
@@ -24,11 +24,39 @@ Three pillars. Non-negotiable. Every agent, every phase, every interaction.
|
|
|
24
24
|
- Maximum effort on every task. No coasting, no rubber-stamping, no going through motions.
|
|
25
25
|
- Every interaction carries work forward. If you're not adding new information or evidence, stop talking.
|
|
26
26
|
- The Dungeon is a scoreboard, not a chat log. Pin only what survived challenge from at least two agents.
|
|
27
|
-
- Agents talk directly to each other. The Wizard is not a relay.
|
|
28
27
|
- Escalate to the Wizard only after you've tried to resolve it by reading code and discussing with teammates.
|
|
29
28
|
- All agents participate actively at every step. Silence when you have nothing to add is fine — silence when you haven't investigated is laziness.
|
|
30
29
|
- This team uses agent teams only. Never delegate to subagents.
|
|
31
30
|
|
|
31
|
+
## Pillar 4: Round-Based Interaction
|
|
32
|
+
|
|
33
|
+
- **Turn-based, not real-time.** When assigned a task, work independently. No mid-thinking interruptions to other agents.
|
|
34
|
+
- **Flag completion.** When done, signal `ROUND_COMPLETE:` to the Wizard. Wait for dispatch.
|
|
35
|
+
- **Cross-test after your own work.** Pick up teammates' work for review only when the Wizard dispatches it.
|
|
36
|
+
- **Limited interactions.** Converge in 2-3 exchanges per finding. If stuck after 3, escalate to Wizard.
|
|
37
|
+
- **Party is silent during phase transitions.** When the Wizard opens/closes a phase, agents wait.
|
|
38
|
+
- **Exception: only the Wizard can interrupt** an agent mid-work.
|
|
39
|
+
|
|
40
|
+
## Pillar 5: Question Chain
|
|
41
|
+
|
|
42
|
+
- **Agents NEVER ask the human directly.** All questions go through the Wizard.
|
|
43
|
+
- Send `WIZARD:` with the question. The Wizard answers if confident, or digests and asks the human.
|
|
44
|
+
- The Wizard always digests information before passing — agents→human or human→agents.
|
|
45
|
+
|
|
46
|
+
## Pillar 6: Phase Spoils
|
|
47
|
+
|
|
48
|
+
- Every phase MUST produce at least one detailed markdown artifact (the phase spoils).
|
|
49
|
+
- The Wizard creates and frameworks each phase file. Agents fill sections.
|
|
50
|
+
- The Wizard wraps up documents at phase close and sends a report to the human.
|
|
51
|
+
|
|
52
|
+
## Pillar 7: Black Cards
|
|
53
|
+
|
|
54
|
+
- A `BLACKCARD:` is a high-concern finding that fundamentally breaks the architecture.
|
|
55
|
+
- It cannot be fixed within the current design — it invalidates the implementation.
|
|
56
|
+
- To play a Black Card: provide full evidence (file paths, scenarios, why unfixable) and impact.
|
|
57
|
+
- Other agents must independently verify before it escalates.
|
|
58
|
+
- The Wizard presents Black Cards to the human with options: (a) rollback to an earlier phase, (b) accept the limitation.
|
|
59
|
+
|
|
32
60
|
## Teammate Operating Protocol
|
|
33
61
|
|
|
34
62
|
These rules apply to all teammates (Warrior, Archer, Rogue). The Wizard follows its own protocol.
|
|
@@ -45,14 +73,9 @@ You collaborate by being rigorous, not by being agreeable. The best thing you ca
|
|
|
45
73
|
|
|
46
74
|
Efficiency matters. Say what you found, what it means, and what should happen. No preamble. No restating what others said. No performative analysis.
|
|
47
75
|
|
|
48
|
-
###
|
|
49
|
-
|
|
50
|
-
You operate differently depending on the mode the Wizard sets:
|
|
51
|
-
- **Full Raid** — 3 agents active. Cross-verify everything.
|
|
52
|
-
- **Skirmish** — 2 agents active. The Wizard selects which two.
|
|
53
|
-
- **Scout** — 1 agent alone. Full responsibility, no backup.
|
|
76
|
+
### Full Party
|
|
54
77
|
|
|
55
|
-
|
|
78
|
+
All 4 agents always participate. The full party is Wizard + Warrior + Archer + Rogue. Maximum effort on every quest.
|
|
56
79
|
|
|
57
80
|
### When the Wizard Opens the Dungeon
|
|
58
81
|
|
|
@@ -90,6 +113,8 @@ Lead with the conclusion, follow with the evidence.
|
|
|
90
113
|
- `CONCEDE:` — you were wrong, moving on
|
|
91
114
|
- `DUNGEON:` — pinning a finding that survived challenge from at least two agents
|
|
92
115
|
- `WIZARD:` — you need project-level context or are genuinely stuck
|
|
116
|
+
- `ROUND_COMPLETE:` — finished assigned task, ready for cross-testing
|
|
117
|
+
- `BLACKCARD:` — high-concern finding that breaks the architecture
|
|
93
118
|
|
|
94
119
|
### Team Communication
|
|
95
120
|
|
|
@@ -120,14 +145,14 @@ SendMessage(to="wizard", message="User directed me to [X]. Proceeding.")
|
|
|
120
145
|
|
|
121
146
|
## The Dungeon
|
|
122
147
|
|
|
123
|
-
The Dungeon
|
|
148
|
+
The Dungeon is the quest's shared knowledge directory at `.claude/dungeon/{quest-slug}/`. Each phase produces a phase file (e.g., `phase-2-design.md`).
|
|
124
149
|
|
|
125
150
|
### Structure
|
|
126
151
|
|
|
127
152
|
```markdown
|
|
128
153
|
# Dungeon — Phase N: <Phase Name>
|
|
129
154
|
## Quest: <task description>
|
|
130
|
-
##
|
|
155
|
+
## Quest Type: <Canonical Quest>
|
|
131
156
|
|
|
132
157
|
### Discoveries
|
|
133
158
|
<!-- Verified findings that survived challenge, tagged with agent name -->
|
|
@@ -160,7 +185,7 @@ The Dungeon (`.claude/raid-dungeon.md`) is the team's shared knowledge board.
|
|
|
160
185
|
|
|
161
186
|
**The conversation is the sparring ring. The Dungeon is the scoreboard.**
|
|
162
187
|
|
|
163
|
-
Agents can read
|
|
188
|
+
Agents can read prior phase files from the quest directory. Design knowledge carries into Plan. Plan knowledge carries into Implementation.
|
|
164
189
|
|
|
165
190
|
### When to Escalate to Wizard
|
|
166
191
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: raid-browser-chrome
|
|
3
|
-
description: "Claude-in-Chrome live adversarial browser inspection. Angle-driven with minimum coverage gates. Each agent runs own isolated instance. GIF/screenshot evidence required. Invoked from raid-review during Phase
|
|
3
|
+
description: "Claude-in-Chrome live adversarial browser inspection. Angle-driven with minimum coverage gates. Each agent runs own isolated instance. GIF/screenshot evidence required. Invoked from raid-canonical-review during Phase 5."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Raid Browser Chrome — Live Adversarial Inspection
|