@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.
- package/.claude-plugin/marketplace.json +22 -0
- package/.claude-plugin/plugin.json +17 -0
- package/.mcp.json +17 -0
- package/AGENTS.md +59 -0
- package/CLAUDE.md.template +62 -0
- package/LICENSE +202 -0
- package/README.md +258 -0
- package/commands/autocompact.md +37 -0
- package/commands/checkpoint.md +85 -0
- package/commands/cleanup.md +99 -0
- package/commands/debug.md +145 -0
- package/commands/delegate.md +56 -0
- package/commands/ideate.md +82 -0
- package/commands/plan.md +150 -0
- package/commands/refactor.md +139 -0
- package/commands/reload.md +37 -0
- package/commands/resume.md +130 -0
- package/commands/review.md +51 -0
- package/commands/sync-schemas.md +74 -0
- package/commands/synthesize.md +122 -0
- package/commands/tdd.md +58 -0
- package/dist/exarchos-cli.js +8828 -0
- package/dist/exarchos-mcp.js +50 -0
- package/hooks/hooks.json +53 -0
- package/package.json +59 -0
- package/rules/coding-standards.md +46 -0
- package/rules/mcp-tool-guidance.md +26 -0
- package/rules/pr-descriptions.md +12 -0
- package/rules/rm-safety.md +9 -0
- package/rules/skill-path-resolution.md +10 -0
- package/rules/tdd.md +41 -0
- package/rules/telemetry-awareness.md +9 -0
- package/scripts/assess-refactor-scope.sh +239 -0
- package/scripts/check-benchmark-regression.sh +229 -0
- package/scripts/check-coderabbit.sh +288 -0
- package/scripts/check-coverage-thresholds.sh +194 -0
- package/scripts/check-polish-scope.sh +245 -0
- package/scripts/check-property-tests.sh +167 -0
- package/scripts/check-tdd-compliance.sh +265 -0
- package/scripts/coderabbit-review-gate.sh +518 -0
- package/scripts/debug-review-gate.sh +201 -0
- package/scripts/extract-fix-tasks.sh +179 -0
- package/scripts/extract-task.sh +67 -0
- package/scripts/generate-traceability.sh +209 -0
- package/scripts/investigation-timer.sh +171 -0
- package/scripts/needs-schema-sync.sh +174 -0
- package/scripts/new-project.sh +103 -0
- package/scripts/post-delegation-check.sh +317 -0
- package/scripts/pre-synthesis-check.sh +440 -0
- package/scripts/reconcile-state.sh +346 -0
- package/scripts/reconstruct-stack.sh +432 -0
- package/scripts/review-diff.sh +63 -0
- package/scripts/review-verdict.sh +169 -0
- package/scripts/security-scan.sh +248 -0
- package/scripts/select-debug-track.sh +186 -0
- package/scripts/setup-worktree.sh +323 -0
- package/scripts/spec-coverage-check.sh +230 -0
- package/scripts/static-analysis-gate.sh +236 -0
- package/scripts/sync-labels.sh +122 -0
- package/scripts/validate-companion.sh +161 -0
- package/scripts/validate-dotnet-standards.sh +267 -0
- package/scripts/validate-installation.sh +101 -0
- package/scripts/validate-plugin.sh +223 -0
- package/scripts/validate-refactor.sh +234 -0
- package/scripts/validate-rm.sh +93 -0
- package/scripts/verify-delegation-saga.sh +240 -0
- package/scripts/verify-doc-links.sh +211 -0
- package/scripts/verify-ideate-artifacts.sh +296 -0
- package/scripts/verify-plan-coverage.sh +228 -0
- package/scripts/verify-review-triage.sh +219 -0
- package/scripts/verify-worktree-baseline.sh +159 -0
- package/scripts/verify-worktree.sh +84 -0
- package/settings.json +47 -0
- package/skills/brainstorming/SKILL.md +127 -0
- package/skills/brainstorming/references/design-template.md +65 -0
- package/skills/cleanup/SKILL.md +147 -0
- package/skills/cleanup/references/merge-verification.md +40 -0
- package/skills/debug/SKILL.md +204 -0
- package/skills/debug/references/hotfix-track.md +134 -0
- package/skills/debug/references/investigation-checklist.md +217 -0
- package/skills/debug/references/rca-template.md +150 -0
- package/skills/debug/references/state-schema.md +294 -0
- package/skills/debug/references/thorough-track.md +194 -0
- package/skills/debug/references/triage-questions.md +155 -0
- package/skills/debug/references/troubleshooting.md +47 -0
- package/skills/delegation/SKILL.md +150 -0
- package/skills/delegation/references/adaptive-orchestration.md +31 -0
- package/skills/delegation/references/agent-teams-saga.md +248 -0
- package/skills/delegation/references/fix-mode.md +74 -0
- package/skills/delegation/references/fixer-prompt.md +162 -0
- package/skills/delegation/references/implementer-prompt.md +322 -0
- package/skills/delegation/references/parallel-strategy.md +124 -0
- package/skills/delegation/references/pbt-patterns.md +172 -0
- package/skills/delegation/references/pr-fixes-mode.md +154 -0
- package/skills/delegation/references/state-management.md +51 -0
- package/skills/delegation/references/testing-patterns.md +129 -0
- package/skills/delegation/references/troubleshooting.md +33 -0
- package/skills/delegation/references/workflow-steps.md +127 -0
- package/skills/delegation/references/worktree-enforcement.md +64 -0
- package/skills/dotnet-standards/SKILL.md +269 -0
- package/skills/dotnet-standards/references/csharp-standards.md +120 -0
- package/skills/dotnet-standards/templates/.editorconfig +366 -0
- package/skills/dotnet-standards/templates/Directory.Build.props +56 -0
- package/skills/dotnet-standards/templates/Directory.Packages.props +69 -0
- package/skills/dotnet-standards/templates/global.json +6 -0
- package/skills/dotnet-standards/templates/nuget.config +9 -0
- package/skills/dotnet-standards/templates/stylecop.json +37 -0
- package/skills/git-worktrees/SKILL.md +255 -0
- package/skills/implementation-planning/SKILL.md +233 -0
- package/skills/implementation-planning/references/plan-document-template.md +42 -0
- package/skills/implementation-planning/references/spec-tracing-guide.md +51 -0
- package/skills/implementation-planning/references/task-template.md +43 -0
- package/skills/implementation-planning/references/testing-strategy-guide.md +88 -0
- package/skills/quality-review/SKILL.md +278 -0
- package/skills/quality-review/references/code-quality-checklist.md +159 -0
- package/skills/quality-review/references/review-report-template.md +65 -0
- package/skills/quality-review/references/security-checklist.md +79 -0
- package/skills/quality-review/references/typescript-standards.md +24 -0
- package/skills/refactor/COMMAND.md +67 -0
- package/skills/refactor/SKILL.md +198 -0
- package/skills/refactor/phases/auto-chain.md +262 -0
- package/skills/refactor/phases/brief.md +176 -0
- package/skills/refactor/phases/explore.md +132 -0
- package/skills/refactor/phases/overhaul-delegate.md +136 -0
- package/skills/refactor/phases/overhaul-plan.md +312 -0
- package/skills/refactor/phases/overhaul-review.md +304 -0
- package/skills/refactor/phases/polish-implement.md +349 -0
- package/skills/refactor/phases/polish-validate.md +218 -0
- package/skills/refactor/phases/update-docs.md +234 -0
- package/skills/refactor/references/brief-template.md +81 -0
- package/skills/refactor/references/doc-update-checklist.md +110 -0
- package/skills/refactor/references/explore-checklist.md +73 -0
- package/skills/refactor/references/overhaul-track.md +215 -0
- package/skills/refactor/references/polish-track.md +170 -0
- package/skills/shared/prompts/context-reading.md +58 -0
- package/skills/shared/prompts/report-format.md +54 -0
- package/skills/shared/prompts/tdd-requirements.md +39 -0
- package/skills/shepherd/SKILL.md +264 -0
- package/skills/shepherd/references/assess-checklist.md +124 -0
- package/skills/shepherd/references/fix-strategies.md +191 -0
- package/skills/spec-review/SKILL.md +229 -0
- package/skills/spec-review/references/review-checklist.md +60 -0
- package/skills/sync-schemas/SKILL.md +114 -0
- package/skills/sync-schemas/references/configuration.md +73 -0
- package/skills/synthesis/SKILL.md +129 -0
- package/skills/synthesis/references/pr-descriptions.md +87 -0
- package/skills/synthesis/references/synthesis-steps.md +109 -0
- package/skills/synthesis/references/troubleshooting.md +115 -0
- package/skills/validate-all-skills.sh +57 -0
- package/skills/validate-frontmatter.sh +237 -0
- package/skills/workflow-state/SKILL.md +210 -0
- package/skills/workflow-state/references/mcp-tool-reference.md +111 -0
- 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
|