@lvlup-sw/exarchos 2.0.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.
Files changed (153) hide show
  1. package/.claude-plugin/marketplace.json +22 -0
  2. package/.claude-plugin/plugin.json +17 -0
  3. package/.mcp.json +17 -0
  4. package/AGENTS.md +59 -0
  5. package/CLAUDE.md.template +62 -0
  6. package/LICENSE +202 -0
  7. package/README.md +258 -0
  8. package/commands/autocompact.md +37 -0
  9. package/commands/checkpoint.md +85 -0
  10. package/commands/cleanup.md +99 -0
  11. package/commands/debug.md +145 -0
  12. package/commands/delegate.md +56 -0
  13. package/commands/ideate.md +82 -0
  14. package/commands/plan.md +150 -0
  15. package/commands/refactor.md +139 -0
  16. package/commands/reload.md +37 -0
  17. package/commands/resume.md +130 -0
  18. package/commands/review.md +51 -0
  19. package/commands/sync-schemas.md +74 -0
  20. package/commands/synthesize.md +122 -0
  21. package/commands/tdd.md +58 -0
  22. package/dist/exarchos-cli.js +8828 -0
  23. package/dist/exarchos-mcp.js +50 -0
  24. package/hooks/hooks.json +53 -0
  25. package/package.json +59 -0
  26. package/rules/coding-standards.md +46 -0
  27. package/rules/mcp-tool-guidance.md +26 -0
  28. package/rules/pr-descriptions.md +12 -0
  29. package/rules/rm-safety.md +9 -0
  30. package/rules/skill-path-resolution.md +10 -0
  31. package/rules/tdd.md +41 -0
  32. package/rules/telemetry-awareness.md +9 -0
  33. package/scripts/assess-refactor-scope.sh +239 -0
  34. package/scripts/check-benchmark-regression.sh +229 -0
  35. package/scripts/check-coderabbit.sh +288 -0
  36. package/scripts/check-coverage-thresholds.sh +194 -0
  37. package/scripts/check-polish-scope.sh +245 -0
  38. package/scripts/check-property-tests.sh +167 -0
  39. package/scripts/check-tdd-compliance.sh +265 -0
  40. package/scripts/coderabbit-review-gate.sh +518 -0
  41. package/scripts/debug-review-gate.sh +201 -0
  42. package/scripts/extract-fix-tasks.sh +179 -0
  43. package/scripts/extract-task.sh +67 -0
  44. package/scripts/generate-traceability.sh +209 -0
  45. package/scripts/investigation-timer.sh +171 -0
  46. package/scripts/needs-schema-sync.sh +174 -0
  47. package/scripts/new-project.sh +103 -0
  48. package/scripts/post-delegation-check.sh +317 -0
  49. package/scripts/pre-synthesis-check.sh +440 -0
  50. package/scripts/reconcile-state.sh +346 -0
  51. package/scripts/reconstruct-stack.sh +432 -0
  52. package/scripts/review-diff.sh +63 -0
  53. package/scripts/review-verdict.sh +169 -0
  54. package/scripts/security-scan.sh +248 -0
  55. package/scripts/select-debug-track.sh +186 -0
  56. package/scripts/setup-worktree.sh +323 -0
  57. package/scripts/spec-coverage-check.sh +230 -0
  58. package/scripts/static-analysis-gate.sh +236 -0
  59. package/scripts/sync-labels.sh +122 -0
  60. package/scripts/validate-companion.sh +161 -0
  61. package/scripts/validate-dotnet-standards.sh +267 -0
  62. package/scripts/validate-installation.sh +101 -0
  63. package/scripts/validate-plugin.sh +223 -0
  64. package/scripts/validate-refactor.sh +234 -0
  65. package/scripts/validate-rm.sh +93 -0
  66. package/scripts/verify-delegation-saga.sh +240 -0
  67. package/scripts/verify-doc-links.sh +211 -0
  68. package/scripts/verify-ideate-artifacts.sh +296 -0
  69. package/scripts/verify-plan-coverage.sh +228 -0
  70. package/scripts/verify-review-triage.sh +219 -0
  71. package/scripts/verify-worktree-baseline.sh +159 -0
  72. package/scripts/verify-worktree.sh +84 -0
  73. package/settings.json +47 -0
  74. package/skills/brainstorming/SKILL.md +127 -0
  75. package/skills/brainstorming/references/design-template.md +65 -0
  76. package/skills/cleanup/SKILL.md +147 -0
  77. package/skills/cleanup/references/merge-verification.md +40 -0
  78. package/skills/debug/SKILL.md +204 -0
  79. package/skills/debug/references/hotfix-track.md +134 -0
  80. package/skills/debug/references/investigation-checklist.md +217 -0
  81. package/skills/debug/references/rca-template.md +150 -0
  82. package/skills/debug/references/state-schema.md +294 -0
  83. package/skills/debug/references/thorough-track.md +194 -0
  84. package/skills/debug/references/triage-questions.md +155 -0
  85. package/skills/debug/references/troubleshooting.md +47 -0
  86. package/skills/delegation/SKILL.md +150 -0
  87. package/skills/delegation/references/adaptive-orchestration.md +31 -0
  88. package/skills/delegation/references/agent-teams-saga.md +248 -0
  89. package/skills/delegation/references/fix-mode.md +74 -0
  90. package/skills/delegation/references/fixer-prompt.md +162 -0
  91. package/skills/delegation/references/implementer-prompt.md +322 -0
  92. package/skills/delegation/references/parallel-strategy.md +124 -0
  93. package/skills/delegation/references/pbt-patterns.md +172 -0
  94. package/skills/delegation/references/pr-fixes-mode.md +154 -0
  95. package/skills/delegation/references/state-management.md +51 -0
  96. package/skills/delegation/references/testing-patterns.md +129 -0
  97. package/skills/delegation/references/troubleshooting.md +33 -0
  98. package/skills/delegation/references/workflow-steps.md +127 -0
  99. package/skills/delegation/references/worktree-enforcement.md +64 -0
  100. package/skills/dotnet-standards/SKILL.md +269 -0
  101. package/skills/dotnet-standards/references/csharp-standards.md +120 -0
  102. package/skills/dotnet-standards/templates/.editorconfig +366 -0
  103. package/skills/dotnet-standards/templates/Directory.Build.props +56 -0
  104. package/skills/dotnet-standards/templates/Directory.Packages.props +69 -0
  105. package/skills/dotnet-standards/templates/global.json +6 -0
  106. package/skills/dotnet-standards/templates/nuget.config +9 -0
  107. package/skills/dotnet-standards/templates/stylecop.json +37 -0
  108. package/skills/git-worktrees/SKILL.md +255 -0
  109. package/skills/implementation-planning/SKILL.md +233 -0
  110. package/skills/implementation-planning/references/plan-document-template.md +42 -0
  111. package/skills/implementation-planning/references/spec-tracing-guide.md +51 -0
  112. package/skills/implementation-planning/references/task-template.md +43 -0
  113. package/skills/implementation-planning/references/testing-strategy-guide.md +88 -0
  114. package/skills/quality-review/SKILL.md +278 -0
  115. package/skills/quality-review/references/code-quality-checklist.md +159 -0
  116. package/skills/quality-review/references/review-report-template.md +65 -0
  117. package/skills/quality-review/references/security-checklist.md +79 -0
  118. package/skills/quality-review/references/typescript-standards.md +24 -0
  119. package/skills/refactor/COMMAND.md +67 -0
  120. package/skills/refactor/SKILL.md +198 -0
  121. package/skills/refactor/phases/auto-chain.md +262 -0
  122. package/skills/refactor/phases/brief.md +176 -0
  123. package/skills/refactor/phases/explore.md +132 -0
  124. package/skills/refactor/phases/overhaul-delegate.md +136 -0
  125. package/skills/refactor/phases/overhaul-plan.md +312 -0
  126. package/skills/refactor/phases/overhaul-review.md +304 -0
  127. package/skills/refactor/phases/polish-implement.md +349 -0
  128. package/skills/refactor/phases/polish-validate.md +218 -0
  129. package/skills/refactor/phases/update-docs.md +234 -0
  130. package/skills/refactor/references/brief-template.md +81 -0
  131. package/skills/refactor/references/doc-update-checklist.md +110 -0
  132. package/skills/refactor/references/explore-checklist.md +73 -0
  133. package/skills/refactor/references/overhaul-track.md +215 -0
  134. package/skills/refactor/references/polish-track.md +170 -0
  135. package/skills/shared/prompts/context-reading.md +58 -0
  136. package/skills/shared/prompts/report-format.md +54 -0
  137. package/skills/shared/prompts/tdd-requirements.md +39 -0
  138. package/skills/shepherd/SKILL.md +264 -0
  139. package/skills/shepherd/references/assess-checklist.md +124 -0
  140. package/skills/shepherd/references/fix-strategies.md +191 -0
  141. package/skills/spec-review/SKILL.md +229 -0
  142. package/skills/spec-review/references/review-checklist.md +60 -0
  143. package/skills/sync-schemas/SKILL.md +114 -0
  144. package/skills/sync-schemas/references/configuration.md +73 -0
  145. package/skills/synthesis/SKILL.md +129 -0
  146. package/skills/synthesis/references/pr-descriptions.md +87 -0
  147. package/skills/synthesis/references/synthesis-steps.md +109 -0
  148. package/skills/synthesis/references/troubleshooting.md +115 -0
  149. package/skills/validate-all-skills.sh +57 -0
  150. package/skills/validate-frontmatter.sh +237 -0
  151. package/skills/workflow-state/SKILL.md +210 -0
  152. package/skills/workflow-state/references/mcp-tool-reference.md +111 -0
  153. package/skills/workflow-state/references/phase-transitions.md +141 -0
@@ -0,0 +1,432 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # reconstruct-stack.sh - Detect and reconstruct broken Graphite stacks
4
+ #
5
+ # Detects diverged/broken Graphite stacks and reconstructs them idempotently.
6
+ # Three phases: Detection, Reconstruction, Validation.
7
+ #
8
+ # Usage: reconstruct-stack.sh --repo-root <path> [--state-file <path>] [--dry-run] [--help]
9
+ #
10
+ # Exit codes:
11
+ # 0 = stack healthy or successfully reconstructed
12
+ # 1 = reconstruction failed (validation failed after attempt)
13
+ # 2 = usage error
14
+ #
15
+
16
+ set -euo pipefail
17
+
18
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
19
+ REPO_ROOT=""
20
+ STATE_FILE=""
21
+ DRY_RUN=false
22
+
23
+ # Colors
24
+ RED='\033[0;31m'
25
+ GREEN='\033[0;32m'
26
+ YELLOW='\033[1;33m'
27
+ BLUE='\033[0;34m'
28
+ NC='\033[0m'
29
+
30
+ # ============================================================
31
+ # USAGE & ARGUMENT PARSING
32
+ # ============================================================
33
+
34
+ usage() {
35
+ cat <<EOF
36
+ Usage: $(basename "$0") --repo-root <path> [--state-file <path>] [--dry-run] [--help]
37
+
38
+ Detect and reconstruct broken Graphite stacks.
39
+
40
+ Options:
41
+ --repo-root <path> Path to the git repository root (required)
42
+ --state-file <path> Path to workflow state JSON file (optional, auto-detected)
43
+ --dry-run Report actions without making changes
44
+ --help Show this help message
45
+
46
+ Exit codes:
47
+ 0 = stack healthy or successfully reconstructed
48
+ 1 = reconstruction failed (validation failed after attempt)
49
+ 2 = usage error
50
+
51
+ Dependencies: jq, gt (Graphite CLI)
52
+ EOF
53
+ }
54
+
55
+ parse_args() {
56
+ while [[ $# -gt 0 ]]; do
57
+ case "$1" in
58
+ --repo-root)
59
+ REPO_ROOT="${2:-}"
60
+ if [[ -z "$REPO_ROOT" ]]; then
61
+ echo -e "${RED}ERROR${NC}: --repo-root requires a value" >&2
62
+ exit 2
63
+ fi
64
+ shift 2
65
+ ;;
66
+ --state-file)
67
+ STATE_FILE="${2:-}"
68
+ if [[ -z "$STATE_FILE" ]]; then
69
+ echo -e "${RED}ERROR${NC}: --state-file requires a value" >&2
70
+ exit 2
71
+ fi
72
+ shift 2
73
+ ;;
74
+ --dry-run)
75
+ DRY_RUN=true
76
+ shift
77
+ ;;
78
+ --help)
79
+ usage
80
+ exit 0
81
+ ;;
82
+ *)
83
+ echo -e "${RED}ERROR${NC}: Unknown argument: $1" >&2
84
+ usage >&2
85
+ exit 2
86
+ ;;
87
+ esac
88
+ done
89
+
90
+ if [[ -z "$REPO_ROOT" ]]; then
91
+ echo -e "${RED}ERROR${NC}: --repo-root is required" >&2
92
+ usage >&2
93
+ exit 2
94
+ fi
95
+
96
+ if [[ ! -d "$REPO_ROOT/.git" ]] && [[ ! -f "$REPO_ROOT/.git" ]]; then
97
+ echo -e "${RED}ERROR${NC}: $REPO_ROOT is not a git repository" >&2
98
+ exit 2
99
+ fi
100
+ }
101
+
102
+ # ============================================================
103
+ # DEPENDENCY CHECKS
104
+ # ============================================================
105
+
106
+ check_dependencies() {
107
+ if ! command -v jq >/dev/null 2>&1; then
108
+ echo -e "${RED}ERROR${NC}: jq is required but not found. Install with: brew install jq" >&2
109
+ exit 2
110
+ fi
111
+
112
+ if ! command -v gt >/dev/null 2>&1; then
113
+ echo -e "${RED}ERROR${NC}: gt (Graphite CLI) is required but not found. Install with: npm install -g @withgraphite/graphite-cli" >&2
114
+ exit 2
115
+ fi
116
+ }
117
+
118
+ # ============================================================
119
+ # HELPERS
120
+ # ============================================================
121
+
122
+ # Read task branches from state file in order
123
+ # Output: one branch name per line, in task order
124
+ get_expected_branches() {
125
+ if [[ -z "$STATE_FILE" || ! -f "$STATE_FILE" ]]; then
126
+ return 0
127
+ fi
128
+ jq -r '.tasks[]? | .branch // empty' "$STATE_FILE" 2>/dev/null || true
129
+ }
130
+
131
+ # Get task count from state file
132
+ get_task_count() {
133
+ if [[ -z "$STATE_FILE" || ! -f "$STATE_FILE" ]]; then
134
+ echo "0"
135
+ return 0
136
+ fi
137
+ jq -r '.tasks | length' "$STATE_FILE" 2>/dev/null || echo "0"
138
+ }
139
+
140
+ # Parse gt log output for branch names (strip whitespace, annotations)
141
+ # Input: gt log output on stdin
142
+ # Output: branch names, one per line (top = newest)
143
+ parse_gt_log_branches() {
144
+ # gt log lines: " branch-name", " branch-name (diverged)", etc.
145
+ sed -E 's/^[[:space:]]*//; s/[[:space:]]*\(.*\)[[:space:]]*$//' | grep -v '^$' || true
146
+ }
147
+
148
+ # Check if a gt log line has a problem annotation
149
+ # Args: $1 = gt log line
150
+ get_line_status() {
151
+ local line="$1"
152
+ if echo "$line" | grep -q "(diverged)"; then
153
+ echo "diverged"
154
+ elif echo "$line" | grep -q "(needs restack)"; then
155
+ echo "needs restack"
156
+ else
157
+ echo "clean"
158
+ fi
159
+ }
160
+
161
+ # Get the SHA that a branch currently points to
162
+ # Args: $1 = branch name
163
+ # Output: SHA or empty string
164
+ get_branch_sha() {
165
+ local branch="$1"
166
+ (cd "$REPO_ROOT" && git rev-parse "$branch" 2>/dev/null) || true
167
+ }
168
+
169
+ # Find worktree path for a given branch, if any
170
+ # Args: $1 = branch name
171
+ # Output: worktree path or empty string
172
+ find_worktree_for_branch() {
173
+ local branch="$1"
174
+ (cd "$REPO_ROOT" && git worktree list --porcelain 2>/dev/null) | \
175
+ grep -A2 "^worktree " | grep -B1 "branch refs/heads/$branch" | \
176
+ head -1 | sed 's/^worktree //' || true
177
+ }
178
+
179
+ # ============================================================
180
+ # PHASE 1: DETECTION
181
+ # ============================================================
182
+
183
+ detect_problems() {
184
+ local gt_log_output="$1"
185
+ local problems=()
186
+ local diverged_branches=()
187
+ local restack_branches=()
188
+ local missing_branches=()
189
+
190
+ # Parse gt log for status annotations
191
+ while IFS= read -r line; do
192
+ [[ -z "$line" ]] && continue
193
+ local branch_name
194
+ branch_name=$(echo "$line" | sed -E 's/^[[:space:]]*//' | sed -E 's/[[:space:]]*\(.*\)[[:space:]]*$//')
195
+ local status
196
+ status=$(get_line_status "$line")
197
+
198
+ case "$status" in
199
+ "diverged")
200
+ diverged_branches+=("$branch_name")
201
+ problems+=("Branch '$branch_name' is diverged")
202
+ ;;
203
+ "needs restack")
204
+ restack_branches+=("$branch_name")
205
+ problems+=("Branch '$branch_name' needs restack")
206
+ ;;
207
+ esac
208
+ done <<< "$gt_log_output"
209
+
210
+ # Check expected branches from state file against gt log
211
+ local gt_branches
212
+ gt_branches=$(echo "$gt_log_output" | parse_gt_log_branches)
213
+
214
+ while IFS= read -r expected_branch; do
215
+ [[ -z "$expected_branch" ]] && continue
216
+ if ! echo "$gt_branches" | grep -qx "$expected_branch"; then
217
+ missing_branches+=("$expected_branch")
218
+ problems+=("Branch '$expected_branch' not tracked in Graphite (missing)")
219
+ fi
220
+ done < <(get_expected_branches)
221
+
222
+ # Output results
223
+ DETECTED_PROBLEMS=("${problems[@]+"${problems[@]}"}")
224
+ DETECTED_DIVERGED=("${diverged_branches[@]+"${diverged_branches[@]}"}")
225
+ DETECTED_RESTACK=("${restack_branches[@]+"${restack_branches[@]}"}")
226
+ DETECTED_MISSING=("${missing_branches[@]+"${missing_branches[@]}"}")
227
+ }
228
+
229
+ # ============================================================
230
+ # PHASE 2: RECONSTRUCTION
231
+ # ============================================================
232
+
233
+ reconstruct_stack() {
234
+ local expected_branches=()
235
+ while IFS= read -r branch; do
236
+ [[ -z "$branch" ]] && continue
237
+ expected_branches+=("$branch")
238
+ done < <(get_expected_branches)
239
+
240
+ if [[ ${#expected_branches[@]} -eq 0 ]]; then
241
+ echo -e "${YELLOW}No task branches to reconstruct${NC}"
242
+ return 0
243
+ fi
244
+
245
+ echo -e "${BLUE}## Reconstruction${NC}"
246
+ echo ""
247
+
248
+ # Step 1: Untrack all task branches from Graphite
249
+ echo -e "${BLUE}### Step 1: Untrack stale branches${NC}"
250
+ for branch in "${expected_branches[@]}"; do
251
+ if $DRY_RUN; then
252
+ echo -e " ${YELLOW}[dry-run]${NC} Would untrack: $branch"
253
+ else
254
+ echo " Untracking: $branch"
255
+ gt untrack "$branch" 2>/dev/null || true
256
+ fi
257
+ done
258
+ echo ""
259
+
260
+ # Step 2: Remove worktrees that might block branch resets
261
+ echo -e "${BLUE}### Step 2: Check for blocking worktrees${NC}"
262
+ for branch in "${expected_branches[@]}"; do
263
+ local worktree_path=""
264
+ worktree_path=$(find_worktree_for_branch "$branch")
265
+ if [[ -n "$worktree_path" ]]; then
266
+ if $DRY_RUN; then
267
+ echo -e " ${YELLOW}[dry-run]${NC} Would remove worktree: $worktree_path (branch: $branch)"
268
+ else
269
+ echo " Removing worktree: $worktree_path (branch: $branch)"
270
+ (cd "$REPO_ROOT" && git worktree remove "$worktree_path" --force 2>/dev/null || true)
271
+ fi
272
+ fi
273
+ done
274
+ echo ""
275
+
276
+ # Step 3: Reset branch pointers
277
+ echo -e "${BLUE}### Step 3: Reset branch pointers${NC}"
278
+ for branch in "${expected_branches[@]}"; do
279
+ local target_sha=""
280
+ target_sha=$(get_branch_sha "$branch")
281
+ if [[ -n "$target_sha" ]]; then
282
+ if $DRY_RUN; then
283
+ echo -e " ${YELLOW}[dry-run]${NC} Would reset: $branch -> ${target_sha:0:8}"
284
+ else
285
+ echo " Resetting: $branch -> ${target_sha:0:8}"
286
+ (cd "$REPO_ROOT" && git branch -f "$branch" "$target_sha" 2>/dev/null || true)
287
+ fi
288
+ else
289
+ echo -e " ${YELLOW}Skipping${NC}: $branch (no commit mapping found)"
290
+ fi
291
+ done
292
+ echo ""
293
+
294
+ # Step 4: Re-track with correct parent chain
295
+ echo -e "${BLUE}### Step 4: Re-track with parent chain${NC}"
296
+ local prev_branch="main"
297
+ for branch in "${expected_branches[@]}"; do
298
+ if $DRY_RUN; then
299
+ echo -e " ${YELLOW}[dry-run]${NC} Would track: $branch --parent $prev_branch"
300
+ else
301
+ echo " Tracking: $branch --parent $prev_branch"
302
+ gt track --parent "$prev_branch" --branch "$branch" 2>/dev/null || true
303
+ fi
304
+ prev_branch="$branch"
305
+ done
306
+ echo ""
307
+ }
308
+
309
+ # ============================================================
310
+ # PHASE 3: VALIDATION
311
+ # ============================================================
312
+
313
+ validate_stack() {
314
+ local gt_log_output="$1"
315
+ local issues=()
316
+
317
+ # Check for any remaining problem annotations
318
+ while IFS= read -r line; do
319
+ [[ -z "$line" ]] && continue
320
+ local status
321
+ status=$(get_line_status "$line")
322
+ if [[ "$status" != "clean" ]]; then
323
+ local branch_name
324
+ branch_name=$(echo "$line" | sed -E 's/^[[:space:]]*//' | sed -E 's/[[:space:]]*\(.*\)[[:space:]]*$//')
325
+ issues+=("Branch '$branch_name' still shows: $status")
326
+ fi
327
+ done <<< "$gt_log_output"
328
+
329
+ # Check expected branches are all tracked
330
+ local gt_branches
331
+ gt_branches=$(echo "$gt_log_output" | parse_gt_log_branches)
332
+
333
+ while IFS= read -r expected_branch; do
334
+ [[ -z "$expected_branch" ]] && continue
335
+ if ! echo "$gt_branches" | grep -qx "$expected_branch"; then
336
+ issues+=("Branch '$expected_branch' still not tracked after reconstruction")
337
+ fi
338
+ done < <(get_expected_branches)
339
+
340
+ VALIDATION_ISSUES=("${issues[@]+"${issues[@]}"}")
341
+ }
342
+
343
+ # ============================================================
344
+ # MAIN
345
+ # ============================================================
346
+
347
+ main() {
348
+ parse_args "$@"
349
+ check_dependencies
350
+
351
+ local task_count
352
+ task_count=$(get_task_count)
353
+
354
+ # Early exit if no tasks
355
+ if [[ "$task_count" -eq 0 ]]; then
356
+ echo -e "${GREEN}Stack is healthy${NC} (no tasks defined)"
357
+ exit 0
358
+ fi
359
+
360
+ echo -e "${BLUE}# Stack Reconstruction${NC}"
361
+ echo ""
362
+
363
+ # Phase 1: Detection
364
+ echo -e "${BLUE}## Detection${NC}"
365
+ echo ""
366
+
367
+ local gt_log_output
368
+ gt_log_output=$(cd "$REPO_ROOT" && gt log 2>/dev/null || true)
369
+
370
+ DETECTED_PROBLEMS=()
371
+ DETECTED_DIVERGED=()
372
+ DETECTED_RESTACK=()
373
+ DETECTED_MISSING=()
374
+ detect_problems "$gt_log_output"
375
+
376
+ if [[ ${#DETECTED_PROBLEMS[@]} -eq 0 ]]; then
377
+ echo -e "${GREEN}Stack is healthy${NC} — all ${task_count} task branches tracked and clean"
378
+ exit 0
379
+ fi
380
+
381
+ echo "Detected ${#DETECTED_PROBLEMS[@]} problem(s):"
382
+ for problem in "${DETECTED_PROBLEMS[@]}"; do
383
+ echo -e " - ${YELLOW}$problem${NC}"
384
+ done
385
+ echo ""
386
+
387
+ if [[ ${#DETECTED_DIVERGED[@]} -gt 0 ]]; then
388
+ echo "Diverged branches: ${DETECTED_DIVERGED[*]}"
389
+ fi
390
+ if [[ ${#DETECTED_RESTACK[@]} -gt 0 ]]; then
391
+ echo "Needs restack: ${DETECTED_RESTACK[*]}"
392
+ fi
393
+ if [[ ${#DETECTED_MISSING[@]} -gt 0 ]]; then
394
+ echo "Missing from stack: ${DETECTED_MISSING[*]}"
395
+ fi
396
+ echo ""
397
+
398
+ # Phase 2: Reconstruction
399
+ reconstruct_stack
400
+
401
+ # Phase 3: Validation
402
+ echo -e "${BLUE}## Validation${NC}"
403
+ echo ""
404
+
405
+ if $DRY_RUN; then
406
+ echo -e "${YELLOW}Skipping validation (dry-run mode)${NC}"
407
+ echo ""
408
+ echo -e "${GREEN}Dry run complete${NC} — no changes were made"
409
+ exit 0
410
+ fi
411
+
412
+ local post_gt_log
413
+ post_gt_log=$(cd "$REPO_ROOT" && gt log 2>/dev/null || true)
414
+
415
+ VALIDATION_ISSUES=()
416
+ validate_stack "$post_gt_log"
417
+
418
+ if [[ ${#VALIDATION_ISSUES[@]} -eq 0 ]]; then
419
+ echo -e "${GREEN}Validation passed${NC} — stack is clean after reconstruction"
420
+ exit 0
421
+ fi
422
+
423
+ echo -e "${RED}Validation failed${NC} — ${#VALIDATION_ISSUES[@]} issue(s) remain:"
424
+ for issue in "${VALIDATION_ISSUES[@]}"; do
425
+ echo -e " - ${RED}$issue${NC}"
426
+ done
427
+ echo ""
428
+ echo "Manual intervention may be required."
429
+ exit 1
430
+ }
431
+
432
+ main "$@"
@@ -0,0 +1,63 @@
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 '```'
@@ -0,0 +1,169 @@
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