@lvlup-sw/exarchos 2.4.3 → 2.5.0
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/.claude-plugin/plugin.json +7 -2
- package/AGENTS.md +2 -2
- package/README.md +70 -57
- package/agents/.gitkeep +0 -0
- package/agents/fixer.md +62 -0
- package/agents/implementer.md +68 -0
- package/agents/reviewer.md +50 -0
- package/commands/ideate.md +1 -1
- package/commands/plan.md +1 -1
- package/commands/review.md +58 -0
- package/dist/exarchos.js +583 -146
- package/hooks/hooks.json +8 -0
- package/package.json +12 -4
- package/scripts/sync-versions.sh +31 -22
- package/skills/brainstorming/SKILL.md +16 -0
- package/skills/brainstorming/references/design-template.md +9 -0
- package/skills/debug/SKILL.md +41 -0
- package/skills/debug/references/hotfix-track.md +12 -49
- package/skills/debug/references/investigation-checklist.md +3 -3
- package/skills/debug/references/thorough-track.md +12 -42
- package/skills/delegation/SKILL.md +104 -37
- package/skills/delegation/references/agent-teams-saga.md +4 -1
- package/skills/delegation/references/fix-mode.md +46 -6
- package/skills/delegation/references/implementer-prompt.md +29 -1
- package/skills/delegation/references/parallel-strategy.md +1 -1
- package/skills/delegation/references/state-management.md +33 -0
- package/skills/delegation/references/workflow-steps.md +6 -10
- package/skills/delegation/references/worktree-enforcement.md +13 -7
- package/skills/git-worktrees/SKILL.md +6 -9
- package/skills/implementation-planning/SKILL.md +32 -27
- package/skills/implementation-planning/references/task-template.md +20 -0
- package/skills/implementation-planning/references/testing-strategy-guide.md +22 -1
- package/skills/implementation-planning/references/worked-example.md +2 -2
- package/skills/quality-review/SKILL.md +103 -10
- package/skills/quality-review/references/auto-transition.md +1 -1
- package/skills/quality-review/references/axiom-integration.md +135 -0
- package/skills/refactor/SKILL.md +32 -39
- package/skills/refactor/phases/polish-implement.md +2 -2
- package/skills/refactor/phases/polish-validate.md +1 -1
- package/skills/refactor/references/doc-update-checklist.md +2 -3
- package/skills/refactor/references/explore-checklist.md +4 -6
- package/skills/refactor/references/overhaul-track.md +20 -50
- package/skills/refactor/references/polish-track.md +18 -46
- package/skills/shared/prompts/context-reading.md +7 -7
- package/skills/shared/references/mcp-tool-guidance.md +14 -1
- package/skills/shared/references/tdd.md +17 -0
- package/skills/shepherd/SKILL.md +38 -10
- package/skills/shepherd/references/fix-strategies.md +1 -2
- package/skills/shepherd/references/shepherd-event-schemas.md +56 -0
- package/skills/spec-review/SKILL.md +46 -10
- package/skills/spec-review/references/worked-example.md +1 -1
- package/skills/synthesis/SKILL.md +32 -10
- package/skills/synthesis/references/github-native-stacking.md +3 -4
- package/skills/synthesis/references/synthesis-steps.md +11 -13
- package/skills/workflow-state/SKILL.md +11 -3
- package/skills/workflow-state/references/mcp-tool-reference.md +5 -5
- package/skills/workflow-state/references/phase-transitions.md +6 -3
- package/.claude-plugin/marketplace.json +0 -34
- package/scripts/assess-refactor-scope.sh +0 -239
- package/scripts/check-coderabbit.sh +0 -288
- package/scripts/check-context-economy.sh +0 -405
- package/scripts/check-coverage-thresholds.sh +0 -194
- package/scripts/check-operational-resilience.sh +0 -306
- package/scripts/check-polish-scope.sh +0 -245
- package/scripts/check-post-merge.sh +0 -185
- package/scripts/check-pr-comments.sh +0 -127
- package/scripts/check-task-decomposition.sh +0 -451
- package/scripts/check-tdd-compliance.sh +0 -265
- package/scripts/check-workflow-determinism.sh +0 -312
- package/scripts/debug-review-gate.sh +0 -201
- package/scripts/extract-fix-tasks.sh +0 -179
- package/scripts/extract-task.sh +0 -67
- package/scripts/generate-traceability.sh +0 -209
- package/scripts/investigation-timer.sh +0 -171
- package/scripts/needs-schema-sync.sh +0 -174
- package/scripts/new-project.sh +0 -103
- package/scripts/post-delegation-check.sh +0 -317
- package/scripts/pre-synthesis-check.sh +0 -475
- package/scripts/reconcile-state.sh +0 -346
- package/scripts/review-diff.sh +0 -63
- package/scripts/review-verdict.sh +0 -169
- package/scripts/security-scan.sh +0 -248
- package/scripts/select-debug-track.sh +0 -186
- package/scripts/setup-worktree.sh +0 -323
- package/scripts/spec-coverage-check.sh +0 -230
- package/scripts/static-analysis-gate.sh +0 -261
- package/scripts/validate-companion.sh +0 -161
- package/scripts/validate-pr-body.sh +0 -158
- package/scripts/validate-pr-stack.sh +0 -146
- package/scripts/verify-delegation-saga.sh +0 -240
- package/scripts/verify-doc-links.sh +0 -211
- package/scripts/verify-ideate-artifacts.sh +0 -296
- package/scripts/verify-plan-coverage.sh +0 -408
- package/scripts/verify-provenance-chain.sh +0 -310
- package/scripts/verify-review-triage.sh +0 -219
- package/scripts/verify-worktree-baseline.sh +0 -159
- package/scripts/verify-worktree.sh +0 -84
|
@@ -1,346 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# Reconcile State
|
|
3
|
-
# Compares workflow state file to git reality: verifies worktrees exist,
|
|
4
|
-
# branches exist, task statuses are consistent, and phase is valid.
|
|
5
|
-
#
|
|
6
|
-
# Usage: reconcile-state.sh --state-file <path> --repo-root <path>
|
|
7
|
-
#
|
|
8
|
-
# Exit codes:
|
|
9
|
-
# 0 = state is consistent with git
|
|
10
|
-
# 1 = discrepancies found
|
|
11
|
-
# 2 = usage error (missing required args)
|
|
12
|
-
|
|
13
|
-
set -euo pipefail
|
|
14
|
-
|
|
15
|
-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
16
|
-
|
|
17
|
-
# Colors
|
|
18
|
-
RED='\033[0;31m'
|
|
19
|
-
GREEN='\033[0;32m'
|
|
20
|
-
YELLOW='\033[1;33m'
|
|
21
|
-
NC='\033[0m'
|
|
22
|
-
|
|
23
|
-
# ============================================================
|
|
24
|
-
# ARGUMENT PARSING
|
|
25
|
-
# ============================================================
|
|
26
|
-
|
|
27
|
-
STATE_FILE=""
|
|
28
|
-
REPO_ROOT=""
|
|
29
|
-
|
|
30
|
-
usage() {
|
|
31
|
-
cat << 'USAGE'
|
|
32
|
-
Usage: reconcile-state.sh --state-file <path> --repo-root <path>
|
|
33
|
-
|
|
34
|
-
Required:
|
|
35
|
-
--state-file <path> Path to the workflow state JSON file
|
|
36
|
-
--repo-root <path> Git repository root directory
|
|
37
|
-
|
|
38
|
-
Optional:
|
|
39
|
-
--help Show this help message
|
|
40
|
-
|
|
41
|
-
Exit codes:
|
|
42
|
-
0 State is consistent with git
|
|
43
|
-
1 Discrepancies found
|
|
44
|
-
2 Usage error (missing required args)
|
|
45
|
-
USAGE
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
while [[ $# -gt 0 ]]; do
|
|
49
|
-
case "$1" in
|
|
50
|
-
--state-file)
|
|
51
|
-
if [[ -z "${2:-}" ]]; then
|
|
52
|
-
echo "Error: --state-file requires a path argument" >&2
|
|
53
|
-
exit 2
|
|
54
|
-
fi
|
|
55
|
-
STATE_FILE="$2"
|
|
56
|
-
shift 2
|
|
57
|
-
;;
|
|
58
|
-
--repo-root)
|
|
59
|
-
if [[ -z "${2:-}" ]]; then
|
|
60
|
-
echo "Error: --repo-root requires a path argument" >&2
|
|
61
|
-
exit 2
|
|
62
|
-
fi
|
|
63
|
-
REPO_ROOT="$2"
|
|
64
|
-
shift 2
|
|
65
|
-
;;
|
|
66
|
-
--help)
|
|
67
|
-
usage
|
|
68
|
-
exit 0
|
|
69
|
-
;;
|
|
70
|
-
*)
|
|
71
|
-
echo "Error: Unknown argument '$1'" >&2
|
|
72
|
-
usage >&2
|
|
73
|
-
exit 2
|
|
74
|
-
;;
|
|
75
|
-
esac
|
|
76
|
-
done
|
|
77
|
-
|
|
78
|
-
if [[ -z "$STATE_FILE" || -z "$REPO_ROOT" ]]; then
|
|
79
|
-
echo "Error: --state-file and --repo-root are required" >&2
|
|
80
|
-
usage >&2
|
|
81
|
-
exit 2
|
|
82
|
-
fi
|
|
83
|
-
|
|
84
|
-
# ============================================================
|
|
85
|
-
# DEPENDENCY CHECK
|
|
86
|
-
# ============================================================
|
|
87
|
-
|
|
88
|
-
if ! command -v jq &>/dev/null; then
|
|
89
|
-
echo "Error: jq is required but not installed" >&2
|
|
90
|
-
exit 2
|
|
91
|
-
fi
|
|
92
|
-
|
|
93
|
-
if ! command -v git &>/dev/null; then
|
|
94
|
-
echo "Error: git is required but not installed" >&2
|
|
95
|
-
exit 2
|
|
96
|
-
fi
|
|
97
|
-
|
|
98
|
-
# ============================================================
|
|
99
|
-
# CHECK FUNCTIONS
|
|
100
|
-
# ============================================================
|
|
101
|
-
|
|
102
|
-
CHECK_PASS=0
|
|
103
|
-
CHECK_FAIL=0
|
|
104
|
-
RESULTS=()
|
|
105
|
-
|
|
106
|
-
check_pass() {
|
|
107
|
-
local name="$1"
|
|
108
|
-
RESULTS+=("- **PASS**: $name")
|
|
109
|
-
CHECK_PASS=$((CHECK_PASS + 1))
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
check_fail() {
|
|
113
|
-
local name="$1"
|
|
114
|
-
local detail="${2:-}"
|
|
115
|
-
if [[ -n "$detail" ]]; then
|
|
116
|
-
RESULTS+=("- **FAIL**: $name — $detail")
|
|
117
|
-
else
|
|
118
|
-
RESULTS+=("- **FAIL**: $name")
|
|
119
|
-
fi
|
|
120
|
-
CHECK_FAIL=$((CHECK_FAIL + 1))
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
# ============================================================
|
|
124
|
-
# CHECK 1: State file exists and is valid JSON
|
|
125
|
-
# ============================================================
|
|
126
|
-
|
|
127
|
-
check_state_file() {
|
|
128
|
-
if [[ ! -f "$STATE_FILE" ]]; then
|
|
129
|
-
check_fail "State file exists" "File not found: $STATE_FILE"
|
|
130
|
-
return 1
|
|
131
|
-
fi
|
|
132
|
-
|
|
133
|
-
if ! jq empty "$STATE_FILE" 2>/dev/null; then
|
|
134
|
-
check_fail "State file exists" "Invalid JSON: $STATE_FILE"
|
|
135
|
-
return 1
|
|
136
|
-
fi
|
|
137
|
-
|
|
138
|
-
check_pass "State file exists"
|
|
139
|
-
return 0
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
# ============================================================
|
|
143
|
-
# CHECK 2: Phase is valid for workflow type
|
|
144
|
-
# ============================================================
|
|
145
|
-
|
|
146
|
-
check_phase_valid() {
|
|
147
|
-
local workflow_type
|
|
148
|
-
local phase
|
|
149
|
-
|
|
150
|
-
workflow_type="$(jq -r '.workflowType // "feature"' "$STATE_FILE")"
|
|
151
|
-
phase="$(jq -r '.phase // "unknown"' "$STATE_FILE")"
|
|
152
|
-
|
|
153
|
-
# Define valid phases per workflow type
|
|
154
|
-
local -a valid_phases
|
|
155
|
-
case "$workflow_type" in
|
|
156
|
-
feature)
|
|
157
|
-
valid_phases=(ideate plan plan-review delegate review synthesize completed cancelled blocked)
|
|
158
|
-
;;
|
|
159
|
-
debug)
|
|
160
|
-
valid_phases=(triage investigate rca design debug-implement debug-validate debug-review hotfix-implement hotfix-validate synthesize completed cancelled blocked)
|
|
161
|
-
;;
|
|
162
|
-
refactor)
|
|
163
|
-
valid_phases=(explore brief polish-implement polish-validate polish-update-docs overhaul-plan overhaul-delegate overhaul-review overhaul-update-docs synthesize completed cancelled blocked)
|
|
164
|
-
;;
|
|
165
|
-
*)
|
|
166
|
-
check_fail "Phase is valid" "Unknown workflow type: $workflow_type"
|
|
167
|
-
return 1
|
|
168
|
-
;;
|
|
169
|
-
esac
|
|
170
|
-
|
|
171
|
-
local found=false
|
|
172
|
-
for valid_phase in "${valid_phases[@]}"; do
|
|
173
|
-
if [[ "$phase" == "$valid_phase" ]]; then
|
|
174
|
-
found=true
|
|
175
|
-
break
|
|
176
|
-
fi
|
|
177
|
-
done
|
|
178
|
-
|
|
179
|
-
if [[ "$found" == true ]]; then
|
|
180
|
-
check_pass "Phase is valid ($phase for $workflow_type)"
|
|
181
|
-
return 0
|
|
182
|
-
else
|
|
183
|
-
check_fail "Phase is valid" "Phase '$phase' is not valid for workflow type '$workflow_type' (valid: ${valid_phases[*]})"
|
|
184
|
-
return 1
|
|
185
|
-
fi
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
# ============================================================
|
|
189
|
-
# CHECK 3: Task branches exist in git
|
|
190
|
-
# ============================================================
|
|
191
|
-
|
|
192
|
-
check_task_branches() {
|
|
193
|
-
local task_count
|
|
194
|
-
task_count="$(jq '.tasks | length' "$STATE_FILE")"
|
|
195
|
-
|
|
196
|
-
if [[ "$task_count" -eq 0 ]]; then
|
|
197
|
-
check_pass "Task branches exist (no tasks to check)"
|
|
198
|
-
return 0
|
|
199
|
-
fi
|
|
200
|
-
|
|
201
|
-
local missing_branches=()
|
|
202
|
-
local branches_checked=0
|
|
203
|
-
|
|
204
|
-
# Get all branches from the task array
|
|
205
|
-
local task_branches
|
|
206
|
-
task_branches="$(jq -r '.tasks[] | select(.branch != null and .branch != "") | .branch' "$STATE_FILE")"
|
|
207
|
-
|
|
208
|
-
while IFS= read -r branch; do
|
|
209
|
-
[[ -z "$branch" ]] && continue
|
|
210
|
-
branches_checked=$((branches_checked + 1))
|
|
211
|
-
|
|
212
|
-
# Check if branch exists in git
|
|
213
|
-
if ! git -C "$REPO_ROOT" rev-parse --verify "refs/heads/$branch" &>/dev/null; then
|
|
214
|
-
missing_branches+=("$branch")
|
|
215
|
-
fi
|
|
216
|
-
done <<< "$task_branches"
|
|
217
|
-
|
|
218
|
-
if [[ -z "${missing_branches+x}" ]] || [[ ${#missing_branches[@]} -eq 0 ]]; then
|
|
219
|
-
check_pass "Task branches exist ($branches_checked branches verified)"
|
|
220
|
-
return 0
|
|
221
|
-
else
|
|
222
|
-
local missing_list
|
|
223
|
-
missing_list="$(IFS=', '; echo "${missing_branches[*]}")"
|
|
224
|
-
check_fail "Task branches exist" "Missing branches: $missing_list"
|
|
225
|
-
return 1
|
|
226
|
-
fi
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
# ============================================================
|
|
230
|
-
# CHECK 4: Worktrees listed in state exist on disk
|
|
231
|
-
# ============================================================
|
|
232
|
-
|
|
233
|
-
check_worktrees_exist() {
|
|
234
|
-
local worktree_count
|
|
235
|
-
worktree_count="$(jq '.worktrees | length' "$STATE_FILE")"
|
|
236
|
-
|
|
237
|
-
if [[ "$worktree_count" -eq 0 ]]; then
|
|
238
|
-
check_pass "Worktrees exist (no worktrees to check)"
|
|
239
|
-
return 0
|
|
240
|
-
fi
|
|
241
|
-
|
|
242
|
-
# Get actual git worktrees
|
|
243
|
-
local git_worktrees
|
|
244
|
-
git_worktrees="$(git -C "$REPO_ROOT" worktree list --porcelain 2>/dev/null | grep '^worktree ' | sed 's/^worktree //' || true)"
|
|
245
|
-
|
|
246
|
-
local missing_worktrees=()
|
|
247
|
-
local worktrees_checked=0
|
|
248
|
-
|
|
249
|
-
# Check each worktree in state
|
|
250
|
-
local worktree_paths
|
|
251
|
-
worktree_paths="$(jq -r '.worktrees | to_entries[] | select(.value.status == "active") | .value.path // empty' "$STATE_FILE")"
|
|
252
|
-
|
|
253
|
-
while IFS= read -r wt_path; do
|
|
254
|
-
[[ -z "$wt_path" ]] && continue
|
|
255
|
-
worktrees_checked=$((worktrees_checked + 1))
|
|
256
|
-
|
|
257
|
-
if [[ ! -d "$wt_path" ]]; then
|
|
258
|
-
missing_worktrees+=("$wt_path")
|
|
259
|
-
elif ! echo "$git_worktrees" | grep -qFx "$wt_path"; then
|
|
260
|
-
missing_worktrees+=("$wt_path (not a git worktree)")
|
|
261
|
-
fi
|
|
262
|
-
done <<< "$worktree_paths"
|
|
263
|
-
|
|
264
|
-
if [[ -z "${missing_worktrees+x}" ]] || [[ ${#missing_worktrees[@]} -eq 0 ]]; then
|
|
265
|
-
check_pass "Worktrees exist ($worktrees_checked worktrees verified)"
|
|
266
|
-
return 0
|
|
267
|
-
else
|
|
268
|
-
local missing_list
|
|
269
|
-
missing_list="$(IFS=', '; echo "${missing_worktrees[*]}")"
|
|
270
|
-
check_fail "Worktrees exist" "Missing worktree paths: $missing_list"
|
|
271
|
-
return 1
|
|
272
|
-
fi
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
# ============================================================
|
|
276
|
-
# CHECK 5: Task status consistency
|
|
277
|
-
# ============================================================
|
|
278
|
-
|
|
279
|
-
check_task_status_consistency() {
|
|
280
|
-
local task_count
|
|
281
|
-
task_count="$(jq '.tasks | length' "$STATE_FILE")"
|
|
282
|
-
|
|
283
|
-
if [[ "$task_count" -eq 0 ]]; then
|
|
284
|
-
check_pass "Task status consistency (no tasks to check)"
|
|
285
|
-
return 0
|
|
286
|
-
fi
|
|
287
|
-
|
|
288
|
-
local inconsistencies=()
|
|
289
|
-
|
|
290
|
-
# Check for in-progress tasks without branches
|
|
291
|
-
local in_progress_no_branch
|
|
292
|
-
in_progress_no_branch="$(jq -r '.tasks[] | select(.status == "in-progress" and (.branch == null or .branch == "")) | .id' "$STATE_FILE")"
|
|
293
|
-
|
|
294
|
-
while IFS= read -r task_id; do
|
|
295
|
-
[[ -z "$task_id" ]] && continue
|
|
296
|
-
inconsistencies+=("Task $task_id is in-progress but has no branch")
|
|
297
|
-
done <<< "$in_progress_no_branch"
|
|
298
|
-
|
|
299
|
-
if [[ -z "${inconsistencies+x}" ]] || [[ ${#inconsistencies[@]} -eq 0 ]]; then
|
|
300
|
-
check_pass "Task status consistency ($task_count tasks checked)"
|
|
301
|
-
return 0
|
|
302
|
-
else
|
|
303
|
-
local issue_list
|
|
304
|
-
issue_list="$(IFS='; '; echo "${inconsistencies[*]}")"
|
|
305
|
-
check_fail "Task status consistency" "$issue_list"
|
|
306
|
-
return 1
|
|
307
|
-
fi
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
# ============================================================
|
|
311
|
-
# EXECUTE CHECKS
|
|
312
|
-
# ============================================================
|
|
313
|
-
|
|
314
|
-
if check_state_file; then
|
|
315
|
-
check_phase_valid || true
|
|
316
|
-
check_task_branches || true
|
|
317
|
-
check_worktrees_exist || true
|
|
318
|
-
check_task_status_consistency || true
|
|
319
|
-
fi
|
|
320
|
-
|
|
321
|
-
# ============================================================
|
|
322
|
-
# STRUCTURED OUTPUT
|
|
323
|
-
# ============================================================
|
|
324
|
-
|
|
325
|
-
echo "## State Reconciliation Report"
|
|
326
|
-
echo ""
|
|
327
|
-
echo "**State file:** \`$STATE_FILE\`"
|
|
328
|
-
echo "**Repo root:** \`$REPO_ROOT\`"
|
|
329
|
-
echo ""
|
|
330
|
-
|
|
331
|
-
for result in "${RESULTS[@]}"; do
|
|
332
|
-
echo "$result"
|
|
333
|
-
done
|
|
334
|
-
|
|
335
|
-
echo ""
|
|
336
|
-
TOTAL=$((CHECK_PASS + CHECK_FAIL))
|
|
337
|
-
echo "---"
|
|
338
|
-
echo ""
|
|
339
|
-
|
|
340
|
-
if [[ $CHECK_FAIL -eq 0 ]]; then
|
|
341
|
-
echo "**Result: PASS** — State is consistent with git ($CHECK_PASS/$TOTAL checks passed)"
|
|
342
|
-
exit 0
|
|
343
|
-
else
|
|
344
|
-
echo "**Result: FAIL** — Discrepancies found ($CHECK_FAIL/$TOTAL checks failed)"
|
|
345
|
-
exit 1
|
|
346
|
-
fi
|
package/scripts/review-diff.sh
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
#
|
|
3
|
-
# review-diff.sh - Generate context-efficient diff for code review
|
|
4
|
-
#
|
|
5
|
-
# Usage: review-diff.sh <worktree-path> [base-branch]
|
|
6
|
-
#
|
|
7
|
-
# Output: Structured diff with only changed sections
|
|
8
|
-
# - Stats summary
|
|
9
|
-
# - Unified diff with 3-line context
|
|
10
|
-
#
|
|
11
|
-
# This reduces context consumption by 80-90% compared to full file contents.
|
|
12
|
-
#
|
|
13
|
-
|
|
14
|
-
set -euo pipefail
|
|
15
|
-
|
|
16
|
-
WORKTREE="${1:-.}"
|
|
17
|
-
BASE="${2:-main}"
|
|
18
|
-
|
|
19
|
-
if [ ! -d "$WORKTREE" ]; then
|
|
20
|
-
echo "ERROR: Directory not found: $WORKTREE" >&2
|
|
21
|
-
exit 1
|
|
22
|
-
fi
|
|
23
|
-
|
|
24
|
-
cd "$WORKTREE"
|
|
25
|
-
|
|
26
|
-
# Check if we're in a git repository
|
|
27
|
-
if ! git rev-parse --git-dir > /dev/null 2>&1; then
|
|
28
|
-
echo "ERROR: Not a git repository: $WORKTREE" >&2
|
|
29
|
-
exit 1
|
|
30
|
-
fi
|
|
31
|
-
|
|
32
|
-
# Get current branch
|
|
33
|
-
CURRENT_BRANCH=$(git branch --show-current)
|
|
34
|
-
|
|
35
|
-
echo "## Review Diff"
|
|
36
|
-
echo ""
|
|
37
|
-
echo "**Worktree:** $WORKTREE"
|
|
38
|
-
echo "**Branch:** $CURRENT_BRANCH"
|
|
39
|
-
echo "**Base:** $BASE"
|
|
40
|
-
echo ""
|
|
41
|
-
|
|
42
|
-
# Stats summary
|
|
43
|
-
echo "### Changed Files"
|
|
44
|
-
echo ""
|
|
45
|
-
echo '```'
|
|
46
|
-
git diff "$BASE"...HEAD --stat 2>/dev/null || git diff "$BASE"..HEAD --stat
|
|
47
|
-
echo '```'
|
|
48
|
-
echo ""
|
|
49
|
-
|
|
50
|
-
# File list for quick reference
|
|
51
|
-
echo "### Files Modified"
|
|
52
|
-
echo ""
|
|
53
|
-
git diff "$BASE"...HEAD --name-only 2>/dev/null || git diff "$BASE"..HEAD --name-only | while read -r file; do
|
|
54
|
-
echo "- \`$file\`"
|
|
55
|
-
done
|
|
56
|
-
echo ""
|
|
57
|
-
|
|
58
|
-
# Unified diff with context
|
|
59
|
-
echo "### Diff Content"
|
|
60
|
-
echo ""
|
|
61
|
-
echo '```diff'
|
|
62
|
-
git diff "$BASE"...HEAD --unified=3 2>/dev/null || git diff "$BASE"..HEAD --unified=3
|
|
63
|
-
echo '```'
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# Review Verdict Classification
|
|
3
|
-
# Classifies review findings into a routing verdict for the quality-review workflow.
|
|
4
|
-
#
|
|
5
|
-
# Usage: review-verdict.sh --high <n> --medium <n> --low <n> [--blocked <reason>]
|
|
6
|
-
# review-verdict.sh --findings-file <path>
|
|
7
|
-
#
|
|
8
|
-
# Exit codes:
|
|
9
|
-
# 0 = APPROVED (no HIGH findings)
|
|
10
|
-
# 1 = NEEDS_FIXES (HIGH findings present)
|
|
11
|
-
# 2 = BLOCKED (--blocked flag) or usage error
|
|
12
|
-
|
|
13
|
-
set -euo pipefail
|
|
14
|
-
|
|
15
|
-
# ============================================================
|
|
16
|
-
# ARGUMENT PARSING
|
|
17
|
-
# ============================================================
|
|
18
|
-
|
|
19
|
-
HIGH_COUNT=""
|
|
20
|
-
MEDIUM_COUNT=""
|
|
21
|
-
LOW_COUNT=""
|
|
22
|
-
BLOCKED_REASON=""
|
|
23
|
-
FINDINGS_FILE=""
|
|
24
|
-
|
|
25
|
-
usage() {
|
|
26
|
-
cat << 'USAGE'
|
|
27
|
-
Usage: review-verdict.sh --high <n> --medium <n> --low <n> [--blocked <reason>]
|
|
28
|
-
review-verdict.sh --findings-file <path>
|
|
29
|
-
|
|
30
|
-
Classify review findings into a routing verdict.
|
|
31
|
-
|
|
32
|
-
Options:
|
|
33
|
-
--high <n> Number of HIGH-severity findings
|
|
34
|
-
--medium <n> Number of MEDIUM-severity findings
|
|
35
|
-
--low <n> Number of LOW-severity findings
|
|
36
|
-
--blocked <reason> Mark as BLOCKED with the given reason
|
|
37
|
-
--findings-file <path> JSON file with {high:N, medium:N, low:N}
|
|
38
|
-
--help Show this help message
|
|
39
|
-
|
|
40
|
-
Exit codes:
|
|
41
|
-
0 APPROVED (no HIGH findings)
|
|
42
|
-
1 NEEDS_FIXES (HIGH findings present)
|
|
43
|
-
2 BLOCKED or usage error
|
|
44
|
-
USAGE
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
while [[ $# -gt 0 ]]; do
|
|
48
|
-
case "$1" in
|
|
49
|
-
--high)
|
|
50
|
-
if [[ -z "${2:-}" ]]; then
|
|
51
|
-
echo "Error: --high requires a number argument" >&2
|
|
52
|
-
exit 2
|
|
53
|
-
fi
|
|
54
|
-
HIGH_COUNT="$2"
|
|
55
|
-
shift 2
|
|
56
|
-
;;
|
|
57
|
-
--medium)
|
|
58
|
-
if [[ -z "${2:-}" ]]; then
|
|
59
|
-
echo "Error: --medium requires a number argument" >&2
|
|
60
|
-
exit 2
|
|
61
|
-
fi
|
|
62
|
-
MEDIUM_COUNT="$2"
|
|
63
|
-
shift 2
|
|
64
|
-
;;
|
|
65
|
-
--low)
|
|
66
|
-
if [[ -z "${2:-}" ]]; then
|
|
67
|
-
echo "Error: --low requires a number argument" >&2
|
|
68
|
-
exit 2
|
|
69
|
-
fi
|
|
70
|
-
LOW_COUNT="$2"
|
|
71
|
-
shift 2
|
|
72
|
-
;;
|
|
73
|
-
--blocked)
|
|
74
|
-
if [[ -z "${2:-}" ]]; then
|
|
75
|
-
echo "Error: --blocked requires a reason argument" >&2
|
|
76
|
-
exit 2
|
|
77
|
-
fi
|
|
78
|
-
BLOCKED_REASON="$2"
|
|
79
|
-
shift 2
|
|
80
|
-
;;
|
|
81
|
-
--findings-file)
|
|
82
|
-
if [[ -z "${2:-}" ]]; then
|
|
83
|
-
echo "Error: --findings-file requires a path argument" >&2
|
|
84
|
-
exit 2
|
|
85
|
-
fi
|
|
86
|
-
FINDINGS_FILE="$2"
|
|
87
|
-
shift 2
|
|
88
|
-
;;
|
|
89
|
-
--help)
|
|
90
|
-
usage
|
|
91
|
-
exit 0
|
|
92
|
-
;;
|
|
93
|
-
*)
|
|
94
|
-
echo "Error: Unknown argument '$1'" >&2
|
|
95
|
-
usage >&2
|
|
96
|
-
exit 2
|
|
97
|
-
;;
|
|
98
|
-
esac
|
|
99
|
-
done
|
|
100
|
-
|
|
101
|
-
# ============================================================
|
|
102
|
-
# INPUT RESOLUTION
|
|
103
|
-
# ============================================================
|
|
104
|
-
|
|
105
|
-
# If --findings-file provided, parse JSON
|
|
106
|
-
if [[ -n "$FINDINGS_FILE" ]]; then
|
|
107
|
-
if [[ ! -f "$FINDINGS_FILE" ]]; then
|
|
108
|
-
echo "Error: Findings file not found: $FINDINGS_FILE" >&2
|
|
109
|
-
exit 2
|
|
110
|
-
fi
|
|
111
|
-
|
|
112
|
-
if ! command -v jq &>/dev/null; then
|
|
113
|
-
echo "Error: jq is required to parse findings file" >&2
|
|
114
|
-
exit 2
|
|
115
|
-
fi
|
|
116
|
-
|
|
117
|
-
HIGH_COUNT="$(jq -r '.high // 0' "$FINDINGS_FILE")"
|
|
118
|
-
MEDIUM_COUNT="$(jq -r '.medium // 0' "$FINDINGS_FILE")"
|
|
119
|
-
LOW_COUNT="$(jq -r '.low // 0' "$FINDINGS_FILE")"
|
|
120
|
-
|
|
121
|
-
# Ensure numeric values (guard against malformed JSON)
|
|
122
|
-
[[ "$HIGH_COUNT" =~ ^[0-9]+$ ]] || HIGH_COUNT=0
|
|
123
|
-
[[ "$MEDIUM_COUNT" =~ ^[0-9]+$ ]] || MEDIUM_COUNT=0
|
|
124
|
-
[[ "$LOW_COUNT" =~ ^[0-9]+$ ]] || LOW_COUNT=0
|
|
125
|
-
fi
|
|
126
|
-
|
|
127
|
-
# Validate we have the required inputs (either via flags or file)
|
|
128
|
-
if [[ -z "$HIGH_COUNT" && -z "$BLOCKED_REASON" ]]; then
|
|
129
|
-
echo "Error: Must provide --high/--medium/--low counts, --findings-file, or --blocked" >&2
|
|
130
|
-
usage >&2
|
|
131
|
-
exit 2
|
|
132
|
-
fi
|
|
133
|
-
|
|
134
|
-
# Default counts to 0 if not set
|
|
135
|
-
HIGH_COUNT="${HIGH_COUNT:-0}"
|
|
136
|
-
MEDIUM_COUNT="${MEDIUM_COUNT:-0}"
|
|
137
|
-
LOW_COUNT="${LOW_COUNT:-0}"
|
|
138
|
-
|
|
139
|
-
# ============================================================
|
|
140
|
-
# VERDICT LOGIC
|
|
141
|
-
# ============================================================
|
|
142
|
-
|
|
143
|
-
# Priority: BLOCKED > NEEDS_FIXES > APPROVED
|
|
144
|
-
if [[ -n "$BLOCKED_REASON" ]]; then
|
|
145
|
-
echo "## Review Verdict: BLOCKED"
|
|
146
|
-
echo ""
|
|
147
|
-
echo "**Reason:** $BLOCKED_REASON"
|
|
148
|
-
echo ""
|
|
149
|
-
echo "Return to design phase. Route to \`/ideate --redesign\`."
|
|
150
|
-
exit 2
|
|
151
|
-
fi
|
|
152
|
-
|
|
153
|
-
if [[ "$HIGH_COUNT" -gt 0 ]]; then
|
|
154
|
-
TOTAL=$((HIGH_COUNT + MEDIUM_COUNT + LOW_COUNT))
|
|
155
|
-
echo "## Review Verdict: NEEDS_FIXES"
|
|
156
|
-
echo ""
|
|
157
|
-
echo "Found $HIGH_COUNT HIGH-severity findings. Route to \`/delegate --fixes\`."
|
|
158
|
-
echo ""
|
|
159
|
-
echo "**Finding summary:** $HIGH_COUNT high, $MEDIUM_COUNT medium, $LOW_COUNT low ($TOTAL total)"
|
|
160
|
-
exit 1
|
|
161
|
-
fi
|
|
162
|
-
|
|
163
|
-
TOTAL=$((HIGH_COUNT + MEDIUM_COUNT + LOW_COUNT))
|
|
164
|
-
echo "## Review Verdict: APPROVED"
|
|
165
|
-
echo ""
|
|
166
|
-
echo "No HIGH-severity findings. Proceed to synthesis."
|
|
167
|
-
echo ""
|
|
168
|
-
echo "**Finding summary:** $HIGH_COUNT high, $MEDIUM_COUNT medium, $LOW_COUNT low ($TOTAL total)"
|
|
169
|
-
exit 0
|