@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,236 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Static Analysis Gate
|
|
3
|
+
# Runs static analysis tools with structured pass/fail output for the quality-review workflow.
|
|
4
|
+
#
|
|
5
|
+
# Usage: static-analysis-gate.sh --repo-root <path> [--skip-lint] [--skip-typecheck]
|
|
6
|
+
#
|
|
7
|
+
# Exit codes:
|
|
8
|
+
# 0 = all checks pass (warnings OK)
|
|
9
|
+
# 1 = errors found
|
|
10
|
+
# 2 = usage error
|
|
11
|
+
|
|
12
|
+
set -euo pipefail
|
|
13
|
+
|
|
14
|
+
# ============================================================
|
|
15
|
+
# ARGUMENT PARSING
|
|
16
|
+
# ============================================================
|
|
17
|
+
|
|
18
|
+
REPO_ROOT=""
|
|
19
|
+
SKIP_LINT=false
|
|
20
|
+
SKIP_TYPECHECK=false
|
|
21
|
+
|
|
22
|
+
usage() {
|
|
23
|
+
cat << 'USAGE'
|
|
24
|
+
Usage: static-analysis-gate.sh --repo-root <path> [--skip-lint] [--skip-typecheck]
|
|
25
|
+
|
|
26
|
+
Run static analysis tools with structured pass/fail output.
|
|
27
|
+
|
|
28
|
+
Required:
|
|
29
|
+
--repo-root <path> Repository root containing package.json
|
|
30
|
+
|
|
31
|
+
Optional:
|
|
32
|
+
--skip-lint Skip lint check
|
|
33
|
+
--skip-typecheck Skip typecheck
|
|
34
|
+
--help Show this help message
|
|
35
|
+
|
|
36
|
+
Exit codes:
|
|
37
|
+
0 All checks pass (warnings OK)
|
|
38
|
+
1 Errors found in one or more tools
|
|
39
|
+
2 Usage error (missing required args)
|
|
40
|
+
USAGE
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
while [[ $# -gt 0 ]]; do
|
|
44
|
+
case "$1" in
|
|
45
|
+
--repo-root)
|
|
46
|
+
if [[ -z "${2:-}" ]]; then
|
|
47
|
+
echo "Error: --repo-root requires a path argument" >&2
|
|
48
|
+
exit 2
|
|
49
|
+
fi
|
|
50
|
+
REPO_ROOT="$2"
|
|
51
|
+
shift 2
|
|
52
|
+
;;
|
|
53
|
+
--skip-lint)
|
|
54
|
+
SKIP_LINT=true
|
|
55
|
+
shift
|
|
56
|
+
;;
|
|
57
|
+
--skip-typecheck)
|
|
58
|
+
SKIP_TYPECHECK=true
|
|
59
|
+
shift
|
|
60
|
+
;;
|
|
61
|
+
--help)
|
|
62
|
+
usage
|
|
63
|
+
exit 0
|
|
64
|
+
;;
|
|
65
|
+
*)
|
|
66
|
+
echo "Error: Unknown argument '$1'" >&2
|
|
67
|
+
usage >&2
|
|
68
|
+
exit 2
|
|
69
|
+
;;
|
|
70
|
+
esac
|
|
71
|
+
done
|
|
72
|
+
|
|
73
|
+
if [[ -z "$REPO_ROOT" ]]; then
|
|
74
|
+
echo "Error: --repo-root is required" >&2
|
|
75
|
+
usage >&2
|
|
76
|
+
exit 2
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
if [[ ! -f "$REPO_ROOT/package.json" ]]; then
|
|
80
|
+
echo "Error: No package.json found at $REPO_ROOT" >&2
|
|
81
|
+
exit 2
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
# ============================================================
|
|
85
|
+
# CHECK FUNCTIONS
|
|
86
|
+
# ============================================================
|
|
87
|
+
|
|
88
|
+
CHECK_PASS=0
|
|
89
|
+
CHECK_FAIL=0
|
|
90
|
+
RESULTS=()
|
|
91
|
+
|
|
92
|
+
check_pass() {
|
|
93
|
+
local name="$1"
|
|
94
|
+
local detail="${2:-}"
|
|
95
|
+
if [[ -n "$detail" ]]; then
|
|
96
|
+
RESULTS+=("- **PASS**: $name — $detail")
|
|
97
|
+
else
|
|
98
|
+
RESULTS+=("- **PASS**: $name")
|
|
99
|
+
fi
|
|
100
|
+
CHECK_PASS=$((CHECK_PASS + 1))
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
check_fail() {
|
|
104
|
+
local name="$1"
|
|
105
|
+
local detail="${2:-}"
|
|
106
|
+
if [[ -n "$detail" ]]; then
|
|
107
|
+
RESULTS+=("- **FAIL**: $name — $detail")
|
|
108
|
+
else
|
|
109
|
+
RESULTS+=("- **FAIL**: $name")
|
|
110
|
+
fi
|
|
111
|
+
CHECK_FAIL=$((CHECK_FAIL + 1))
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
check_skip() {
|
|
115
|
+
local name="$1"
|
|
116
|
+
local detail="${2:-}"
|
|
117
|
+
if [[ -n "$detail" ]]; then
|
|
118
|
+
RESULTS+=("- **SKIP**: $name — $detail")
|
|
119
|
+
else
|
|
120
|
+
RESULTS+=("- **SKIP**: $name")
|
|
121
|
+
fi
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
# Check if an npm script exists in package.json
|
|
125
|
+
has_npm_script() {
|
|
126
|
+
local script_name="$1"
|
|
127
|
+
node -e '
|
|
128
|
+
const p = require(process.argv[1]);
|
|
129
|
+
const s = p.scripts || {};
|
|
130
|
+
process.exit(s[process.argv[2]] ? 0 : 1);
|
|
131
|
+
' "$REPO_ROOT/package.json" "$script_name" 2>/dev/null
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
# ============================================================
|
|
135
|
+
# CHECK 1: Lint
|
|
136
|
+
# ============================================================
|
|
137
|
+
|
|
138
|
+
run_lint() {
|
|
139
|
+
if [[ "$SKIP_LINT" == true ]]; then
|
|
140
|
+
check_skip "Lint" "--skip-lint"
|
|
141
|
+
return 0
|
|
142
|
+
fi
|
|
143
|
+
|
|
144
|
+
if ! has_npm_script "lint"; then
|
|
145
|
+
check_skip "Lint" "no 'lint' script in package.json"
|
|
146
|
+
return 0
|
|
147
|
+
fi
|
|
148
|
+
|
|
149
|
+
local output
|
|
150
|
+
if output="$(cd "$REPO_ROOT" && npm run lint 2>&1)"; then
|
|
151
|
+
check_pass "Lint"
|
|
152
|
+
return 0
|
|
153
|
+
else
|
|
154
|
+
check_fail "Lint" "npm run lint failed"
|
|
155
|
+
return 1
|
|
156
|
+
fi
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
# ============================================================
|
|
160
|
+
# CHECK 2: Typecheck
|
|
161
|
+
# ============================================================
|
|
162
|
+
|
|
163
|
+
run_typecheck() {
|
|
164
|
+
if [[ "$SKIP_TYPECHECK" == true ]]; then
|
|
165
|
+
check_skip "Typecheck" "--skip-typecheck"
|
|
166
|
+
return 0
|
|
167
|
+
fi
|
|
168
|
+
|
|
169
|
+
if ! has_npm_script "typecheck"; then
|
|
170
|
+
check_skip "Typecheck" "no 'typecheck' script in package.json"
|
|
171
|
+
return 0
|
|
172
|
+
fi
|
|
173
|
+
|
|
174
|
+
local output
|
|
175
|
+
if output="$(cd "$REPO_ROOT" && npm run typecheck 2>&1)"; then
|
|
176
|
+
check_pass "Typecheck"
|
|
177
|
+
return 0
|
|
178
|
+
else
|
|
179
|
+
check_fail "Typecheck" "npm run typecheck failed"
|
|
180
|
+
return 1
|
|
181
|
+
fi
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
# ============================================================
|
|
185
|
+
# CHECK 3: Quality check
|
|
186
|
+
# ============================================================
|
|
187
|
+
|
|
188
|
+
run_quality_check() {
|
|
189
|
+
if ! has_npm_script "quality-check"; then
|
|
190
|
+
check_skip "Quality check" "no 'quality-check' script in package.json"
|
|
191
|
+
return 0
|
|
192
|
+
fi
|
|
193
|
+
|
|
194
|
+
local output
|
|
195
|
+
if output="$(cd "$REPO_ROOT" && npm run quality-check 2>&1)"; then
|
|
196
|
+
check_pass "Quality check"
|
|
197
|
+
return 0
|
|
198
|
+
else
|
|
199
|
+
check_fail "Quality check" "npm run quality-check failed"
|
|
200
|
+
return 1
|
|
201
|
+
fi
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
# ============================================================
|
|
205
|
+
# EXECUTE CHECKS
|
|
206
|
+
# ============================================================
|
|
207
|
+
|
|
208
|
+
run_lint || true
|
|
209
|
+
run_typecheck || true
|
|
210
|
+
run_quality_check || true
|
|
211
|
+
|
|
212
|
+
# ============================================================
|
|
213
|
+
# STRUCTURED OUTPUT
|
|
214
|
+
# ============================================================
|
|
215
|
+
|
|
216
|
+
echo "## Static Analysis Report"
|
|
217
|
+
echo ""
|
|
218
|
+
echo "**Repository:** \`$REPO_ROOT\`"
|
|
219
|
+
echo ""
|
|
220
|
+
|
|
221
|
+
for result in "${RESULTS[@]}"; do
|
|
222
|
+
echo "$result"
|
|
223
|
+
done
|
|
224
|
+
|
|
225
|
+
echo ""
|
|
226
|
+
TOTAL=$((CHECK_PASS + CHECK_FAIL))
|
|
227
|
+
echo "---"
|
|
228
|
+
echo ""
|
|
229
|
+
|
|
230
|
+
if [[ $CHECK_FAIL -eq 0 ]]; then
|
|
231
|
+
echo "**Result: PASS** ($CHECK_PASS/$TOTAL checks passed)"
|
|
232
|
+
exit 0
|
|
233
|
+
else
|
|
234
|
+
echo "**Result: FAIL** ($CHECK_FAIL/$TOTAL checks failed)"
|
|
235
|
+
exit 1
|
|
236
|
+
fi
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# sync-labels.sh - Sync labels from .github/labels.yml to GitHub
|
|
3
|
+
#
|
|
4
|
+
# Usage: ./scripts/sync-labels.sh [--dry-run]
|
|
5
|
+
#
|
|
6
|
+
# Requires: gh (GitHub CLI), python3 with pyyaml
|
|
7
|
+
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
|
|
10
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
|
+
REPO_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
12
|
+
LABELS_FILE="$REPO_ROOT/.github/labels.yml"
|
|
13
|
+
|
|
14
|
+
# Auto-detect repository from git remote, environment, or use default
|
|
15
|
+
if [[ -n "${GITHUB_REPOSITORY:-}" ]]; then
|
|
16
|
+
# Use GitHub Actions environment variable
|
|
17
|
+
REPO="$GITHUB_REPOSITORY"
|
|
18
|
+
elif command -v gh &> /dev/null && gh repo view --json nameWithOwner -q .nameWithOwner &> /dev/null; then
|
|
19
|
+
# Auto-detect from git remote via gh CLI
|
|
20
|
+
REPO="$(gh repo view --json nameWithOwner -q .nameWithOwner)"
|
|
21
|
+
else
|
|
22
|
+
# Fallback to default
|
|
23
|
+
REPO="lvlup-sw/exarchos"
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
# Parse arguments
|
|
27
|
+
DRY_RUN=false
|
|
28
|
+
while [[ $# -gt 0 ]]; do
|
|
29
|
+
case $1 in
|
|
30
|
+
--dry-run) DRY_RUN=true; shift ;;
|
|
31
|
+
-h|--help)
|
|
32
|
+
echo "Usage: $0 [--dry-run]"
|
|
33
|
+
echo ""
|
|
34
|
+
echo "Options:"
|
|
35
|
+
echo " --dry-run Show what would be done without making changes"
|
|
36
|
+
echo " -h, --help Show this help message"
|
|
37
|
+
exit 0
|
|
38
|
+
;;
|
|
39
|
+
*)
|
|
40
|
+
echo "Error: Unknown argument: $1" >&2
|
|
41
|
+
echo "Use --help for usage information" >&2
|
|
42
|
+
exit 1
|
|
43
|
+
;;
|
|
44
|
+
esac
|
|
45
|
+
done
|
|
46
|
+
|
|
47
|
+
# Colors
|
|
48
|
+
RED='\033[0;31m'
|
|
49
|
+
GREEN='\033[0;32m'
|
|
50
|
+
YELLOW='\033[1;33m'
|
|
51
|
+
NC='\033[0m'
|
|
52
|
+
|
|
53
|
+
info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
|
54
|
+
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
55
|
+
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
|
|
56
|
+
|
|
57
|
+
# Check dependencies
|
|
58
|
+
check_deps() {
|
|
59
|
+
if ! command -v gh &> /dev/null; then
|
|
60
|
+
error "gh (GitHub CLI) is required but not installed"
|
|
61
|
+
fi
|
|
62
|
+
if ! python3 -c "import yaml" &> /dev/null; then
|
|
63
|
+
error "Python yaml module is required. Install with: pip install pyyaml"
|
|
64
|
+
fi
|
|
65
|
+
if [[ ! -f "$LABELS_FILE" ]]; then
|
|
66
|
+
error "Labels file not found: $LABELS_FILE"
|
|
67
|
+
fi
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# Delete default GitHub labels we don't use
|
|
71
|
+
delete_default_labels() {
|
|
72
|
+
local defaults=("duplicate" "enhancement" "good first issue" "help wanted" "invalid" "wontfix" "bug" "documentation" "question")
|
|
73
|
+
|
|
74
|
+
info "Removing default labels..."
|
|
75
|
+
for label in "${defaults[@]}"; do
|
|
76
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
77
|
+
echo " [dry-run] Would delete: $label"
|
|
78
|
+
else
|
|
79
|
+
gh label delete "$label" -R "$REPO" --yes 2>/dev/null && \
|
|
80
|
+
echo " Deleted: $label" || \
|
|
81
|
+
echo " Skipped: $label (not found)"
|
|
82
|
+
fi
|
|
83
|
+
done
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
# Create/update labels from config
|
|
87
|
+
sync_labels() {
|
|
88
|
+
info "Syncing labels from $LABELS_FILE..."
|
|
89
|
+
|
|
90
|
+
# Parse YAML and create labels using Python
|
|
91
|
+
python3 -c "import yaml; [print(f\"{l['name']}|{l['color']}|{l['description']}\") for l in yaml.safe_load(open('$LABELS_FILE'))]" | \
|
|
92
|
+
while IFS='|' read -r name color desc; do
|
|
93
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
94
|
+
echo " [dry-run] Would create/update: $name ($color) - $desc"
|
|
95
|
+
else
|
|
96
|
+
gh label create "$name" -R "$REPO" --color "$color" --description "$desc" --force 2>/dev/null && \
|
|
97
|
+
echo " Created/Updated: $name" || \
|
|
98
|
+
echo " Failed: $name"
|
|
99
|
+
fi
|
|
100
|
+
done
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
# Main
|
|
104
|
+
main() {
|
|
105
|
+
echo "Label Sync"
|
|
106
|
+
echo "=========="
|
|
107
|
+
echo ""
|
|
108
|
+
echo "Repository: $REPO"
|
|
109
|
+
echo "Labels file: $LABELS_FILE"
|
|
110
|
+
[[ "$DRY_RUN" == "true" ]] && echo "Mode: DRY RUN"
|
|
111
|
+
echo ""
|
|
112
|
+
|
|
113
|
+
check_deps
|
|
114
|
+
delete_default_labels
|
|
115
|
+
echo ""
|
|
116
|
+
sync_labels
|
|
117
|
+
|
|
118
|
+
echo ""
|
|
119
|
+
info "Label sync complete!"
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
main
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# validate-companion.sh — Validate companion plugin directory structure
|
|
3
|
+
#
|
|
4
|
+
# Checks:
|
|
5
|
+
# 1. companion/.claude-plugin/plugin.json exists and valid JSON with required fields (name, version, mcpServers)
|
|
6
|
+
# 2. companion/.mcp.json exists and valid JSON
|
|
7
|
+
# 3. companion/settings.json exists and valid JSON with enabledPlugins
|
|
8
|
+
#
|
|
9
|
+
# Usage: validate-companion.sh --repo-root <path>
|
|
10
|
+
#
|
|
11
|
+
# Exit codes:
|
|
12
|
+
# 0 = all checks pass
|
|
13
|
+
# 1 = one or more checks fail
|
|
14
|
+
# 2 = usage error
|
|
15
|
+
|
|
16
|
+
set -euo pipefail
|
|
17
|
+
|
|
18
|
+
# ============================================================
|
|
19
|
+
# ARGUMENT PARSING
|
|
20
|
+
# ============================================================
|
|
21
|
+
|
|
22
|
+
REPO_ROOT="."
|
|
23
|
+
|
|
24
|
+
usage() {
|
|
25
|
+
cat << 'USAGE'
|
|
26
|
+
Usage: validate-companion.sh --repo-root <path>
|
|
27
|
+
|
|
28
|
+
Validates the Exarchos companion plugin directory structure.
|
|
29
|
+
|
|
30
|
+
Options:
|
|
31
|
+
--repo-root <path> Path to the repository root (default: .)
|
|
32
|
+
--help Show this help message
|
|
33
|
+
|
|
34
|
+
Exit codes:
|
|
35
|
+
0 All checks pass
|
|
36
|
+
1 One or more checks fail
|
|
37
|
+
2 Usage error
|
|
38
|
+
USAGE
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
while [[ $# -gt 0 ]]; do
|
|
42
|
+
case "$1" in
|
|
43
|
+
--repo-root)
|
|
44
|
+
if [[ -z "${2:-}" ]]; then
|
|
45
|
+
echo "Error: --repo-root requires a path argument" >&2
|
|
46
|
+
exit 2
|
|
47
|
+
fi
|
|
48
|
+
REPO_ROOT="$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 [[ ! -d "$REPO_ROOT" ]]; then
|
|
64
|
+
echo "Error: Repository root not found: $REPO_ROOT" >&2
|
|
65
|
+
exit 2
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
# ============================================================
|
|
69
|
+
# DEPENDENCY CHECK
|
|
70
|
+
# ============================================================
|
|
71
|
+
|
|
72
|
+
if ! command -v jq &>/dev/null; then
|
|
73
|
+
echo "Error: jq is required but not installed" >&2
|
|
74
|
+
exit 2
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# ============================================================
|
|
78
|
+
# VALIDATION
|
|
79
|
+
# ============================================================
|
|
80
|
+
|
|
81
|
+
CHECK_PASS=0
|
|
82
|
+
CHECK_FAIL=0
|
|
83
|
+
TOTAL=0
|
|
84
|
+
RESULTS=()
|
|
85
|
+
|
|
86
|
+
check() {
|
|
87
|
+
local description="$1"
|
|
88
|
+
local passed="$2"
|
|
89
|
+
TOTAL=$((TOTAL + 1))
|
|
90
|
+
if [[ "$passed" == "true" ]]; then
|
|
91
|
+
RESULTS+=("- **PASS**: $description")
|
|
92
|
+
CHECK_PASS=$((CHECK_PASS + 1))
|
|
93
|
+
else
|
|
94
|
+
RESULTS+=("- **FAIL**: $description")
|
|
95
|
+
CHECK_FAIL=$((CHECK_FAIL + 1))
|
|
96
|
+
fi
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
# --- Check 1: companion/.claude-plugin/plugin.json exists and valid JSON with required fields ---
|
|
100
|
+
PLUGIN_JSON="$REPO_ROOT/companion/.claude-plugin/plugin.json"
|
|
101
|
+
if [[ -f "$PLUGIN_JSON" ]] && jq empty "$PLUGIN_JSON" 2>/dev/null; then
|
|
102
|
+
REQUIRED_FIELDS=("name" "version" "mcpServers")
|
|
103
|
+
ALL_FIELDS_PRESENT=true
|
|
104
|
+
MISSING_FIELDS=()
|
|
105
|
+
for field in "${REQUIRED_FIELDS[@]}"; do
|
|
106
|
+
if ! jq -e ".$field" "$PLUGIN_JSON" >/dev/null 2>&1; then
|
|
107
|
+
ALL_FIELDS_PRESENT=false
|
|
108
|
+
MISSING_FIELDS+=("$field")
|
|
109
|
+
fi
|
|
110
|
+
done
|
|
111
|
+
if [[ "$ALL_FIELDS_PRESENT" == "true" ]]; then
|
|
112
|
+
check "companion/.claude-plugin/plugin.json exists and valid" "true"
|
|
113
|
+
else
|
|
114
|
+
check "companion/.claude-plugin/plugin.json missing fields: ${MISSING_FIELDS[*]}" "false"
|
|
115
|
+
fi
|
|
116
|
+
else
|
|
117
|
+
check "companion/.claude-plugin/plugin.json exists and valid" "false"
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
# --- Check 2: companion/.mcp.json exists and valid JSON ---
|
|
121
|
+
MCP_FILE="$REPO_ROOT/companion/.mcp.json"
|
|
122
|
+
if [[ -f "$MCP_FILE" ]] && jq empty "$MCP_FILE" 2>/dev/null; then
|
|
123
|
+
check "companion/.mcp.json exists and valid JSON" "true"
|
|
124
|
+
else
|
|
125
|
+
check "companion/.mcp.json exists and valid JSON" "false"
|
|
126
|
+
fi
|
|
127
|
+
|
|
128
|
+
# --- Check 3: companion/settings.json exists and valid JSON with enabledPlugins ---
|
|
129
|
+
SETTINGS_FILE="$REPO_ROOT/companion/settings.json"
|
|
130
|
+
if [[ -f "$SETTINGS_FILE" ]] && jq empty "$SETTINGS_FILE" 2>/dev/null; then
|
|
131
|
+
if jq -e '.enabledPlugins' "$SETTINGS_FILE" >/dev/null 2>&1; then
|
|
132
|
+
check "companion/settings.json exists and has enabledPlugins" "true"
|
|
133
|
+
else
|
|
134
|
+
check "companion/settings.json missing enabledPlugins field" "false"
|
|
135
|
+
fi
|
|
136
|
+
else
|
|
137
|
+
check "companion/settings.json exists and valid JSON" "false"
|
|
138
|
+
fi
|
|
139
|
+
|
|
140
|
+
# ============================================================
|
|
141
|
+
# STRUCTURED OUTPUT
|
|
142
|
+
# ============================================================
|
|
143
|
+
|
|
144
|
+
echo "## Companion Validation Report"
|
|
145
|
+
echo ""
|
|
146
|
+
|
|
147
|
+
for result in "${RESULTS[@]}"; do
|
|
148
|
+
echo "$result"
|
|
149
|
+
done
|
|
150
|
+
|
|
151
|
+
echo ""
|
|
152
|
+
echo "---"
|
|
153
|
+
echo ""
|
|
154
|
+
|
|
155
|
+
if [[ $CHECK_FAIL -eq 0 ]]; then
|
|
156
|
+
echo "**Result: PASS** ($CHECK_PASS/$TOTAL checks passed)"
|
|
157
|
+
exit 0
|
|
158
|
+
else
|
|
159
|
+
echo "**Result: FAIL** ($CHECK_PASS/$TOTAL checks passed)"
|
|
160
|
+
exit 1
|
|
161
|
+
fi
|