@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,211 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Verify Doc Links
|
|
3
|
+
# Checks that internal markdown links resolve to existing files.
|
|
4
|
+
# Replaces manual documentation link verification with deterministic validation.
|
|
5
|
+
#
|
|
6
|
+
# Usage: verify-doc-links.sh --doc-file <path> | --docs-dir <path>
|
|
7
|
+
#
|
|
8
|
+
# Exit codes:
|
|
9
|
+
# 0 = all links valid
|
|
10
|
+
# 1 = broken links found
|
|
11
|
+
# 2 = usage error (missing required args)
|
|
12
|
+
|
|
13
|
+
set -euo pipefail
|
|
14
|
+
|
|
15
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
16
|
+
|
|
17
|
+
# Colors
|
|
18
|
+
RED='\033[0;31m'
|
|
19
|
+
GREEN='\033[0;32m'
|
|
20
|
+
YELLOW='\033[1;33m'
|
|
21
|
+
NC='\033[0m'
|
|
22
|
+
|
|
23
|
+
# ============================================================
|
|
24
|
+
# ARGUMENT PARSING
|
|
25
|
+
# ============================================================
|
|
26
|
+
|
|
27
|
+
DOC_FILE=""
|
|
28
|
+
DOCS_DIR=""
|
|
29
|
+
|
|
30
|
+
usage() {
|
|
31
|
+
cat << 'USAGE'
|
|
32
|
+
Usage: verify-doc-links.sh --doc-file <path> | --docs-dir <path>
|
|
33
|
+
|
|
34
|
+
Required (one of):
|
|
35
|
+
--doc-file <path> Single markdown file to check
|
|
36
|
+
--docs-dir <path> Directory to check recursively (all .md files)
|
|
37
|
+
|
|
38
|
+
Optional:
|
|
39
|
+
--help Show this help message
|
|
40
|
+
|
|
41
|
+
Exit codes:
|
|
42
|
+
0 All internal links resolve to existing files
|
|
43
|
+
1 One or more broken links found
|
|
44
|
+
2 Usage error (missing required args)
|
|
45
|
+
|
|
46
|
+
Notes:
|
|
47
|
+
- External URLs (http://, https://) are skipped
|
|
48
|
+
- Anchor-only links (#section) are skipped
|
|
49
|
+
- Links with anchors (file.md#section) check the file part only
|
|
50
|
+
USAGE
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
while [[ $# -gt 0 ]]; do
|
|
54
|
+
case "$1" in
|
|
55
|
+
--doc-file)
|
|
56
|
+
if [[ -z "${2:-}" ]]; then
|
|
57
|
+
echo "Error: --doc-file requires a path argument" >&2
|
|
58
|
+
exit 2
|
|
59
|
+
fi
|
|
60
|
+
DOC_FILE="$2"
|
|
61
|
+
shift 2
|
|
62
|
+
;;
|
|
63
|
+
--docs-dir)
|
|
64
|
+
if [[ -z "${2:-}" ]]; then
|
|
65
|
+
echo "Error: --docs-dir requires a path argument" >&2
|
|
66
|
+
exit 2
|
|
67
|
+
fi
|
|
68
|
+
DOCS_DIR="$2"
|
|
69
|
+
shift 2
|
|
70
|
+
;;
|
|
71
|
+
--help)
|
|
72
|
+
usage
|
|
73
|
+
exit 0
|
|
74
|
+
;;
|
|
75
|
+
*)
|
|
76
|
+
echo "Error: Unknown argument '$1'" >&2
|
|
77
|
+
usage >&2
|
|
78
|
+
exit 2
|
|
79
|
+
;;
|
|
80
|
+
esac
|
|
81
|
+
done
|
|
82
|
+
|
|
83
|
+
if [[ -z "$DOC_FILE" && -z "$DOCS_DIR" ]]; then
|
|
84
|
+
echo "Error: --doc-file or --docs-dir is required" >&2
|
|
85
|
+
usage >&2
|
|
86
|
+
exit 2
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# ============================================================
|
|
90
|
+
# LINK CHECKING
|
|
91
|
+
# ============================================================
|
|
92
|
+
|
|
93
|
+
BROKEN_COUNT=0
|
|
94
|
+
CHECKED_COUNT=0
|
|
95
|
+
SKIPPED_COUNT=0
|
|
96
|
+
BROKEN_LINKS=()
|
|
97
|
+
|
|
98
|
+
check_file() {
|
|
99
|
+
local file="$1"
|
|
100
|
+
local file_dir
|
|
101
|
+
file_dir="$(dirname "$file")"
|
|
102
|
+
local line_num=0
|
|
103
|
+
|
|
104
|
+
while IFS= read -r line; do
|
|
105
|
+
line_num=$((line_num + 1))
|
|
106
|
+
|
|
107
|
+
# Extract markdown links: [text](target)
|
|
108
|
+
# Use grep to find all link targets on this line
|
|
109
|
+
while IFS= read -r target; do
|
|
110
|
+
[[ -z "$target" ]] && continue
|
|
111
|
+
|
|
112
|
+
# Skip external URLs
|
|
113
|
+
if [[ "$target" == http://* || "$target" == https://* ]]; then
|
|
114
|
+
SKIPPED_COUNT=$((SKIPPED_COUNT + 1))
|
|
115
|
+
continue
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
# Skip anchor-only links
|
|
119
|
+
if [[ "$target" == \#* ]]; then
|
|
120
|
+
SKIPPED_COUNT=$((SKIPPED_COUNT + 1))
|
|
121
|
+
continue
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
# Strip anchor from target (file.md#section -> file.md)
|
|
125
|
+
local file_target="${target%%#*}"
|
|
126
|
+
|
|
127
|
+
# Skip if empty after stripping anchor
|
|
128
|
+
if [[ -z "$file_target" ]]; then
|
|
129
|
+
SKIPPED_COUNT=$((SKIPPED_COUNT + 1))
|
|
130
|
+
continue
|
|
131
|
+
fi
|
|
132
|
+
|
|
133
|
+
CHECKED_COUNT=$((CHECKED_COUNT + 1))
|
|
134
|
+
|
|
135
|
+
# Resolve relative to the file's directory (or use as-is if absolute)
|
|
136
|
+
local resolved_path
|
|
137
|
+
if [[ "$file_target" == /* ]]; then
|
|
138
|
+
resolved_path="$file_target"
|
|
139
|
+
else
|
|
140
|
+
resolved_path="$file_dir/$file_target"
|
|
141
|
+
fi
|
|
142
|
+
|
|
143
|
+
if [[ ! -e "$resolved_path" ]]; then
|
|
144
|
+
BROKEN_COUNT=$((BROKEN_COUNT + 1))
|
|
145
|
+
BROKEN_LINKS+=("$file:$line_num -> $target (resolved: $resolved_path)")
|
|
146
|
+
fi
|
|
147
|
+
done < <(echo "$line" | grep -oE '\[[^]]*\]\([^)]+\)' | sed -E 's/\[[^]]*\]\(([^)]+)\)/\1/g' || true)
|
|
148
|
+
done < "$file"
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
# ============================================================
|
|
152
|
+
# COLLECT FILES TO CHECK
|
|
153
|
+
# ============================================================
|
|
154
|
+
|
|
155
|
+
FILES_TO_CHECK=()
|
|
156
|
+
|
|
157
|
+
if [[ -n "$DOC_FILE" ]]; then
|
|
158
|
+
if [[ ! -f "$DOC_FILE" ]]; then
|
|
159
|
+
echo "Error: File not found: $DOC_FILE" >&2
|
|
160
|
+
exit 2
|
|
161
|
+
fi
|
|
162
|
+
FILES_TO_CHECK+=("$DOC_FILE")
|
|
163
|
+
elif [[ -n "$DOCS_DIR" ]]; then
|
|
164
|
+
if [[ ! -d "$DOCS_DIR" ]]; then
|
|
165
|
+
echo "Error: Directory not found: $DOCS_DIR" >&2
|
|
166
|
+
exit 2
|
|
167
|
+
fi
|
|
168
|
+
while IFS= read -r f; do
|
|
169
|
+
FILES_TO_CHECK+=("$f")
|
|
170
|
+
done < <(find "$DOCS_DIR" -name "*.md" -type f 2>/dev/null | sort)
|
|
171
|
+
fi
|
|
172
|
+
|
|
173
|
+
# ============================================================
|
|
174
|
+
# EXECUTE CHECKS
|
|
175
|
+
# ============================================================
|
|
176
|
+
|
|
177
|
+
for f in "${FILES_TO_CHECK[@]}"; do
|
|
178
|
+
check_file "$f"
|
|
179
|
+
done
|
|
180
|
+
|
|
181
|
+
# ============================================================
|
|
182
|
+
# STRUCTURED OUTPUT
|
|
183
|
+
# ============================================================
|
|
184
|
+
|
|
185
|
+
echo "## Documentation Link Verification Report"
|
|
186
|
+
echo ""
|
|
187
|
+
echo "**Files checked:** ${#FILES_TO_CHECK[@]}"
|
|
188
|
+
echo "**Links checked:** $CHECKED_COUNT"
|
|
189
|
+
echo "**Links skipped:** $SKIPPED_COUNT (external URLs, anchors)"
|
|
190
|
+
echo "**Broken links:** $BROKEN_COUNT"
|
|
191
|
+
echo ""
|
|
192
|
+
|
|
193
|
+
if [[ $BROKEN_COUNT -gt 0 ]]; then
|
|
194
|
+
echo "### Broken Links"
|
|
195
|
+
echo ""
|
|
196
|
+
for link in "${BROKEN_LINKS[@]}"; do
|
|
197
|
+
echo "- \`$link\`"
|
|
198
|
+
done
|
|
199
|
+
echo ""
|
|
200
|
+
fi
|
|
201
|
+
|
|
202
|
+
echo "---"
|
|
203
|
+
echo ""
|
|
204
|
+
|
|
205
|
+
if [[ $BROKEN_COUNT -eq 0 ]]; then
|
|
206
|
+
echo "**Result: PASS** — All internal links resolve to existing files"
|
|
207
|
+
exit 0
|
|
208
|
+
else
|
|
209
|
+
echo "**Result: FAIL** — $BROKEN_COUNT broken link(s) found"
|
|
210
|
+
exit 1
|
|
211
|
+
fi
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Verify Ideate Artifacts
|
|
3
|
+
# Checks brainstorming/ideation completion by validating design document existence,
|
|
4
|
+
# required sections, option evaluation, and state file consistency.
|
|
5
|
+
#
|
|
6
|
+
# Usage: verify-ideate-artifacts.sh --state-file <path> [--docs-dir <path>] [--design-file <path>]
|
|
7
|
+
#
|
|
8
|
+
# Exit codes:
|
|
9
|
+
# 0 = all checks pass (ideation complete)
|
|
10
|
+
# 1 = one or more checks failed (missing sections or artifacts)
|
|
11
|
+
# 2 = usage error (missing required args)
|
|
12
|
+
|
|
13
|
+
set -euo pipefail
|
|
14
|
+
|
|
15
|
+
# ============================================================
|
|
16
|
+
# ARGUMENT PARSING
|
|
17
|
+
# ============================================================
|
|
18
|
+
|
|
19
|
+
STATE_FILE=""
|
|
20
|
+
DOCS_DIR=""
|
|
21
|
+
DESIGN_FILE=""
|
|
22
|
+
|
|
23
|
+
usage() {
|
|
24
|
+
cat << 'USAGE'
|
|
25
|
+
Usage: verify-ideate-artifacts.sh --state-file <path> [--docs-dir <path>] [--design-file <path>]
|
|
26
|
+
|
|
27
|
+
Required:
|
|
28
|
+
--state-file <path> Path to the workflow state JSON file
|
|
29
|
+
|
|
30
|
+
Optional:
|
|
31
|
+
--docs-dir <path> Directory to search for design documents (e.g., docs/designs)
|
|
32
|
+
--design-file <path> Direct path to the design document (overrides --docs-dir)
|
|
33
|
+
--help Show this help message
|
|
34
|
+
|
|
35
|
+
Exit codes:
|
|
36
|
+
0 All completion criteria met
|
|
37
|
+
1 Missing artifacts or sections
|
|
38
|
+
2 Usage error (missing required args)
|
|
39
|
+
USAGE
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
while [[ $# -gt 0 ]]; do
|
|
43
|
+
case "$1" in
|
|
44
|
+
--state-file)
|
|
45
|
+
if [[ -z "${2:-}" ]]; then
|
|
46
|
+
echo "Error: --state-file requires a path argument" >&2
|
|
47
|
+
exit 2
|
|
48
|
+
fi
|
|
49
|
+
STATE_FILE="$2"
|
|
50
|
+
shift 2
|
|
51
|
+
;;
|
|
52
|
+
--docs-dir)
|
|
53
|
+
if [[ -z "${2:-}" ]]; then
|
|
54
|
+
echo "Error: --docs-dir requires a path argument" >&2
|
|
55
|
+
exit 2
|
|
56
|
+
fi
|
|
57
|
+
DOCS_DIR="$2"
|
|
58
|
+
shift 2
|
|
59
|
+
;;
|
|
60
|
+
--design-file)
|
|
61
|
+
if [[ -z "${2:-}" ]]; then
|
|
62
|
+
echo "Error: --design-file requires a path argument" >&2
|
|
63
|
+
exit 2
|
|
64
|
+
fi
|
|
65
|
+
DESIGN_FILE="$2"
|
|
66
|
+
shift 2
|
|
67
|
+
;;
|
|
68
|
+
--help)
|
|
69
|
+
usage
|
|
70
|
+
exit 0
|
|
71
|
+
;;
|
|
72
|
+
*)
|
|
73
|
+
echo "Error: Unknown argument '$1'" >&2
|
|
74
|
+
usage >&2
|
|
75
|
+
exit 2
|
|
76
|
+
;;
|
|
77
|
+
esac
|
|
78
|
+
done
|
|
79
|
+
|
|
80
|
+
if [[ -z "$STATE_FILE" ]]; then
|
|
81
|
+
echo "Error: --state-file is required" >&2
|
|
82
|
+
usage >&2
|
|
83
|
+
exit 2
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
# ============================================================
|
|
87
|
+
# DEPENDENCY CHECK
|
|
88
|
+
# ============================================================
|
|
89
|
+
|
|
90
|
+
if ! command -v jq &>/dev/null; then
|
|
91
|
+
echo "Error: jq is required but not installed" >&2
|
|
92
|
+
exit 2
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
# ============================================================
|
|
96
|
+
# CHECK FUNCTIONS
|
|
97
|
+
# ============================================================
|
|
98
|
+
|
|
99
|
+
CHECK_PASS=0
|
|
100
|
+
CHECK_FAIL=0
|
|
101
|
+
RESULTS=()
|
|
102
|
+
|
|
103
|
+
check_pass() {
|
|
104
|
+
local name="$1"
|
|
105
|
+
RESULTS+=("- **PASS**: $name")
|
|
106
|
+
CHECK_PASS=$((CHECK_PASS + 1))
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
check_fail() {
|
|
110
|
+
local name="$1"
|
|
111
|
+
local detail="${2:-}"
|
|
112
|
+
if [[ -n "$detail" ]]; then
|
|
113
|
+
RESULTS+=("- **FAIL**: $name — $detail")
|
|
114
|
+
else
|
|
115
|
+
RESULTS+=("- **FAIL**: $name")
|
|
116
|
+
fi
|
|
117
|
+
CHECK_FAIL=$((CHECK_FAIL + 1))
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
# ============================================================
|
|
121
|
+
# RESOLVE DESIGN FILE
|
|
122
|
+
# ============================================================
|
|
123
|
+
|
|
124
|
+
resolve_design_file() {
|
|
125
|
+
# If --design-file was given, use it directly
|
|
126
|
+
if [[ -n "$DESIGN_FILE" ]]; then
|
|
127
|
+
if [[ -f "$DESIGN_FILE" ]]; then
|
|
128
|
+
return 0
|
|
129
|
+
else
|
|
130
|
+
check_fail "Design document exists" "File not found: $DESIGN_FILE"
|
|
131
|
+
return 1
|
|
132
|
+
fi
|
|
133
|
+
fi
|
|
134
|
+
|
|
135
|
+
# Try to get design path from state file
|
|
136
|
+
if [[ -f "$STATE_FILE" ]] && jq empty "$STATE_FILE" 2>/dev/null; then
|
|
137
|
+
local state_design_path
|
|
138
|
+
state_design_path="$(jq -r '.artifacts.design // empty' "$STATE_FILE")"
|
|
139
|
+
if [[ -n "$state_design_path" && -f "$state_design_path" ]]; then
|
|
140
|
+
DESIGN_FILE="$state_design_path"
|
|
141
|
+
return 0
|
|
142
|
+
fi
|
|
143
|
+
if [[ -n "$state_design_path" ]] && [[ ! -f "$state_design_path" ]]; then
|
|
144
|
+
check_fail "Design document exists" "State references $state_design_path but file not found"
|
|
145
|
+
return 1
|
|
146
|
+
fi
|
|
147
|
+
fi
|
|
148
|
+
|
|
149
|
+
# Search in docs dir for YYYY-MM-DD-*.md pattern
|
|
150
|
+
if [[ -n "$DOCS_DIR" && -d "$DOCS_DIR" ]]; then
|
|
151
|
+
local found_files
|
|
152
|
+
found_files="$(find "$DOCS_DIR" -maxdepth 1 -name '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]-*.md' -type f 2>/dev/null | sort -r | head -1)"
|
|
153
|
+
if [[ -n "$found_files" ]]; then
|
|
154
|
+
DESIGN_FILE="$found_files"
|
|
155
|
+
return 0
|
|
156
|
+
fi
|
|
157
|
+
fi
|
|
158
|
+
|
|
159
|
+
check_fail "Design document exists" "No design document found in ${DOCS_DIR:-<no docs-dir>}"
|
|
160
|
+
return 1
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
# ============================================================
|
|
164
|
+
# CHECK 1: Design document exists
|
|
165
|
+
# ============================================================
|
|
166
|
+
|
|
167
|
+
check_design_exists() {
|
|
168
|
+
if resolve_design_file; then
|
|
169
|
+
check_pass "Design document exists ($DESIGN_FILE)"
|
|
170
|
+
return 0
|
|
171
|
+
fi
|
|
172
|
+
return 1
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
# ============================================================
|
|
176
|
+
# CHECK 2: Required sections present
|
|
177
|
+
# ============================================================
|
|
178
|
+
|
|
179
|
+
REQUIRED_SECTIONS=(
|
|
180
|
+
"Problem Statement"
|
|
181
|
+
"Chosen Approach"
|
|
182
|
+
"Technical Design"
|
|
183
|
+
"Integration Points"
|
|
184
|
+
"Testing Strategy"
|
|
185
|
+
"Open Questions"
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
check_required_sections() {
|
|
189
|
+
local missing=()
|
|
190
|
+
local content
|
|
191
|
+
content="$(cat "$DESIGN_FILE")"
|
|
192
|
+
|
|
193
|
+
for section in "${REQUIRED_SECTIONS[@]}"; do
|
|
194
|
+
if ! echo "$content" | grep -qi "##.*$section"; then
|
|
195
|
+
missing+=("$section")
|
|
196
|
+
fi
|
|
197
|
+
done
|
|
198
|
+
|
|
199
|
+
if [[ ${#missing[@]} -eq 0 ]]; then
|
|
200
|
+
check_pass "Required sections present (${#REQUIRED_SECTIONS[@]}/${#REQUIRED_SECTIONS[@]})"
|
|
201
|
+
return 0
|
|
202
|
+
else
|
|
203
|
+
local missing_list
|
|
204
|
+
missing_list="$(IFS=', '; echo "${missing[*]}")"
|
|
205
|
+
check_fail "Required sections present" "Missing: $missing_list"
|
|
206
|
+
return 1
|
|
207
|
+
fi
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
# ============================================================
|
|
211
|
+
# CHECK 3: Multiple options evaluated (2-3)
|
|
212
|
+
# ============================================================
|
|
213
|
+
|
|
214
|
+
check_multiple_options() {
|
|
215
|
+
local content
|
|
216
|
+
content="$(cat "$DESIGN_FILE")"
|
|
217
|
+
|
|
218
|
+
# Count "Option N" or "Option [N]" patterns in headings
|
|
219
|
+
local option_count
|
|
220
|
+
option_count="$(echo "$content" | grep -ciE '#+\s*(option\s+[0-9]|option\s+\[?[0-9])' || true)"
|
|
221
|
+
|
|
222
|
+
if [[ "$option_count" -ge 2 ]]; then
|
|
223
|
+
check_pass "Multiple options evaluated ($option_count options found)"
|
|
224
|
+
return 0
|
|
225
|
+
else
|
|
226
|
+
check_fail "Multiple options evaluated" "Found $option_count option(s), expected at least 2"
|
|
227
|
+
return 1
|
|
228
|
+
fi
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
# ============================================================
|
|
232
|
+
# CHECK 4: State file has design path recorded
|
|
233
|
+
# ============================================================
|
|
234
|
+
|
|
235
|
+
check_state_design_path() {
|
|
236
|
+
if [[ ! -f "$STATE_FILE" ]]; then
|
|
237
|
+
check_fail "State file has design path" "State file not found: $STATE_FILE"
|
|
238
|
+
return 1
|
|
239
|
+
fi
|
|
240
|
+
|
|
241
|
+
if ! jq empty "$STATE_FILE" 2>/dev/null; then
|
|
242
|
+
check_fail "State file has design path" "Invalid JSON: $STATE_FILE"
|
|
243
|
+
return 1
|
|
244
|
+
fi
|
|
245
|
+
|
|
246
|
+
local design_path
|
|
247
|
+
design_path="$(jq -r '.artifacts.design // empty' "$STATE_FILE")"
|
|
248
|
+
|
|
249
|
+
if [[ -n "$design_path" ]]; then
|
|
250
|
+
check_pass "State file has design path ($design_path)"
|
|
251
|
+
return 0
|
|
252
|
+
else
|
|
253
|
+
check_fail "State file has design path" "artifacts.design is empty or missing"
|
|
254
|
+
return 1
|
|
255
|
+
fi
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
# ============================================================
|
|
259
|
+
# EXECUTE CHECKS
|
|
260
|
+
# ============================================================
|
|
261
|
+
|
|
262
|
+
if check_design_exists; then
|
|
263
|
+
check_required_sections || true
|
|
264
|
+
check_multiple_options || true
|
|
265
|
+
fi
|
|
266
|
+
|
|
267
|
+
check_state_design_path || true
|
|
268
|
+
|
|
269
|
+
# ============================================================
|
|
270
|
+
# STRUCTURED OUTPUT
|
|
271
|
+
# ============================================================
|
|
272
|
+
|
|
273
|
+
echo "## Ideation Artifact Verification Report"
|
|
274
|
+
echo ""
|
|
275
|
+
echo "**State file:** \`$STATE_FILE\`"
|
|
276
|
+
if [[ -n "$DESIGN_FILE" ]]; then
|
|
277
|
+
echo "**Design file:** \`$DESIGN_FILE\`"
|
|
278
|
+
fi
|
|
279
|
+
echo ""
|
|
280
|
+
|
|
281
|
+
for result in "${RESULTS[@]}"; do
|
|
282
|
+
echo "$result"
|
|
283
|
+
done
|
|
284
|
+
|
|
285
|
+
echo ""
|
|
286
|
+
TOTAL=$((CHECK_PASS + CHECK_FAIL))
|
|
287
|
+
echo "---"
|
|
288
|
+
echo ""
|
|
289
|
+
|
|
290
|
+
if [[ $CHECK_FAIL -eq 0 ]]; then
|
|
291
|
+
echo "**Result: PASS** ($CHECK_PASS/$TOTAL checks passed)"
|
|
292
|
+
exit 0
|
|
293
|
+
else
|
|
294
|
+
echo "**Result: FAIL** ($CHECK_FAIL/$TOTAL checks failed)"
|
|
295
|
+
exit 1
|
|
296
|
+
fi
|