@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,228 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Verify Plan Coverage
|
|
3
|
+
# Cross-reference design document sections to plan tasks. Replaces "Plan Verification" prose.
|
|
4
|
+
#
|
|
5
|
+
# Usage: verify-plan-coverage.sh --design-file <path> --plan-file <path>
|
|
6
|
+
#
|
|
7
|
+
# Exit codes:
|
|
8
|
+
# 0 = complete coverage (every Technical Design subsection maps to >= 1 task)
|
|
9
|
+
# 1 = gaps found (unmapped sections)
|
|
10
|
+
# 2 = usage error (missing required args, empty design, missing files)
|
|
11
|
+
|
|
12
|
+
set -euo pipefail
|
|
13
|
+
|
|
14
|
+
# ============================================================
|
|
15
|
+
# ARGUMENT PARSING
|
|
16
|
+
# ============================================================
|
|
17
|
+
|
|
18
|
+
DESIGN_FILE=""
|
|
19
|
+
PLAN_FILE=""
|
|
20
|
+
|
|
21
|
+
usage() {
|
|
22
|
+
cat << 'USAGE'
|
|
23
|
+
Usage: verify-plan-coverage.sh --design-file <path> --plan-file <path>
|
|
24
|
+
|
|
25
|
+
Required:
|
|
26
|
+
--design-file <path> Path to the design document markdown file
|
|
27
|
+
--plan-file <path> Path to the implementation plan markdown file
|
|
28
|
+
|
|
29
|
+
Optional:
|
|
30
|
+
--help Show this help message
|
|
31
|
+
|
|
32
|
+
Exit codes:
|
|
33
|
+
0 Complete coverage (all Technical Design subsections mapped to tasks)
|
|
34
|
+
1 Gaps found (unmapped design sections)
|
|
35
|
+
2 Usage error (missing required args, empty design, missing files)
|
|
36
|
+
USAGE
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
while [[ $# -gt 0 ]]; do
|
|
40
|
+
case "$1" in
|
|
41
|
+
--design-file)
|
|
42
|
+
if [[ -z "${2:-}" ]]; then
|
|
43
|
+
echo "Error: --design-file requires a path argument" >&2
|
|
44
|
+
exit 2
|
|
45
|
+
fi
|
|
46
|
+
DESIGN_FILE="$2"
|
|
47
|
+
shift 2
|
|
48
|
+
;;
|
|
49
|
+
--plan-file)
|
|
50
|
+
if [[ -z "${2:-}" ]]; then
|
|
51
|
+
echo "Error: --plan-file requires a path argument" >&2
|
|
52
|
+
exit 2
|
|
53
|
+
fi
|
|
54
|
+
PLAN_FILE="$2"
|
|
55
|
+
shift 2
|
|
56
|
+
;;
|
|
57
|
+
--help)
|
|
58
|
+
usage
|
|
59
|
+
exit 0
|
|
60
|
+
;;
|
|
61
|
+
*)
|
|
62
|
+
echo "Error: Unknown argument '$1'" >&2
|
|
63
|
+
usage >&2
|
|
64
|
+
exit 2
|
|
65
|
+
;;
|
|
66
|
+
esac
|
|
67
|
+
done
|
|
68
|
+
|
|
69
|
+
if [[ -z "$DESIGN_FILE" || -z "$PLAN_FILE" ]]; then
|
|
70
|
+
echo "Error: --design-file and --plan-file are required" >&2
|
|
71
|
+
usage >&2
|
|
72
|
+
exit 2
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
if [[ ! -f "$DESIGN_FILE" ]]; then
|
|
76
|
+
echo "Error: Design file not found: $DESIGN_FILE" >&2
|
|
77
|
+
exit 2
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
if [[ ! -f "$PLAN_FILE" ]]; then
|
|
81
|
+
echo "Error: Plan file not found: $PLAN_FILE" >&2
|
|
82
|
+
exit 2
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
# ============================================================
|
|
86
|
+
# EXTRACT DESIGN SECTIONS
|
|
87
|
+
# ============================================================
|
|
88
|
+
|
|
89
|
+
# Extract ### subsections under ## Technical Design
|
|
90
|
+
# We look for "## Technical Design" then collect all ### headers until the next ## header
|
|
91
|
+
DESIGN_SECTIONS=()
|
|
92
|
+
IN_TECH_DESIGN=false
|
|
93
|
+
|
|
94
|
+
while IFS= read -r line; do
|
|
95
|
+
# Detect start of Technical Design section
|
|
96
|
+
if [[ "$line" =~ ^##[[:space:]]+Technical[[:space:]]+Design ]]; then
|
|
97
|
+
IN_TECH_DESIGN=true
|
|
98
|
+
continue
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
# Detect next ## section (end of Technical Design)
|
|
102
|
+
if [[ "$IN_TECH_DESIGN" == true && "$line" =~ ^##[[:space:]] && ! "$line" =~ ^###[[:space:]] ]]; then
|
|
103
|
+
IN_TECH_DESIGN=false
|
|
104
|
+
continue
|
|
105
|
+
fi
|
|
106
|
+
|
|
107
|
+
# Collect ### subsection headers within Technical Design
|
|
108
|
+
if [[ "$IN_TECH_DESIGN" == true && "$line" =~ ^###[[:space:]]+(.+) ]]; then
|
|
109
|
+
section_name="${BASH_REMATCH[1]}"
|
|
110
|
+
# Trim trailing whitespace
|
|
111
|
+
section_name="$(echo "$section_name" | sed 's/[[:space:]]*$//')"
|
|
112
|
+
DESIGN_SECTIONS+=("$section_name")
|
|
113
|
+
fi
|
|
114
|
+
done < "$DESIGN_FILE"
|
|
115
|
+
|
|
116
|
+
# Validate we found sections
|
|
117
|
+
if [[ ${#DESIGN_SECTIONS[@]} -eq 0 ]]; then
|
|
118
|
+
echo "Error: No Technical Design subsections found in design document" >&2
|
|
119
|
+
echo "Expected ### headers under '## Technical Design'" >&2
|
|
120
|
+
exit 2
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
# ============================================================
|
|
124
|
+
# EXTRACT PLAN TASKS
|
|
125
|
+
# ============================================================
|
|
126
|
+
|
|
127
|
+
# Extract ### Task headers from plan
|
|
128
|
+
PLAN_TASKS=()
|
|
129
|
+
while IFS= read -r line; do
|
|
130
|
+
if [[ "$line" =~ ^###[[:space:]]+Task[[:space:]]+[0-9]+ ]]; then
|
|
131
|
+
# Extract the full task title (everything after "### Task NNN: ")
|
|
132
|
+
task_title="${line#*: }"
|
|
133
|
+
if [[ -n "$task_title" && "$task_title" != "$line" ]]; then
|
|
134
|
+
PLAN_TASKS+=("$task_title")
|
|
135
|
+
else
|
|
136
|
+
PLAN_TASKS+=("$line")
|
|
137
|
+
fi
|
|
138
|
+
fi
|
|
139
|
+
done < "$PLAN_FILE"
|
|
140
|
+
|
|
141
|
+
# Also read the full plan content for free-text matching
|
|
142
|
+
PLAN_CONTENT="$(cat "$PLAN_FILE")"
|
|
143
|
+
|
|
144
|
+
# ============================================================
|
|
145
|
+
# CROSS-REFERENCE: Design sections to plan tasks
|
|
146
|
+
# ============================================================
|
|
147
|
+
|
|
148
|
+
CHECK_PASS=0
|
|
149
|
+
CHECK_FAIL=0
|
|
150
|
+
GAPS=()
|
|
151
|
+
MATRIX_ROWS=()
|
|
152
|
+
|
|
153
|
+
for section in "${DESIGN_SECTIONS[@]}"; do
|
|
154
|
+
# Check if any task title or plan content references this design section
|
|
155
|
+
MATCHED_TASKS=()
|
|
156
|
+
|
|
157
|
+
for task in "${PLAN_TASKS[@]}"; do
|
|
158
|
+
# Case-insensitive substring match
|
|
159
|
+
if echo "$task" | grep -qiF "$section"; then
|
|
160
|
+
MATCHED_TASKS+=("$task")
|
|
161
|
+
fi
|
|
162
|
+
done
|
|
163
|
+
|
|
164
|
+
# If no task title matches, check the full plan content for the section name
|
|
165
|
+
if [[ ${#MATCHED_TASKS[@]} -eq 0 ]]; then
|
|
166
|
+
if echo "$PLAN_CONTENT" | grep -qiF "$section"; then
|
|
167
|
+
MATCHED_TASKS+=("(referenced in plan body)")
|
|
168
|
+
fi
|
|
169
|
+
fi
|
|
170
|
+
|
|
171
|
+
if [[ ${#MATCHED_TASKS[@]} -gt 0 ]]; then
|
|
172
|
+
task_list="$(printf '%s, ' "${MATCHED_TASKS[@]}")"
|
|
173
|
+
task_list="${task_list%, }"
|
|
174
|
+
MATRIX_ROWS+=("| $section | $task_list | Covered |")
|
|
175
|
+
CHECK_PASS=$((CHECK_PASS + 1))
|
|
176
|
+
else
|
|
177
|
+
MATRIX_ROWS+=("| $section | — | **GAP** |")
|
|
178
|
+
GAPS+=("$section")
|
|
179
|
+
CHECK_FAIL=$((CHECK_FAIL + 1))
|
|
180
|
+
fi
|
|
181
|
+
done
|
|
182
|
+
|
|
183
|
+
# ============================================================
|
|
184
|
+
# STRUCTURED OUTPUT
|
|
185
|
+
# ============================================================
|
|
186
|
+
|
|
187
|
+
echo "## Plan Coverage Report"
|
|
188
|
+
echo ""
|
|
189
|
+
echo "**Design file:** \`$DESIGN_FILE\`"
|
|
190
|
+
echo "**Plan file:** \`$PLAN_FILE\`"
|
|
191
|
+
echo ""
|
|
192
|
+
|
|
193
|
+
echo "### Coverage Matrix"
|
|
194
|
+
echo ""
|
|
195
|
+
echo "| Design Section | Task(s) | Status |"
|
|
196
|
+
echo "|----------------|---------|--------|"
|
|
197
|
+
for row in "${MATRIX_ROWS[@]}"; do
|
|
198
|
+
echo "$row"
|
|
199
|
+
done
|
|
200
|
+
echo ""
|
|
201
|
+
|
|
202
|
+
TOTAL=$((CHECK_PASS + CHECK_FAIL))
|
|
203
|
+
echo "### Summary"
|
|
204
|
+
echo ""
|
|
205
|
+
echo "- Design sections: $TOTAL"
|
|
206
|
+
echo "- Covered: $CHECK_PASS"
|
|
207
|
+
echo "- Gaps: $CHECK_FAIL"
|
|
208
|
+
echo ""
|
|
209
|
+
|
|
210
|
+
if [[ ${#GAPS[@]} -gt 0 ]]; then
|
|
211
|
+
echo "### Unmapped Sections"
|
|
212
|
+
echo ""
|
|
213
|
+
for gap in "${GAPS[@]}"; do
|
|
214
|
+
echo "- **$gap** — No task maps to this design section"
|
|
215
|
+
done
|
|
216
|
+
echo ""
|
|
217
|
+
fi
|
|
218
|
+
|
|
219
|
+
echo "---"
|
|
220
|
+
echo ""
|
|
221
|
+
|
|
222
|
+
if [[ $CHECK_FAIL -eq 0 ]]; then
|
|
223
|
+
echo "**Result: PASS** (${CHECK_PASS}/${TOTAL} sections covered)"
|
|
224
|
+
exit 0
|
|
225
|
+
else
|
|
226
|
+
echo "**Result: FAIL** (${CHECK_FAIL}/${TOTAL} sections have gaps)"
|
|
227
|
+
exit 1
|
|
228
|
+
fi
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# verify-review-triage.sh
|
|
3
|
+
# Verifies review triage was applied correctly to a stack of PRs.
|
|
4
|
+
#
|
|
5
|
+
# Usage: verify-review-triage.sh --state-file <path> --event-stream <path>
|
|
6
|
+
#
|
|
7
|
+
# Checks:
|
|
8
|
+
# 1. All PRs in state file have a review.routed event in the event stream
|
|
9
|
+
# 2. High-risk PRs (riskScore >= 0.4) were sent to CodeRabbit
|
|
10
|
+
# 3. Self-hosted review ran for all PRs (destination is "self-hosted" or "both")
|
|
11
|
+
# 4. No PR is missing review routing
|
|
12
|
+
#
|
|
13
|
+
# Exit codes:
|
|
14
|
+
# 0 All checks pass
|
|
15
|
+
# 1 Verification failed (details in output)
|
|
16
|
+
# 2 Usage error
|
|
17
|
+
|
|
18
|
+
set -euo pipefail
|
|
19
|
+
|
|
20
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
21
|
+
|
|
22
|
+
# Colors
|
|
23
|
+
RED='\033[0;31m'
|
|
24
|
+
GREEN='\033[0;32m'
|
|
25
|
+
YELLOW='\033[1;33m'
|
|
26
|
+
NC='\033[0m'
|
|
27
|
+
|
|
28
|
+
# ============================================================
|
|
29
|
+
# USAGE
|
|
30
|
+
# ============================================================
|
|
31
|
+
|
|
32
|
+
usage() {
|
|
33
|
+
cat <<'EOF'
|
|
34
|
+
Usage: verify-review-triage.sh --state-file <path> --event-stream <path>
|
|
35
|
+
|
|
36
|
+
Verifies review triage was applied correctly to a stack of PRs.
|
|
37
|
+
|
|
38
|
+
Options:
|
|
39
|
+
--state-file <path> Path to workflow state JSON file (required)
|
|
40
|
+
--event-stream <path> Path to event stream JSONL file (required)
|
|
41
|
+
--help Show this help message
|
|
42
|
+
|
|
43
|
+
Checks:
|
|
44
|
+
1. All PRs have a review.routed event
|
|
45
|
+
2. High-risk PRs (score >= 0.4) sent to CodeRabbit
|
|
46
|
+
3. Self-hosted review ran for all PRs
|
|
47
|
+
4. No PR missing review routing
|
|
48
|
+
|
|
49
|
+
Exit codes:
|
|
50
|
+
0 All checks pass
|
|
51
|
+
1 Verification failed (details in output)
|
|
52
|
+
2 Usage error (missing required arguments)
|
|
53
|
+
EOF
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
# ============================================================
|
|
57
|
+
# ARGUMENT PARSING
|
|
58
|
+
# ============================================================
|
|
59
|
+
|
|
60
|
+
STATE_FILE=""
|
|
61
|
+
EVENT_STREAM=""
|
|
62
|
+
|
|
63
|
+
while [[ $# -gt 0 ]]; do
|
|
64
|
+
case "$1" in
|
|
65
|
+
--state-file)
|
|
66
|
+
if [[ $# -lt 2 ]]; then
|
|
67
|
+
echo -e "${RED}ERROR${NC}: --state-file requires a value" >&2
|
|
68
|
+
exit 2
|
|
69
|
+
fi
|
|
70
|
+
STATE_FILE="$2"
|
|
71
|
+
shift 2
|
|
72
|
+
;;
|
|
73
|
+
--event-stream)
|
|
74
|
+
if [[ $# -lt 2 ]]; then
|
|
75
|
+
echo -e "${RED}ERROR${NC}: --event-stream requires a value" >&2
|
|
76
|
+
exit 2
|
|
77
|
+
fi
|
|
78
|
+
EVENT_STREAM="$2"
|
|
79
|
+
shift 2
|
|
80
|
+
;;
|
|
81
|
+
--help)
|
|
82
|
+
usage
|
|
83
|
+
exit 0
|
|
84
|
+
;;
|
|
85
|
+
-*)
|
|
86
|
+
echo -e "${RED}ERROR${NC}: Unknown option: $1" >&2
|
|
87
|
+
usage >&2
|
|
88
|
+
exit 2
|
|
89
|
+
;;
|
|
90
|
+
*)
|
|
91
|
+
echo -e "${RED}ERROR${NC}: Unexpected argument: $1" >&2
|
|
92
|
+
usage >&2
|
|
93
|
+
exit 2
|
|
94
|
+
;;
|
|
95
|
+
esac
|
|
96
|
+
done
|
|
97
|
+
|
|
98
|
+
# ============================================================
|
|
99
|
+
# VALIDATION
|
|
100
|
+
# ============================================================
|
|
101
|
+
|
|
102
|
+
if [[ -z "$STATE_FILE" ]]; then
|
|
103
|
+
echo -e "${RED}ERROR${NC}: --state-file is required" >&2
|
|
104
|
+
usage >&2
|
|
105
|
+
exit 2
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
if [[ ! -f "$STATE_FILE" ]]; then
|
|
109
|
+
echo -e "${RED}ERROR${NC}: State file not found: $STATE_FILE" >&2
|
|
110
|
+
exit 2
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
if [[ -z "$EVENT_STREAM" ]]; then
|
|
114
|
+
echo -e "${RED}ERROR${NC}: --event-stream is required" >&2
|
|
115
|
+
usage >&2
|
|
116
|
+
exit 2
|
|
117
|
+
fi
|
|
118
|
+
|
|
119
|
+
if [[ ! -f "$EVENT_STREAM" ]]; then
|
|
120
|
+
echo -e "${RED}ERROR${NC}: Event stream file not found: $EVENT_STREAM" >&2
|
|
121
|
+
exit 2
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
# ============================================================
|
|
125
|
+
# DEPENDENCY CHECKS
|
|
126
|
+
# ============================================================
|
|
127
|
+
|
|
128
|
+
if ! command -v jq &> /dev/null; then
|
|
129
|
+
echo -e "${RED}ERROR${NC}: jq is not installed" >&2
|
|
130
|
+
exit 1
|
|
131
|
+
fi
|
|
132
|
+
|
|
133
|
+
# ============================================================
|
|
134
|
+
# VERIFICATION LOGIC
|
|
135
|
+
# ============================================================
|
|
136
|
+
|
|
137
|
+
HAS_FAILURE=false
|
|
138
|
+
CHECKS_PASSED=0
|
|
139
|
+
CHECKS_FAILED=0
|
|
140
|
+
REPORT_LINES=()
|
|
141
|
+
|
|
142
|
+
report_pass() {
|
|
143
|
+
local msg="$1"
|
|
144
|
+
REPORT_LINES+=("| PASS | $msg |")
|
|
145
|
+
CHECKS_PASSED=$((CHECKS_PASSED + 1))
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
report_fail() {
|
|
149
|
+
local msg="$1"
|
|
150
|
+
REPORT_LINES+=("| FAIL | $msg |")
|
|
151
|
+
CHECKS_FAILED=$((CHECKS_FAILED + 1))
|
|
152
|
+
HAS_FAILURE=true
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
# Extract PR numbers from state file
|
|
156
|
+
PR_NUMBERS=$(jq -r '.prs[].number' "$STATE_FILE" 2>/dev/null)
|
|
157
|
+
if [[ -z "$PR_NUMBERS" ]]; then
|
|
158
|
+
echo -e "${RED}ERROR${NC}: No PRs found in state file" >&2
|
|
159
|
+
exit 1
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
# Build a lookup of review.routed events from the event stream (one per line JSONL)
|
|
163
|
+
# Parse each line that is a review.routed event
|
|
164
|
+
for pr in $PR_NUMBERS; do
|
|
165
|
+
# Check 1: review.routed event exists for this PR
|
|
166
|
+
ROUTED_EVENT=$(jq -c "select(.type == \"review.routed\" and .data.pr == $pr)" "$EVENT_STREAM" 2>/dev/null | tail -1)
|
|
167
|
+
|
|
168
|
+
if [[ -z "$ROUTED_EVENT" ]]; then
|
|
169
|
+
report_fail "PR #$pr: missing review.routed event"
|
|
170
|
+
continue
|
|
171
|
+
fi
|
|
172
|
+
|
|
173
|
+
report_pass "PR #$pr: review.routed event exists"
|
|
174
|
+
|
|
175
|
+
# Check 2: High-risk PRs (riskScore >= 0.4) sent to CodeRabbit
|
|
176
|
+
RISK_SCORE=$(echo "$ROUTED_EVENT" | jq -r '.data.riskScore // 0')
|
|
177
|
+
IS_HIGH_RISK=$(echo "$RISK_SCORE" | jq -Rr 'tonumber >= 0.4')
|
|
178
|
+
|
|
179
|
+
if [[ "$IS_HIGH_RISK" == "true" ]]; then
|
|
180
|
+
HAS_CODERABBIT=$(echo "$ROUTED_EVENT" | jq -r '.data.destination == "coderabbit" or .data.destination == "both"')
|
|
181
|
+
if [[ "$HAS_CODERABBIT" == "true" ]]; then
|
|
182
|
+
report_pass "PR #$pr: high-risk (score=$RISK_SCORE) sent to CodeRabbit"
|
|
183
|
+
else
|
|
184
|
+
report_fail "PR #$pr: high-risk (score=$RISK_SCORE) NOT sent to CodeRabbit"
|
|
185
|
+
fi
|
|
186
|
+
fi
|
|
187
|
+
|
|
188
|
+
# Check 3: Self-hosted review ran for all PRs
|
|
189
|
+
SELF_HOSTED=$(echo "$ROUTED_EVENT" | jq -r '.data.destination == "self-hosted" or .data.destination == "both"')
|
|
190
|
+
if [[ "$SELF_HOSTED" == "true" ]]; then
|
|
191
|
+
report_pass "PR #$pr: self-hosted review enabled"
|
|
192
|
+
else
|
|
193
|
+
report_fail "PR #$pr: self-hosted review NOT enabled"
|
|
194
|
+
fi
|
|
195
|
+
done
|
|
196
|
+
|
|
197
|
+
# ============================================================
|
|
198
|
+
# OUTPUT REPORT
|
|
199
|
+
# ============================================================
|
|
200
|
+
|
|
201
|
+
echo "## Review Triage Verification"
|
|
202
|
+
echo ""
|
|
203
|
+
echo "| Status | Check |"
|
|
204
|
+
echo "|--------|-------|"
|
|
205
|
+
for line in "${REPORT_LINES[@]}"; do
|
|
206
|
+
echo "$line"
|
|
207
|
+
done
|
|
208
|
+
echo ""
|
|
209
|
+
echo "**Passed:** $CHECKS_PASSED | **Failed:** $CHECKS_FAILED"
|
|
210
|
+
|
|
211
|
+
# ============================================================
|
|
212
|
+
# EXIT CODE
|
|
213
|
+
# ============================================================
|
|
214
|
+
|
|
215
|
+
if [[ "$HAS_FAILURE" == true ]]; then
|
|
216
|
+
exit 1
|
|
217
|
+
else
|
|
218
|
+
exit 0
|
|
219
|
+
fi
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# verify-worktree-baseline.sh — Run baseline tests in a worktree before dispatch
|
|
3
|
+
# Usage: verify-worktree-baseline.sh --worktree-path <path> [--help]
|
|
4
|
+
# Exit codes: 0=baseline pass, 1=baseline fail, 2=project type unknown or usage error
|
|
5
|
+
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
9
|
+
|
|
10
|
+
# ============================================================
|
|
11
|
+
# ARGUMENT PARSING
|
|
12
|
+
# ============================================================
|
|
13
|
+
|
|
14
|
+
WORKTREE_PATH=""
|
|
15
|
+
|
|
16
|
+
usage() {
|
|
17
|
+
cat << 'USAGE'
|
|
18
|
+
Usage: verify-worktree-baseline.sh --worktree-path <path> [--help]
|
|
19
|
+
|
|
20
|
+
Run baseline tests in a worktree to verify it is ready for implementation.
|
|
21
|
+
Auto-detects project type and runs the appropriate test command.
|
|
22
|
+
|
|
23
|
+
Required:
|
|
24
|
+
--worktree-path <path> Path to the worktree directory
|
|
25
|
+
|
|
26
|
+
Optional:
|
|
27
|
+
--help Show this help message
|
|
28
|
+
|
|
29
|
+
Supported project types:
|
|
30
|
+
Node.js package.json → npm run test:run
|
|
31
|
+
.NET *.csproj → dotnet test
|
|
32
|
+
Rust Cargo.toml → cargo test
|
|
33
|
+
|
|
34
|
+
Exit codes:
|
|
35
|
+
0 Baseline tests pass — worktree is ready
|
|
36
|
+
1 Baseline tests failed — investigate before proceeding
|
|
37
|
+
2 Unknown project type or usage error
|
|
38
|
+
USAGE
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
while [[ $# -gt 0 ]]; do
|
|
42
|
+
case "$1" in
|
|
43
|
+
--worktree-path)
|
|
44
|
+
if [[ -z "${2:-}" ]]; then
|
|
45
|
+
echo "Error: --worktree-path requires a path argument" >&2
|
|
46
|
+
exit 2
|
|
47
|
+
fi
|
|
48
|
+
WORKTREE_PATH="$2"
|
|
49
|
+
shift 2
|
|
50
|
+
;;
|
|
51
|
+
--help)
|
|
52
|
+
usage
|
|
53
|
+
exit 0
|
|
54
|
+
;;
|
|
55
|
+
*)
|
|
56
|
+
echo "Error: Unknown argument '$1'" >&2
|
|
57
|
+
usage >&2
|
|
58
|
+
exit 2
|
|
59
|
+
;;
|
|
60
|
+
esac
|
|
61
|
+
done
|
|
62
|
+
|
|
63
|
+
if [[ -z "$WORKTREE_PATH" ]]; then
|
|
64
|
+
echo "Error: --worktree-path is required" >&2
|
|
65
|
+
usage >&2
|
|
66
|
+
exit 2
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
if [[ ! -d "$WORKTREE_PATH" ]]; then
|
|
70
|
+
echo "Error: Worktree path does not exist: $WORKTREE_PATH" >&2
|
|
71
|
+
exit 2
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
# Verify it's actually a git worktree
|
|
75
|
+
if ! git -C "$WORKTREE_PATH" rev-parse --git-dir > /dev/null 2>&1; then
|
|
76
|
+
echo "Error: Not a git worktree: $WORKTREE_PATH" >&2
|
|
77
|
+
exit 2
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
# ============================================================
|
|
81
|
+
# PROJECT TYPE DETECTION
|
|
82
|
+
# ============================================================
|
|
83
|
+
|
|
84
|
+
PROJECT_TYPE=""
|
|
85
|
+
TEST_CMD=""
|
|
86
|
+
|
|
87
|
+
detect_project_type() {
|
|
88
|
+
if [[ -f "$WORKTREE_PATH/package.json" ]]; then
|
|
89
|
+
PROJECT_TYPE="Node.js"
|
|
90
|
+
TEST_CMD="npm run test:run"
|
|
91
|
+
elif ls "$WORKTREE_PATH"/*.csproj 1>/dev/null 2>&1; then
|
|
92
|
+
PROJECT_TYPE=".NET"
|
|
93
|
+
TEST_CMD="dotnet test"
|
|
94
|
+
elif [[ -f "$WORKTREE_PATH/Cargo.toml" ]]; then
|
|
95
|
+
PROJECT_TYPE="Rust"
|
|
96
|
+
TEST_CMD="cargo test"
|
|
97
|
+
fi
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
detect_project_type
|
|
101
|
+
|
|
102
|
+
# ============================================================
|
|
103
|
+
# RUN BASELINE TESTS
|
|
104
|
+
# ============================================================
|
|
105
|
+
|
|
106
|
+
TEST_OUTPUT=""
|
|
107
|
+
TEST_EXIT=0
|
|
108
|
+
|
|
109
|
+
if [[ -z "$PROJECT_TYPE" ]]; then
|
|
110
|
+
echo "## Baseline Verification Report"
|
|
111
|
+
echo ""
|
|
112
|
+
echo "**Worktree:** \`$WORKTREE_PATH\`"
|
|
113
|
+
echo "**Project type detected:** Unknown"
|
|
114
|
+
echo ""
|
|
115
|
+
echo "No recognized project files found (package.json, *.csproj, Cargo.toml)."
|
|
116
|
+
echo "Manual verification required."
|
|
117
|
+
echo ""
|
|
118
|
+
echo "---"
|
|
119
|
+
echo ""
|
|
120
|
+
echo "**Result: UNKNOWN** — could not detect project type"
|
|
121
|
+
exit 2
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
TEST_OUTPUT="$(cd "$WORKTREE_PATH" && $TEST_CMD 2>&1)" && TEST_EXIT=0 || TEST_EXIT=$?
|
|
125
|
+
|
|
126
|
+
# ============================================================
|
|
127
|
+
# STRUCTURED MARKDOWN OUTPUT
|
|
128
|
+
# ============================================================
|
|
129
|
+
|
|
130
|
+
echo "## Baseline Verification Report"
|
|
131
|
+
echo ""
|
|
132
|
+
echo "**Worktree:** \`$WORKTREE_PATH\`"
|
|
133
|
+
echo "**Project type detected:** $PROJECT_TYPE"
|
|
134
|
+
echo "**Test command:** \`$TEST_CMD\`"
|
|
135
|
+
echo ""
|
|
136
|
+
|
|
137
|
+
if [[ $TEST_EXIT -eq 0 ]]; then
|
|
138
|
+
echo "### Test Output"
|
|
139
|
+
echo ""
|
|
140
|
+
echo '```'
|
|
141
|
+
echo "$TEST_OUTPUT"
|
|
142
|
+
echo '```'
|
|
143
|
+
echo ""
|
|
144
|
+
echo "---"
|
|
145
|
+
echo ""
|
|
146
|
+
echo "**Result: PASS** — baseline tests succeeded"
|
|
147
|
+
exit 0
|
|
148
|
+
else
|
|
149
|
+
echo "### Test Output"
|
|
150
|
+
echo ""
|
|
151
|
+
echo '```'
|
|
152
|
+
echo "$TEST_OUTPUT"
|
|
153
|
+
echo '```'
|
|
154
|
+
echo ""
|
|
155
|
+
echo "---"
|
|
156
|
+
echo ""
|
|
157
|
+
echo "**Result: FAIL** — baseline tests failed (exit code $TEST_EXIT)"
|
|
158
|
+
exit 1
|
|
159
|
+
fi
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# verify-worktree.sh — Verify execution is inside a git worktree
|
|
3
|
+
# Usage: verify-worktree.sh [--cwd <path>] [--help]
|
|
4
|
+
# Exit codes: 0=in worktree, 1=not in worktree, 2=usage error
|
|
5
|
+
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
9
|
+
|
|
10
|
+
# Colors
|
|
11
|
+
RED='\033[0;31m'
|
|
12
|
+
GREEN='\033[0;32m'
|
|
13
|
+
NC='\033[0m'
|
|
14
|
+
|
|
15
|
+
# ============================================================
|
|
16
|
+
# ARGUMENT PARSING
|
|
17
|
+
# ============================================================
|
|
18
|
+
|
|
19
|
+
CWD=""
|
|
20
|
+
|
|
21
|
+
usage() {
|
|
22
|
+
cat << 'USAGE'
|
|
23
|
+
Usage: verify-worktree.sh [--cwd <path>] [--help]
|
|
24
|
+
|
|
25
|
+
Verify that the current (or provided) working directory is inside a git worktree.
|
|
26
|
+
|
|
27
|
+
Optional:
|
|
28
|
+
--cwd <path> Directory to check (default: current working directory)
|
|
29
|
+
--help Show this help message
|
|
30
|
+
|
|
31
|
+
Exit codes:
|
|
32
|
+
0 In a valid worktree (path contains .worktrees/)
|
|
33
|
+
1 Not in a worktree
|
|
34
|
+
2 Usage error
|
|
35
|
+
USAGE
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
while [[ $# -gt 0 ]]; do
|
|
39
|
+
case "$1" in
|
|
40
|
+
--cwd)
|
|
41
|
+
if [[ -z "${2:-}" ]]; then
|
|
42
|
+
echo "Error: --cwd requires a path argument" >&2
|
|
43
|
+
exit 2
|
|
44
|
+
fi
|
|
45
|
+
CWD="$2"
|
|
46
|
+
shift 2
|
|
47
|
+
;;
|
|
48
|
+
--help)
|
|
49
|
+
usage
|
|
50
|
+
exit 0
|
|
51
|
+
;;
|
|
52
|
+
*)
|
|
53
|
+
echo "Error: Unknown argument '$1'" >&2
|
|
54
|
+
usage >&2
|
|
55
|
+
exit 2
|
|
56
|
+
;;
|
|
57
|
+
esac
|
|
58
|
+
done
|
|
59
|
+
|
|
60
|
+
# Default to current working directory if --cwd not provided
|
|
61
|
+
if [[ -z "$CWD" ]]; then
|
|
62
|
+
CWD="$(pwd)"
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
# Validate path exists and normalize to absolute
|
|
66
|
+
if [[ ! -d "$CWD" ]]; then
|
|
67
|
+
echo "Error: Directory does not exist: $CWD" >&2
|
|
68
|
+
exit 2
|
|
69
|
+
fi
|
|
70
|
+
CWD="$(cd "$CWD" && pwd)"
|
|
71
|
+
|
|
72
|
+
# ============================================================
|
|
73
|
+
# WORKTREE CHECK
|
|
74
|
+
# ============================================================
|
|
75
|
+
|
|
76
|
+
if [[ "$CWD" =~ \.worktrees/ ]]; then
|
|
77
|
+
echo -e "${GREEN}OK:${NC} Working in worktree at ${CWD}"
|
|
78
|
+
exit 0
|
|
79
|
+
else
|
|
80
|
+
echo -e "${RED}ERROR:${NC} Not in a worktree! Current directory: ${CWD}"
|
|
81
|
+
echo "Expected: path containing '.worktrees/'"
|
|
82
|
+
echo "ABORTING — DO NOT proceed with file modifications"
|
|
83
|
+
exit 1
|
|
84
|
+
fi
|