@lvlup-sw/exarchos 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/.claude-plugin/marketplace.json +22 -0
  2. package/.claude-plugin/plugin.json +17 -0
  3. package/.mcp.json +17 -0
  4. package/AGENTS.md +59 -0
  5. package/CLAUDE.md.template +62 -0
  6. package/LICENSE +202 -0
  7. package/README.md +258 -0
  8. package/commands/autocompact.md +37 -0
  9. package/commands/checkpoint.md +85 -0
  10. package/commands/cleanup.md +99 -0
  11. package/commands/debug.md +145 -0
  12. package/commands/delegate.md +56 -0
  13. package/commands/ideate.md +82 -0
  14. package/commands/plan.md +150 -0
  15. package/commands/refactor.md +139 -0
  16. package/commands/reload.md +37 -0
  17. package/commands/resume.md +130 -0
  18. package/commands/review.md +51 -0
  19. package/commands/sync-schemas.md +74 -0
  20. package/commands/synthesize.md +122 -0
  21. package/commands/tdd.md +58 -0
  22. package/dist/exarchos-cli.js +8828 -0
  23. package/dist/exarchos-mcp.js +50 -0
  24. package/hooks/hooks.json +53 -0
  25. package/package.json +59 -0
  26. package/rules/coding-standards.md +46 -0
  27. package/rules/mcp-tool-guidance.md +26 -0
  28. package/rules/pr-descriptions.md +12 -0
  29. package/rules/rm-safety.md +9 -0
  30. package/rules/skill-path-resolution.md +10 -0
  31. package/rules/tdd.md +41 -0
  32. package/rules/telemetry-awareness.md +9 -0
  33. package/scripts/assess-refactor-scope.sh +239 -0
  34. package/scripts/check-benchmark-regression.sh +229 -0
  35. package/scripts/check-coderabbit.sh +288 -0
  36. package/scripts/check-coverage-thresholds.sh +194 -0
  37. package/scripts/check-polish-scope.sh +245 -0
  38. package/scripts/check-property-tests.sh +167 -0
  39. package/scripts/check-tdd-compliance.sh +265 -0
  40. package/scripts/coderabbit-review-gate.sh +518 -0
  41. package/scripts/debug-review-gate.sh +201 -0
  42. package/scripts/extract-fix-tasks.sh +179 -0
  43. package/scripts/extract-task.sh +67 -0
  44. package/scripts/generate-traceability.sh +209 -0
  45. package/scripts/investigation-timer.sh +171 -0
  46. package/scripts/needs-schema-sync.sh +174 -0
  47. package/scripts/new-project.sh +103 -0
  48. package/scripts/post-delegation-check.sh +317 -0
  49. package/scripts/pre-synthesis-check.sh +440 -0
  50. package/scripts/reconcile-state.sh +346 -0
  51. package/scripts/reconstruct-stack.sh +432 -0
  52. package/scripts/review-diff.sh +63 -0
  53. package/scripts/review-verdict.sh +169 -0
  54. package/scripts/security-scan.sh +248 -0
  55. package/scripts/select-debug-track.sh +186 -0
  56. package/scripts/setup-worktree.sh +323 -0
  57. package/scripts/spec-coverage-check.sh +230 -0
  58. package/scripts/static-analysis-gate.sh +236 -0
  59. package/scripts/sync-labels.sh +122 -0
  60. package/scripts/validate-companion.sh +161 -0
  61. package/scripts/validate-dotnet-standards.sh +267 -0
  62. package/scripts/validate-installation.sh +101 -0
  63. package/scripts/validate-plugin.sh +223 -0
  64. package/scripts/validate-refactor.sh +234 -0
  65. package/scripts/validate-rm.sh +93 -0
  66. package/scripts/verify-delegation-saga.sh +240 -0
  67. package/scripts/verify-doc-links.sh +211 -0
  68. package/scripts/verify-ideate-artifacts.sh +296 -0
  69. package/scripts/verify-plan-coverage.sh +228 -0
  70. package/scripts/verify-review-triage.sh +219 -0
  71. package/scripts/verify-worktree-baseline.sh +159 -0
  72. package/scripts/verify-worktree.sh +84 -0
  73. package/settings.json +47 -0
  74. package/skills/brainstorming/SKILL.md +127 -0
  75. package/skills/brainstorming/references/design-template.md +65 -0
  76. package/skills/cleanup/SKILL.md +147 -0
  77. package/skills/cleanup/references/merge-verification.md +40 -0
  78. package/skills/debug/SKILL.md +204 -0
  79. package/skills/debug/references/hotfix-track.md +134 -0
  80. package/skills/debug/references/investigation-checklist.md +217 -0
  81. package/skills/debug/references/rca-template.md +150 -0
  82. package/skills/debug/references/state-schema.md +294 -0
  83. package/skills/debug/references/thorough-track.md +194 -0
  84. package/skills/debug/references/triage-questions.md +155 -0
  85. package/skills/debug/references/troubleshooting.md +47 -0
  86. package/skills/delegation/SKILL.md +150 -0
  87. package/skills/delegation/references/adaptive-orchestration.md +31 -0
  88. package/skills/delegation/references/agent-teams-saga.md +248 -0
  89. package/skills/delegation/references/fix-mode.md +74 -0
  90. package/skills/delegation/references/fixer-prompt.md +162 -0
  91. package/skills/delegation/references/implementer-prompt.md +322 -0
  92. package/skills/delegation/references/parallel-strategy.md +124 -0
  93. package/skills/delegation/references/pbt-patterns.md +172 -0
  94. package/skills/delegation/references/pr-fixes-mode.md +154 -0
  95. package/skills/delegation/references/state-management.md +51 -0
  96. package/skills/delegation/references/testing-patterns.md +129 -0
  97. package/skills/delegation/references/troubleshooting.md +33 -0
  98. package/skills/delegation/references/workflow-steps.md +127 -0
  99. package/skills/delegation/references/worktree-enforcement.md +64 -0
  100. package/skills/dotnet-standards/SKILL.md +269 -0
  101. package/skills/dotnet-standards/references/csharp-standards.md +120 -0
  102. package/skills/dotnet-standards/templates/.editorconfig +366 -0
  103. package/skills/dotnet-standards/templates/Directory.Build.props +56 -0
  104. package/skills/dotnet-standards/templates/Directory.Packages.props +69 -0
  105. package/skills/dotnet-standards/templates/global.json +6 -0
  106. package/skills/dotnet-standards/templates/nuget.config +9 -0
  107. package/skills/dotnet-standards/templates/stylecop.json +37 -0
  108. package/skills/git-worktrees/SKILL.md +255 -0
  109. package/skills/implementation-planning/SKILL.md +233 -0
  110. package/skills/implementation-planning/references/plan-document-template.md +42 -0
  111. package/skills/implementation-planning/references/spec-tracing-guide.md +51 -0
  112. package/skills/implementation-planning/references/task-template.md +43 -0
  113. package/skills/implementation-planning/references/testing-strategy-guide.md +88 -0
  114. package/skills/quality-review/SKILL.md +278 -0
  115. package/skills/quality-review/references/code-quality-checklist.md +159 -0
  116. package/skills/quality-review/references/review-report-template.md +65 -0
  117. package/skills/quality-review/references/security-checklist.md +79 -0
  118. package/skills/quality-review/references/typescript-standards.md +24 -0
  119. package/skills/refactor/COMMAND.md +67 -0
  120. package/skills/refactor/SKILL.md +198 -0
  121. package/skills/refactor/phases/auto-chain.md +262 -0
  122. package/skills/refactor/phases/brief.md +176 -0
  123. package/skills/refactor/phases/explore.md +132 -0
  124. package/skills/refactor/phases/overhaul-delegate.md +136 -0
  125. package/skills/refactor/phases/overhaul-plan.md +312 -0
  126. package/skills/refactor/phases/overhaul-review.md +304 -0
  127. package/skills/refactor/phases/polish-implement.md +349 -0
  128. package/skills/refactor/phases/polish-validate.md +218 -0
  129. package/skills/refactor/phases/update-docs.md +234 -0
  130. package/skills/refactor/references/brief-template.md +81 -0
  131. package/skills/refactor/references/doc-update-checklist.md +110 -0
  132. package/skills/refactor/references/explore-checklist.md +73 -0
  133. package/skills/refactor/references/overhaul-track.md +215 -0
  134. package/skills/refactor/references/polish-track.md +170 -0
  135. package/skills/shared/prompts/context-reading.md +58 -0
  136. package/skills/shared/prompts/report-format.md +54 -0
  137. package/skills/shared/prompts/tdd-requirements.md +39 -0
  138. package/skills/shepherd/SKILL.md +264 -0
  139. package/skills/shepherd/references/assess-checklist.md +124 -0
  140. package/skills/shepherd/references/fix-strategies.md +191 -0
  141. package/skills/spec-review/SKILL.md +229 -0
  142. package/skills/spec-review/references/review-checklist.md +60 -0
  143. package/skills/sync-schemas/SKILL.md +114 -0
  144. package/skills/sync-schemas/references/configuration.md +73 -0
  145. package/skills/synthesis/SKILL.md +129 -0
  146. package/skills/synthesis/references/pr-descriptions.md +87 -0
  147. package/skills/synthesis/references/synthesis-steps.md +109 -0
  148. package/skills/synthesis/references/troubleshooting.md +115 -0
  149. package/skills/validate-all-skills.sh +57 -0
  150. package/skills/validate-frontmatter.sh +237 -0
  151. package/skills/workflow-state/SKILL.md +210 -0
  152. package/skills/workflow-state/references/mcp-tool-reference.md +111 -0
  153. package/skills/workflow-state/references/phase-transitions.md +141 -0
@@ -0,0 +1,201 @@
1
+ #!/usr/bin/env bash
2
+ # Debug Review Gate
3
+ # Verifies that a debug fix has proper test coverage for the bug scenario.
4
+ # Replaces "Thorough Track Review" prose with deterministic validation.
5
+ #
6
+ # Usage: debug-review-gate.sh --repo-root <path> --base-branch <branch> [--skip-run]
7
+ #
8
+ # Exit codes:
9
+ # 0 = review passed (tests added, tests pass, no regressions)
10
+ # 1 = gaps found (missing tests or regressions)
11
+ # 2 = usage error (missing required args)
12
+
13
+ set -euo pipefail
14
+
15
+ # ============================================================
16
+ # ARGUMENT PARSING
17
+ # ============================================================
18
+
19
+ REPO_ROOT=""
20
+ BASE_BRANCH=""
21
+ SKIP_RUN=false
22
+
23
+ usage() {
24
+ cat << 'USAGE'
25
+ Usage: debug-review-gate.sh --repo-root <path> --base-branch <branch> [--skip-run]
26
+
27
+ Required:
28
+ --repo-root <path> Repository root directory
29
+ --base-branch <branch> Base branch to diff against (e.g., main)
30
+
31
+ Optional:
32
+ --skip-run Skip test execution (only check for new test files)
33
+ --help Show this help message
34
+
35
+ Exit codes:
36
+ 0 Review passed — tests added, tests pass, no regressions
37
+ 1 Gaps found — missing tests or test failures
38
+ 2 Usage error (missing required args)
39
+ USAGE
40
+ }
41
+
42
+ while [[ $# -gt 0 ]]; do
43
+ case "$1" in
44
+ --repo-root)
45
+ if [[ -z "${2:-}" ]]; then
46
+ echo "Error: --repo-root requires a path argument" >&2
47
+ exit 2
48
+ fi
49
+ REPO_ROOT="$2"
50
+ shift 2
51
+ ;;
52
+ --base-branch)
53
+ if [[ -z "${2:-}" ]]; then
54
+ echo "Error: --base-branch requires a branch name argument" >&2
55
+ exit 2
56
+ fi
57
+ BASE_BRANCH="$2"
58
+ shift 2
59
+ ;;
60
+ --skip-run)
61
+ SKIP_RUN=true
62
+ shift
63
+ ;;
64
+ --help)
65
+ usage
66
+ exit 0
67
+ ;;
68
+ *)
69
+ echo "Error: Unknown argument '$1'" >&2
70
+ usage >&2
71
+ exit 2
72
+ ;;
73
+ esac
74
+ done
75
+
76
+ if [[ -z "$REPO_ROOT" || -z "$BASE_BRANCH" ]]; then
77
+ echo "Error: --repo-root and --base-branch are required" >&2
78
+ usage >&2
79
+ exit 2
80
+ fi
81
+
82
+ if [[ ! -d "$REPO_ROOT" ]]; then
83
+ echo "Error: Repository root not found: $REPO_ROOT" >&2
84
+ exit 2
85
+ fi
86
+
87
+ # ============================================================
88
+ # CHECK FUNCTIONS
89
+ # ============================================================
90
+
91
+ CHECK_PASS=0
92
+ CHECK_FAIL=0
93
+ RESULTS=()
94
+
95
+ check_pass() {
96
+ local name="$1"
97
+ RESULTS+=("- **PASS**: $name")
98
+ CHECK_PASS=$((CHECK_PASS + 1))
99
+ }
100
+
101
+ check_fail() {
102
+ local name="$1"
103
+ local detail="${2:-}"
104
+ if [[ -n "$detail" ]]; then
105
+ RESULTS+=("- **FAIL**: $name — $detail")
106
+ else
107
+ RESULTS+=("- **FAIL**: $name")
108
+ fi
109
+ CHECK_FAIL=$((CHECK_FAIL + 1))
110
+ }
111
+
112
+ check_skip() {
113
+ local name="$1"
114
+ RESULTS+=("- **SKIP**: $name")
115
+ }
116
+
117
+ # ============================================================
118
+ # CHECK 1: New test files added in the fix branch
119
+ # ============================================================
120
+
121
+ check_new_tests() {
122
+ local changed_files
123
+ changed_files="$(cd "$REPO_ROOT" && git diff --name-only "$BASE_BRANCH"...HEAD 2>/dev/null || \
124
+ cd "$REPO_ROOT" && git diff --name-only "$BASE_BRANCH" HEAD 2>/dev/null || true)"
125
+
126
+ if [[ -z "$changed_files" ]]; then
127
+ check_fail "New test files added" "No changed files found between $BASE_BRANCH and HEAD"
128
+ return 1
129
+ fi
130
+
131
+ # Look for test files: .test.ts, .test.sh, .spec.ts, .test.js, .spec.js
132
+ local test_files
133
+ test_files="$(echo "$changed_files" | grep -E '\.(test|spec)\.(ts|js|sh)$' || true)"
134
+
135
+ if [[ -z "$test_files" ]]; then
136
+ check_fail "New test files added" "No test files found in changed files"
137
+ return 1
138
+ fi
139
+
140
+ local test_count
141
+ test_count="$(echo "$test_files" | wc -l | tr -d ' ')"
142
+ check_pass "New test files added ($test_count test file(s): $(echo "$test_files" | tr '\n' ', ' | sed 's/,$//'))"
143
+ return 0
144
+ }
145
+
146
+ # ============================================================
147
+ # CHECK 2: Tests pass (npm run test:run)
148
+ # ============================================================
149
+
150
+ check_tests_pass() {
151
+ if [[ "$SKIP_RUN" == true ]]; then
152
+ check_skip "Tests pass (--skip-run)"
153
+ return 0
154
+ fi
155
+
156
+ local test_output
157
+ if ! test_output="$(cd "$REPO_ROOT" && npm run test:run 2>&1)"; then
158
+ check_fail "Tests pass" "npm run test:run failed"
159
+ return 1
160
+ fi
161
+
162
+ check_pass "Tests pass"
163
+ return 0
164
+ }
165
+
166
+ # ============================================================
167
+ # EXECUTE CHECKS
168
+ # ============================================================
169
+
170
+ # Check 1: New test files
171
+ check_new_tests || true
172
+
173
+ # Check 2: Tests pass
174
+ check_tests_pass || true
175
+
176
+ # ============================================================
177
+ # STRUCTURED OUTPUT
178
+ # ============================================================
179
+
180
+ echo "## Debug Review Gate"
181
+ echo ""
182
+ echo "**Repository:** \`$REPO_ROOT\`"
183
+ echo "**Base branch:** \`$BASE_BRANCH\`"
184
+ echo ""
185
+
186
+ for result in "${RESULTS[@]}"; do
187
+ echo "$result"
188
+ done
189
+
190
+ echo ""
191
+ TOTAL=$((CHECK_PASS + CHECK_FAIL))
192
+ echo "---"
193
+ echo ""
194
+
195
+ if [[ $CHECK_FAIL -eq 0 ]]; then
196
+ echo "**Result: PASS** ($CHECK_PASS/$TOTAL checks passed)"
197
+ exit 0
198
+ else
199
+ echo "**Result: FAIL** ($CHECK_FAIL/$TOTAL checks failed)"
200
+ exit 1
201
+ fi
@@ -0,0 +1,179 @@
1
+ #!/usr/bin/env bash
2
+ # extract-fix-tasks.sh — Parse review findings into fix tasks
3
+ # Replaces "Fix Mode Task Extraction" prose in delegation SKILL.md.
4
+ #
5
+ # Usage: extract-fix-tasks.sh --state-file <path> [--review-report <path>] [--repo-root <path>]
6
+ #
7
+ # Exit codes:
8
+ # 0 = tasks extracted (outputs JSON array to stdout)
9
+ # 1 = parse error
10
+ # 2 = usage error (missing required args)
11
+
12
+ set -euo pipefail
13
+
14
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
15
+
16
+ # ============================================================
17
+ # ARGUMENT PARSING
18
+ # ============================================================
19
+
20
+ STATE_FILE=""
21
+ REVIEW_REPORT=""
22
+ REPO_ROOT=""
23
+
24
+ usage() {
25
+ cat << 'USAGE'
26
+ Usage: extract-fix-tasks.sh --state-file <path> [--review-report <path>] [--repo-root <path>]
27
+
28
+ Required:
29
+ --state-file <path> Path to the workflow state JSON file
30
+
31
+ Optional:
32
+ --review-report <path> External review report JSON file (overrides state findings)
33
+ --repo-root <path> Repository root for worktree resolution
34
+ --help Show this help message
35
+
36
+ Output:
37
+ JSON array of fix tasks to stdout. Each task has: id, file, line, worktree, description, severity
38
+
39
+ Exit codes:
40
+ 0 Tasks extracted (JSON array output, may be empty if no findings)
41
+ 1 Parse error (invalid JSON, missing file)
42
+ 2 Usage error (missing required args)
43
+ USAGE
44
+ }
45
+
46
+ while [[ $# -gt 0 ]]; do
47
+ case "$1" in
48
+ --state-file)
49
+ if [[ -z "${2:-}" ]]; then
50
+ echo "Error: --state-file requires a path argument" >&2
51
+ exit 2
52
+ fi
53
+ STATE_FILE="$2"
54
+ shift 2
55
+ ;;
56
+ --review-report)
57
+ if [[ -z "${2:-}" ]]; then
58
+ echo "Error: --review-report requires a path argument" >&2
59
+ exit 2
60
+ fi
61
+ REVIEW_REPORT="$2"
62
+ shift 2
63
+ ;;
64
+ --repo-root)
65
+ if [[ -z "${2:-}" ]]; then
66
+ echo "Error: --repo-root requires a path argument" >&2
67
+ exit 2
68
+ fi
69
+ REPO_ROOT="$2"
70
+ shift 2
71
+ ;;
72
+ --help)
73
+ usage
74
+ exit 0
75
+ ;;
76
+ *)
77
+ echo "Error: Unknown argument '$1'" >&2
78
+ usage >&2
79
+ exit 2
80
+ ;;
81
+ esac
82
+ done
83
+
84
+ if [[ -z "$STATE_FILE" ]]; then
85
+ echo "Error: --state-file is required" >&2
86
+ usage >&2
87
+ exit 2
88
+ fi
89
+
90
+ # ============================================================
91
+ # DEPENDENCY CHECK
92
+ # ============================================================
93
+
94
+ if ! command -v jq &>/dev/null; then
95
+ echo "Error: jq is required but not installed" >&2
96
+ exit 2
97
+ fi
98
+
99
+ # ============================================================
100
+ # VALIDATE INPUTS
101
+ # ============================================================
102
+
103
+ if [[ ! -f "$STATE_FILE" ]]; then
104
+ echo "Error: State file not found: $STATE_FILE" >&2
105
+ exit 1
106
+ fi
107
+
108
+ if ! jq empty "$STATE_FILE" 2>/dev/null; then
109
+ echo "Error: Invalid JSON in state file: $STATE_FILE" >&2
110
+ exit 1
111
+ fi
112
+
113
+ if [[ -n "$REVIEW_REPORT" ]]; then
114
+ if [[ ! -f "$REVIEW_REPORT" ]]; then
115
+ echo "Error: Review report not found: $REVIEW_REPORT" >&2
116
+ exit 1
117
+ fi
118
+ if ! jq empty "$REVIEW_REPORT" 2>/dev/null; then
119
+ echo "Error: Invalid JSON in review report: $REVIEW_REPORT" >&2
120
+ exit 1
121
+ fi
122
+ fi
123
+
124
+ # ============================================================
125
+ # EXTRACT FINDINGS
126
+ # ============================================================
127
+
128
+ # Collect all findings from either the review report or the state file
129
+ if [[ -n "$REVIEW_REPORT" ]]; then
130
+ # Use external review report
131
+ ALL_FINDINGS="$(jq -c '.findings // []' "$REVIEW_REPORT" 2>/dev/null || echo '[]')"
132
+ else
133
+ # Extract findings from state file reviews
134
+ ALL_FINDINGS="$(jq -c '
135
+ [
136
+ (.reviews // {} | to_entries[] | .value.findings // [] | .[])
137
+ ]
138
+ ' "$STATE_FILE" 2>/dev/null || echo '[]')"
139
+ fi
140
+
141
+ # ============================================================
142
+ # BUILD FIX TASKS
143
+ # ============================================================
144
+
145
+ # Get all worktrees from tasks for file-to-worktree mapping
146
+ WORKTREES_JSON="$(jq -c '[.tasks[] | select(.worktree != null) | {worktree: .worktree, branch: (.branch // "unknown")}] | unique_by(.worktree)' "$STATE_FILE" 2>/dev/null || echo '[]')"
147
+
148
+ # Fail fast when multiple worktrees exist — deterministic mapping not yet implemented
149
+ WORKTREE_COUNT="$(echo "$WORKTREES_JSON" | jq 'length')"
150
+ FINDING_COUNT="$(echo "$ALL_FINDINGS" | jq 'length')"
151
+ if [[ "$WORKTREE_COUNT" -gt 1 && "$FINDING_COUNT" -gt 0 ]]; then
152
+ echo "Error: $WORKTREE_COUNT worktrees detected but cannot deterministically map $FINDING_COUNT findings to worktrees." >&2
153
+ echo " Assign worktrees manually in the fix task file." >&2
154
+ exit 1
155
+ fi
156
+
157
+ # Transform findings into fix tasks with IDs and worktree mapping
158
+ FIX_TASKS="$(echo "$ALL_FINDINGS" | jq -c --argjson worktrees "$WORKTREES_JSON" '
159
+ [to_entries[] | {
160
+ id: ("fix-\(.key + 1 | tostring | if length < 3 then ("00" + .)[-3:] else . end)"),
161
+ file: .value.file,
162
+ line: (.value.line // null),
163
+ worktree: (
164
+ ($worktrees | length) as $n |
165
+ if $n == 1 then $worktrees[0].worktree else null end
166
+ ),
167
+ description: .value.description,
168
+ severity: (.value.severity // "MEDIUM")
169
+ }]
170
+ ' 2>/dev/null)"
171
+
172
+ if [[ -z "$FIX_TASKS" || "$FIX_TASKS" == "null" ]]; then
173
+ echo "[]"
174
+ exit 0
175
+ fi
176
+
177
+ # Output the fix tasks JSON array
178
+ echo "$FIX_TASKS"
179
+ exit 0
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # extract-task.sh - Extract single task from implementation plan
4
+ #
5
+ # Usage: extract-task.sh <plan-path> <task-id>
6
+ #
7
+ # Output: Just the task section from the plan, not the full document.
8
+ # This reduces context by ~90% when delegating tasks.
9
+ #
10
+ # Examples:
11
+ # extract-task.sh docs/plans/2026-01-05-auth.md 001
12
+ # extract-task.sh docs/plans/2026-01-05-auth.md A1
13
+ #
14
+
15
+ set -euo pipefail
16
+
17
+ PLAN="${1:-}"
18
+ TASK_ID="${2:-}"
19
+
20
+ if [ -z "$PLAN" ] || [ -z "$TASK_ID" ]; then
21
+ echo "Usage: extract-task.sh <plan-path> <task-id>" >&2
22
+ exit 1
23
+ fi
24
+
25
+ if [ ! -f "$PLAN" ]; then
26
+ echo "ERROR: Plan file not found: $PLAN" >&2
27
+ exit 1
28
+ fi
29
+
30
+ # Extract task section using awk
31
+ # Matches: ### Task 001, ### Task A1, ### Task 1:, etc.
32
+ # Stops at next task header or major section header
33
+
34
+ awk -v task_id="$TASK_ID" '
35
+ BEGIN {
36
+ found = 0
37
+ # Build pattern to match task header
38
+ # Handles: "### Task 001:", "### Task A1:", "## Task 1", etc.
39
+ pattern = "^##+ *Task *" task_id "([: ]|$)"
40
+ }
41
+
42
+ # Start capturing when we find the task
43
+ $0 ~ pattern {
44
+ found = 1
45
+ print
46
+ next
47
+ }
48
+
49
+ # Stop at next task or major section
50
+ found && /^##+ *(Task [0-9A-Za-z]+|[A-Z])/ {
51
+ exit
52
+ }
53
+
54
+ # Print while capturing
55
+ found {
56
+ print
57
+ }
58
+ ' "$PLAN"
59
+
60
+ # Check if we found anything
61
+ if ! grep -qE "^##+ *Task *$TASK_ID([: ]|$)" "$PLAN"; then
62
+ echo "WARNING: Task $TASK_ID not found in $PLAN" >&2
63
+ echo "" >&2
64
+ echo "Available tasks:" >&2
65
+ grep -E "^##+ *Task " "$PLAN" | head -20 >&2
66
+ exit 1
67
+ fi
@@ -0,0 +1,209 @@
1
+ #!/usr/bin/env bash
2
+ # Generate Traceability Matrix
3
+ # Pre-populate traceability matrix from design and plan headers.
4
+ #
5
+ # Usage: generate-traceability.sh --design-file <path> --plan-file <path> [--output <path>]
6
+ #
7
+ # Exit codes:
8
+ # 0 = generated successfully
9
+ # 1 = parse error (no sections found)
10
+ # 2 = usage error (missing required args, missing files)
11
+
12
+ set -euo pipefail
13
+
14
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
15
+
16
+ # Colors
17
+ RED='\033[0;31m'
18
+ GREEN='\033[0;32m'
19
+ YELLOW='\033[1;33m'
20
+ NC='\033[0m'
21
+
22
+ # ============================================================
23
+ # ARGUMENT PARSING
24
+ # ============================================================
25
+
26
+ DESIGN_FILE=""
27
+ PLAN_FILE=""
28
+ OUTPUT_FILE=""
29
+
30
+ usage() {
31
+ cat << 'USAGE'
32
+ Usage: generate-traceability.sh --design-file <path> --plan-file <path> [--output <path>]
33
+
34
+ Required:
35
+ --design-file <path> Path to the design document markdown file
36
+ --plan-file <path> Path to the implementation plan markdown file
37
+
38
+ Optional:
39
+ --output <path> Write output to file instead of stdout
40
+ --help Show this help message
41
+
42
+ Exit codes:
43
+ 0 Generated successfully
44
+ 1 Parse error (no sections found in design)
45
+ 2 Usage error (missing required args, missing files)
46
+ USAGE
47
+ }
48
+
49
+ while [[ $# -gt 0 ]]; do
50
+ case "$1" in
51
+ --design-file)
52
+ if [[ -z "${2:-}" ]]; then
53
+ echo "Error: --design-file requires a path argument" >&2
54
+ exit 2
55
+ fi
56
+ DESIGN_FILE="$2"
57
+ shift 2
58
+ ;;
59
+ --plan-file)
60
+ if [[ -z "${2:-}" ]]; then
61
+ echo "Error: --plan-file requires a path argument" >&2
62
+ exit 2
63
+ fi
64
+ PLAN_FILE="$2"
65
+ shift 2
66
+ ;;
67
+ --output)
68
+ if [[ -z "${2:-}" ]]; then
69
+ echo "Error: --output requires a path argument" >&2
70
+ exit 2
71
+ fi
72
+ OUTPUT_FILE="$2"
73
+ shift 2
74
+ ;;
75
+ --help)
76
+ usage
77
+ exit 0
78
+ ;;
79
+ *)
80
+ echo "Error: Unknown argument '$1'" >&2
81
+ usage >&2
82
+ exit 2
83
+ ;;
84
+ esac
85
+ done
86
+
87
+ if [[ -z "$DESIGN_FILE" || -z "$PLAN_FILE" ]]; then
88
+ echo "Error: --design-file and --plan-file are required" >&2
89
+ usage >&2
90
+ exit 2
91
+ fi
92
+
93
+ if [[ ! -f "$DESIGN_FILE" ]]; then
94
+ echo "Error: Design file not found: $DESIGN_FILE" >&2
95
+ exit 2
96
+ fi
97
+
98
+ if [[ ! -f "$PLAN_FILE" ]]; then
99
+ echo "Error: Plan file not found: $PLAN_FILE" >&2
100
+ exit 2
101
+ fi
102
+
103
+ # ============================================================
104
+ # EXTRACT DESIGN SECTIONS (## and ### headers)
105
+ # ============================================================
106
+
107
+ DESIGN_SECTIONS=()
108
+ DESIGN_LEVELS=()
109
+
110
+ while IFS= read -r line; do
111
+ if [[ "$line" =~ ^(#{2,3})[[:space:]]+(.+) ]]; then
112
+ level="${BASH_REMATCH[1]}"
113
+ section_name="${BASH_REMATCH[2]}"
114
+ section_name="$(echo "$section_name" | sed 's/[[:space:]]*$//')"
115
+ DESIGN_SECTIONS+=("$section_name")
116
+ DESIGN_LEVELS+=("$level")
117
+ fi
118
+ done < "$DESIGN_FILE"
119
+
120
+ if [[ ${#DESIGN_SECTIONS[@]} -eq 0 ]]; then
121
+ echo "Error: No ## or ### headers found in design document" >&2
122
+ exit 1
123
+ fi
124
+
125
+ # ============================================================
126
+ # EXTRACT PLAN TASKS (### Task headers)
127
+ # ============================================================
128
+
129
+ PLAN_TASKS=()
130
+ PLAN_TASK_IDS=()
131
+
132
+ while IFS= read -r line; do
133
+ if [[ "$line" =~ ^###[[:space:]]+Task[[:space:]]+([0-9]+) ]]; then
134
+ task_id="${BASH_REMATCH[1]}"
135
+ # Extract the full task title
136
+ task_title="${line#*: }"
137
+ if [[ -n "$task_title" && "$task_title" != "$line" ]]; then
138
+ PLAN_TASKS+=("$task_title")
139
+ else
140
+ PLAN_TASKS+=("$line")
141
+ fi
142
+ PLAN_TASK_IDS+=("$task_id")
143
+ fi
144
+ done < "$PLAN_FILE"
145
+
146
+ # Read full plan content for matching
147
+ PLAN_CONTENT="$(cat "$PLAN_FILE")"
148
+
149
+ # ============================================================
150
+ # GENERATE TRACEABILITY TABLE
151
+ # ============================================================
152
+
153
+ generate_table() {
154
+ echo "## Spec Traceability"
155
+ echo ""
156
+ echo "### Traceability Matrix"
157
+ echo ""
158
+ echo "| Design Section | Key Requirements | Task ID(s) | Status |"
159
+ echo "|----------------|-----------------|------------|--------|"
160
+
161
+ for i in "${!DESIGN_SECTIONS[@]}"; do
162
+ section="${DESIGN_SECTIONS[$i]}"
163
+ level="${DESIGN_LEVELS[$i]}"
164
+
165
+ # Find matching tasks
166
+ matched_ids=()
167
+ for j in "${!PLAN_TASKS[@]}"; do
168
+ task="${PLAN_TASKS[$j]}"
169
+ tid="${PLAN_TASK_IDS[$j]}"
170
+ if echo "$task" | grep -qiF "$section"; then
171
+ matched_ids+=("$tid")
172
+ fi
173
+ done
174
+
175
+ # Also check plan body
176
+ if [[ ${#matched_ids[@]} -eq 0 ]]; then
177
+ if echo "$PLAN_CONTENT" | grep -qiF "$section"; then
178
+ matched_ids+=("?")
179
+ fi
180
+ fi
181
+
182
+ # Format output
183
+ if [[ ${#matched_ids[@]} -gt 0 ]]; then
184
+ ids="$(printf '%s, ' "${matched_ids[@]}")"
185
+ ids="${ids%, }"
186
+ echo "| $section | (to be filled) | $ids | Covered |"
187
+ else
188
+ echo "| $section | (to be filled) | — | Uncovered |"
189
+ fi
190
+ done
191
+ echo ""
192
+ echo "### Scope Declaration"
193
+ echo ""
194
+ echo "**Target:** (to be filled)"
195
+ echo "**Excluded:** (to be filled)"
196
+ }
197
+
198
+ # ============================================================
199
+ # OUTPUT
200
+ # ============================================================
201
+
202
+ if [[ -n "$OUTPUT_FILE" ]]; then
203
+ generate_table > "$OUTPUT_FILE"
204
+ echo "Traceability matrix written to: $OUTPUT_FILE"
205
+ else
206
+ generate_table
207
+ fi
208
+
209
+ exit 0