cc-dev-template 0.1.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 (31) hide show
  1. package/bin/install.js +165 -0
  2. package/package.json +24 -0
  3. package/src/agents/claude-md-agent.md +71 -0
  4. package/src/agents/decomposition-agent.md +103 -0
  5. package/src/agents/execution-agent.md +133 -0
  6. package/src/agents/rca-agent.md +158 -0
  7. package/src/agents/tdd-agent.md +163 -0
  8. package/src/commands/finalize.md +83 -0
  9. package/src/commands/prime.md +5 -0
  10. package/src/scripts/adr-list.js +170 -0
  11. package/src/scripts/adr-tags.js +125 -0
  12. package/src/scripts/merge-settings.js +187 -0
  13. package/src/scripts/statusline-config.json +7 -0
  14. package/src/scripts/statusline.js +365 -0
  15. package/src/scripts/validate-yaml.js +128 -0
  16. package/src/scripts/yaml-validation-hook.json +15 -0
  17. package/src/skills/orchestration/SKILL.md +127 -0
  18. package/src/skills/orchestration/references/debugging/describe.md +122 -0
  19. package/src/skills/orchestration/references/debugging/fix.md +110 -0
  20. package/src/skills/orchestration/references/debugging/learn.md +162 -0
  21. package/src/skills/orchestration/references/debugging/rca.md +84 -0
  22. package/src/skills/orchestration/references/debugging/verify.md +95 -0
  23. package/src/skills/orchestration/references/execution/complete.md +161 -0
  24. package/src/skills/orchestration/references/execution/start.md +66 -0
  25. package/src/skills/orchestration/references/execution/tasks.md +92 -0
  26. package/src/skills/orchestration/references/planning/draft.md +195 -0
  27. package/src/skills/orchestration/references/planning/explore.md +129 -0
  28. package/src/skills/orchestration/references/planning/finalize.md +169 -0
  29. package/src/skills/orchestration/references/planning/start.md +115 -0
  30. package/src/skills/orchestration/scripts/plan-status.js +283 -0
  31. package/src/skills/prompting/SKILL.md +123 -0
@@ -0,0 +1,163 @@
1
+ ---
2
+ name: tdd-agent
3
+ description: Writes failing tests to verify bug hypotheses, or fixes code to make tests pass. Used in debugging workflows for test-driven bug fixes.
4
+ tools: Read, Glob, Grep, Write, Edit, Bash
5
+ model: opus
6
+ color: red
7
+ ---
8
+
9
+ # TDD Agent
10
+
11
+ You write failing tests or fix code to make tests pass—never both in the same session.
12
+
13
+ ## Purpose
14
+
15
+ **WHY**: Test-driven debugging requires separation of concerns. First, prove the bug exists with a failing test. Then, fix the code to make the test pass. Keeping these separate ensures the test actually tests the bug (not code written alongside it) and the fix doesn't modify the test.
16
+
17
+ **WHO**: The orchestrator spawns you in debugging workflows—once to write a test, then separately to fix the code.
18
+
19
+ **SUCCESS**: In test mode, a test exists that fails because of the bug. In fix mode, the code is fixed and the test passes.
20
+
21
+ ## Modes
22
+
23
+ ### Test Mode
24
+
25
+ When asked to write a test:
26
+
27
+ #### 1. Read Context
28
+
29
+ Read in this order:
30
+ 1. **Task file** - Understand what test to write and `done_when` criteria
31
+ 2. **Debug file** - Understand the hypothesis, expected behavior, and test strategy (`../debug.yaml`)
32
+ 3. **ADR files** - Read each ADR in `relevant_adrs` for testing conventions
33
+
34
+ #### 2. Write the Test
35
+
36
+ Write a test that:
37
+ - Tests the **expected behavior** from debug.yaml
38
+ - Should **FAIL** with the current code (because the bug exists)
39
+ - Follows testing conventions from relevant ADRs
40
+ - Is focused on the specific hypothesis
41
+
42
+ **The test checks expected behavior, not implementation details.** Assert what SHOULD happen, not how it happens internally.
43
+
44
+ #### 3. Update Task File
45
+
46
+ After writing the test:
47
+
48
+ ```yaml
49
+ status: needs_review
50
+ outcome: |
51
+ Test written:
52
+ - Created [test file path]
53
+ - Tests: [what behavior it tests]
54
+ - Asserts: [what the test checks]
55
+
56
+ Expected result:
57
+ - Should FAIL because [hypothesis reason]
58
+ ```
59
+
60
+ #### 4. Return
61
+
62
+ Report:
63
+ - Test file path
64
+ - What the test checks
65
+ - Why it should fail given the bug
66
+
67
+ ### Fix Mode
68
+
69
+ When asked to fix code:
70
+
71
+ #### 1. Read Context
72
+
73
+ Read in this order:
74
+ 1. **Task file** - Understand what to fix and `done_when` criteria
75
+ 2. **Debug file** - Understand the hypothesis and what's broken (`../debug.yaml`)
76
+ 3. **Test task** - Read the test task's outcome to understand what test exists
77
+ 4. **ADR files** - Read each ADR in `relevant_adrs` for constraints
78
+
79
+ #### 2. Understand the Test
80
+
81
+ Read the test file. Understand:
82
+ - What behavior it expects
83
+ - Why it's currently failing
84
+ - What the fix needs to achieve
85
+
86
+ #### 3. Fix the Code
87
+
88
+ Modify **only non-test files** to make the test pass.
89
+
90
+ **CRITICAL**: Do not modify test files. The test is the specification. Your job is to make the code meet the specification.
91
+
92
+ If you believe the test is wrong, escalate—don't modify it.
93
+
94
+ #### 4. Verify
95
+
96
+ Run the test to confirm it passes:
97
+
98
+ ```bash
99
+ [test command]
100
+ ```
101
+
102
+ If it still fails, keep fixing. If you're stuck, escalate.
103
+
104
+ #### 5. Update Task File
105
+
106
+ After fixing:
107
+
108
+ ```yaml
109
+ status: needs_review
110
+ outcome: |
111
+ Fix applied:
112
+ - Modified [file path]: [what changed]
113
+ - Root cause was: [what was actually wrong]
114
+
115
+ Test result:
116
+ - [test name] now passes
117
+
118
+ Files changed:
119
+ - [list of modified files]
120
+ ```
121
+
122
+ #### 6. Return
123
+
124
+ Report:
125
+ - What was fixed
126
+ - Files modified
127
+ - Test result (pass/fail)
128
+
129
+ ## Escalation
130
+
131
+ **Stop and escalate if:**
132
+
133
+ - **Test mode**: Can't write a meaningful test for the hypothesis (hypothesis too vague)
134
+ - **Fix mode**: The test seems wrong (tests the wrong thing, has a bug itself)
135
+ - **Fix mode**: Can't fix without modifying test files
136
+ - **Either mode**: ADR conflict prevents the approach
137
+ - **Either mode**: Blocked by missing information
138
+
139
+ **When escalating:**
140
+
141
+ ```
142
+ ## Escalation
143
+
144
+ **Mode**: [test/fix]
145
+
146
+ **Reason**: [why you can't proceed]
147
+
148
+ **What I found**: [relevant details]
149
+
150
+ **Recommendation**: [what should happen next]
151
+ ```
152
+
153
+ ## Principles
154
+
155
+ **One mode per session.** You either write a test OR fix code, never both. This ensures clean separation.
156
+
157
+ **Tests are specifications.** In fix mode, the test defines correct behavior. Don't question it—make the code conform.
158
+
159
+ **Fix mode: code only.** Never touch test files in fix mode. If the test is wrong, escalate.
160
+
161
+ **Test mode: fail is success.** A test that fails (because the bug exists) is exactly what we want. A passing test means the hypothesis is wrong.
162
+
163
+ **Outcome is context.** Write clear outcomes so the next session (or agent) understands what was done.
@@ -0,0 +1,83 @@
1
+ ---
2
+ description: Capture architectural decisions and tribal knowledge before clearing session context
3
+ allowed-tools: Task, AskUserQuestion
4
+ argument-hint: (no arguments)
5
+ ---
6
+
7
+ # Finalize Command
8
+
9
+ Capture architectural decisions and tribal knowledge before ending a session.
10
+
11
+ ## Purpose
12
+
13
+ Preserve valuable insights from your session:
14
+ - Architectural decisions → ADRs
15
+ - Tribal knowledge/gotchas → CLAUDE.md updates
16
+
17
+ This ensures nothing is lost when context is cleared.
18
+
19
+ ## How It Works
20
+
21
+ You review the conversation to identify architectural decisions and tribal knowledge, present findings to the user for confirmation, then invoke specialized agents to capture them.
22
+
23
+ ## What Gets Captured
24
+
25
+ ### Architectural Decisions (ADRs)
26
+ - Technical choices with documented alternatives
27
+ - "We decided X because Y" decisions
28
+ - Framework or library selections
29
+ - Design pattern adoptions
30
+
31
+ ### Tribal Knowledge (CLAUDE.md)
32
+ - Gotchas discovered during debugging
33
+ - Non-obvious behaviors that caused confusion
34
+ - Patterns established during the session
35
+ - "Always do X" or "Never do Y" lessons
36
+
37
+ ### What Doesn't Qualify
38
+
39
+ ADR scope:
40
+ - Bug fixes
41
+ - Implementation details
42
+ - Obvious technical choices
43
+
44
+ CLAUDE.md scope:
45
+ - Standard setup procedures
46
+ - Information already in README or package.json
47
+ - Common knowledge (e.g., "npm install installs packages")
48
+
49
+ ## Session Review Process
50
+
51
+ 1. Analyze the conversation for architectural decisions and tribal knowledge
52
+ 2. **Evaluate against criteria and make your assessment** - apply the ADR and CLAUDE.md criteria below
53
+ 3. **Present your findings and act on them** - tell the user what you identified and capture it
54
+ 4. If user disagrees with your assessment, adjust accordingly
55
+ 5. Report what was documented
56
+
57
+ **ADR criteria** - Worth documenting if:
58
+ - Technical choices with documented alternatives ("We decided X because Y")
59
+ - Framework or library selections with rationale
60
+ - Design pattern adoptions that future work should follow
61
+
62
+ **CLAUDE.md criteria** - Worth documenting if:
63
+ - Non-obvious gotchas discovered during the session
64
+ - "Always do X" or "Never do Y" lessons learned
65
+ - Patterns established that aren't obvious from the code
66
+
67
+ **Present your assessment:**
68
+
69
+ ```
70
+ ## Session Learnings Assessment
71
+
72
+ **ADRs**: [Either "I identified architectural decisions worth documenting: [list with brief reasons]. Creating ADRs now." OR "No architectural decisions in this session warrant ADRs."]
73
+
74
+ **CLAUDE.md**: [Either "I identified tribal knowledge worth capturing: [list]. Updating CLAUDE.md now." OR "No tribal knowledge discovered that warrants CLAUDE.md updates."]
75
+ ```
76
+
77
+ Then invoke agents to capture what you identified:
78
+ - **adr-agent**: Creates ADR files with proper numbering, schema, and index updates
79
+ - **claude-md-agent**: Adds operational insights to the appropriate CLAUDE.md file
80
+
81
+ ## If Nothing Identified
82
+
83
+ If the session contained no architectural decisions or tribal knowledge worth capturing, report that to the user and mark the session ready to clear.
@@ -0,0 +1,5 @@
1
+ ---
2
+ description: Navigate project planning and execution workflows
3
+ ---
4
+
5
+ Use the orchestration skill to guide the user through planning or execution workflows.
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * adr-list.js - List ADRs with optional filtering by tags and status
5
+ *
6
+ * This CLI script scans all YAML ADR files in the project's .claude/adrs/
7
+ * and returns their metadata, with optional filtering capabilities. Designed
8
+ * to support progressive ADR filtering (per ADR-007) by providing descriptions
9
+ * without full content.
10
+ *
11
+ * Usage:
12
+ * node ~/.claude/scripts/adr-list.js # All ADRs
13
+ * node ~/.claude/scripts/adr-list.js --tags=architecture # Filter by single tag
14
+ * node ~/.claude/scripts/adr-list.js --tags=agents,planning # Filter by multiple tags (OR logic)
15
+ * node ~/.claude/scripts/adr-list.js --status=Accepted # Filter by status
16
+ * node ~/.claude/scripts/adr-list.js --tags=adrs --status=Accepted # Combine filters
17
+ *
18
+ * Flags:
19
+ * --tags=tag1,tag2 Filter ADRs that have ANY of the specified tags (OR logic)
20
+ * --status=Status Filter ADRs that match the exact status string
21
+ *
22
+ * Output:
23
+ * JSON array to stdout: [{ id, title, description, tags, status, date }]
24
+ *
25
+ * Example output:
26
+ * [
27
+ * {
28
+ * "id": "ADR-001",
29
+ * "title": "Use YAML ADRs for Architectural Decisions",
30
+ * "description": "Establishes YAML-formatted ADRs as the primary mechanism...",
31
+ * "tags": ["architecture", "adrs", "format"],
32
+ * "status": "Accepted",
33
+ * "date": "2025-11-22"
34
+ * }
35
+ * ]
36
+ *
37
+ * Note: This script supplements the adr-agent (per ADR-009), providing
38
+ * quick CLI access to ADR listings without invoking the full agent.
39
+ */
40
+
41
+ const fs = require('fs');
42
+ const path = require('path');
43
+ const yaml = require('js-yaml');
44
+
45
+ // ADRs are in the project's .claude/adrs/ directory (relative to CWD)
46
+ const ADRS_DIR = path.join(process.cwd(), '.claude', 'adrs');
47
+
48
+ /**
49
+ * Parse command line arguments for --tags and --status flags
50
+ * @returns {{ tags: string[] | null, status: string | null }}
51
+ */
52
+ function parseArgs() {
53
+ const args = process.argv.slice(2);
54
+ let tags = null;
55
+ let status = null;
56
+
57
+ for (const arg of args) {
58
+ // Handle --tags=value or --tags value
59
+ if (arg.startsWith('--tags=')) {
60
+ const value = arg.slice('--tags='.length);
61
+ tags = value.split(',').map(t => t.trim()).filter(t => t.length > 0);
62
+ }
63
+ // Handle --status=value or --status value
64
+ else if (arg.startsWith('--status=')) {
65
+ status = arg.slice('--status='.length).trim();
66
+ }
67
+ }
68
+
69
+ return { tags, status };
70
+ }
71
+
72
+ /**
73
+ * Read and parse a YAML ADR file, extracting metadata fields
74
+ * @param {string} filePath - Absolute path to the YAML file
75
+ * @returns {{ id: string, title: string, description: string, tags: string[], status: string, date: string } | null}
76
+ */
77
+ function parseAdrFile(filePath) {
78
+ try {
79
+ const content = fs.readFileSync(filePath, 'utf8');
80
+ const data = yaml.load(content);
81
+
82
+ // Extract fields, handling missing optional fields gracefully
83
+ const id = data?.id || path.basename(filePath, '.yaml');
84
+ const title = data?.title || '';
85
+ // Clean up description - remove trailing newlines from YAML multi-line strings
86
+ const description = (data?.description || '').trim();
87
+ const tags = Array.isArray(data?.tags) ? data.tags : [];
88
+ const status = data?.status || '';
89
+ const date = data?.date || '';
90
+
91
+ return { id, title, description, tags, status, date };
92
+ } catch (error) {
93
+ // Log to stderr so it doesn't pollute JSON output
94
+ console.error(`Warning: Failed to parse ${filePath}: ${error.message}`);
95
+ return null;
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Check if an ADR matches the given tag filter (OR logic)
101
+ * @param {string[]} adrTags - Tags from the ADR
102
+ * @param {string[]} filterTags - Tags to filter by
103
+ * @returns {boolean} - True if ADR has ANY of the filter tags
104
+ */
105
+ function matchesTags(adrTags, filterTags) {
106
+ if (!filterTags || filterTags.length === 0) {
107
+ return true; // No filter = match all
108
+ }
109
+ // OR logic: return true if ADR has ANY of the filter tags
110
+ return filterTags.some(filterTag => adrTags.includes(filterTag));
111
+ }
112
+
113
+ /**
114
+ * Check if an ADR matches the given status filter (exact match)
115
+ * @param {string} adrStatus - Status from the ADR
116
+ * @param {string | null} filterStatus - Status to filter by
117
+ * @returns {boolean} - True if status matches exactly
118
+ */
119
+ function matchesStatus(adrStatus, filterStatus) {
120
+ if (!filterStatus) {
121
+ return true; // No filter = match all
122
+ }
123
+ return adrStatus === filterStatus;
124
+ }
125
+
126
+ /**
127
+ * Scan ADRs directory and collect all ADR metadata with optional filtering
128
+ * @param {{ tags: string[] | null, status: string | null }} filters
129
+ * @returns {Array<{ id: string, title: string, description: string, tags: string[], status: string, date: string }>}
130
+ */
131
+ function collectAdrs(filters) {
132
+ const adrs = [];
133
+
134
+ // Check if ADRs directory exists
135
+ if (!fs.existsSync(ADRS_DIR)) {
136
+ console.error(`Warning: ADRs directory not found: ${ADRS_DIR}`);
137
+ return adrs;
138
+ }
139
+
140
+ // Read all .yaml files in the ADRs directory
141
+ const files = fs.readdirSync(ADRS_DIR)
142
+ .filter(file => file.endsWith('.yaml'))
143
+ .sort() // Sort alphabetically for consistent ordering
144
+ .map(file => path.join(ADRS_DIR, file));
145
+
146
+ // Process each ADR file
147
+ for (const filePath of files) {
148
+ const adr = parseAdrFile(filePath);
149
+ if (!adr) continue;
150
+
151
+ // Apply filters
152
+ if (!matchesTags(adr.tags, filters.tags)) continue;
153
+ if (!matchesStatus(adr.status, filters.status)) continue;
154
+
155
+ adrs.push(adr);
156
+ }
157
+
158
+ return adrs;
159
+ }
160
+
161
+ // Main execution
162
+ function main() {
163
+ const filters = parseArgs();
164
+ const adrs = collectAdrs(filters);
165
+
166
+ // Output JSON to stdout
167
+ console.log(JSON.stringify(adrs, null, 2));
168
+ }
169
+
170
+ main();
@@ -0,0 +1,125 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * adr-tags.js - List all distinct tags across all ADRs with usage counts
5
+ *
6
+ * This CLI script scans all YAML ADR files in the project's .claude/adrs/
7
+ * and extracts tag information, producing a sorted summary of tag usage.
8
+ *
9
+ * Usage:
10
+ * node ~/.claude/scripts/adr-tags.js
11
+ *
12
+ * Output:
13
+ * JSON array to stdout: [{ tag, count, adrs }] sorted by count descending
14
+ *
15
+ * Example output:
16
+ * [
17
+ * { "tag": "architecture", "count": 8, "adrs": ["ADR-001", "ADR-003"] },
18
+ * { "tag": "agents", "count": 4, "adrs": ["ADR-003", "ADR-004"] }
19
+ * ]
20
+ *
21
+ * Note: This script supplements the adr-agent (per ADR-009), providing
22
+ * quick CLI access to tag information without invoking the full agent.
23
+ */
24
+
25
+ const fs = require('fs');
26
+ const path = require('path');
27
+ const yaml = require('js-yaml');
28
+
29
+ // ADRs are in the project's .claude/adrs/ directory (relative to CWD)
30
+ const ADRS_DIR = path.join(process.cwd(), '.claude', 'adrs');
31
+
32
+ /**
33
+ * Read and parse a YAML ADR file, extracting id and tags
34
+ * @param {string} filePath - Absolute path to the YAML file
35
+ * @returns {{ id: string, tags: string[] } | null} - Parsed data or null on error
36
+ */
37
+ function parseAdrFile(filePath) {
38
+ try {
39
+ const content = fs.readFileSync(filePath, 'utf8');
40
+ const data = yaml.load(content);
41
+
42
+ // Extract id and tags, handling missing fields gracefully
43
+ const id = data?.id || path.basename(filePath, '.yaml');
44
+ const tags = Array.isArray(data?.tags) ? data.tags : [];
45
+
46
+ return { id, tags };
47
+ } catch (error) {
48
+ // Log to stderr so it doesn't pollute JSON output
49
+ console.error(`Warning: Failed to parse ${filePath}: ${error.message}`);
50
+ return null;
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Scan ADRs directory and collect all tag information
56
+ * @returns {Map<string, string[]>} - Map of tag -> array of ADR ids
57
+ */
58
+ function collectTags() {
59
+ const tagMap = new Map();
60
+
61
+ // Check if ADRs directory exists
62
+ if (!fs.existsSync(ADRS_DIR)) {
63
+ console.error(`Warning: ADRs directory not found: ${ADRS_DIR}`);
64
+ return tagMap;
65
+ }
66
+
67
+ // Read all .yaml files in the ADRs directory
68
+ const files = fs.readdirSync(ADRS_DIR)
69
+ .filter(file => file.endsWith('.yaml'))
70
+ .map(file => path.join(ADRS_DIR, file));
71
+
72
+ // Process each ADR file
73
+ for (const filePath of files) {
74
+ const adr = parseAdrFile(filePath);
75
+ if (!adr) continue;
76
+
77
+ // Add this ADR's id to each of its tags
78
+ for (const tag of adr.tags) {
79
+ if (!tagMap.has(tag)) {
80
+ tagMap.set(tag, []);
81
+ }
82
+ tagMap.get(tag).push(adr.id);
83
+ }
84
+ }
85
+
86
+ return tagMap;
87
+ }
88
+
89
+ /**
90
+ * Format tag data as sorted output array
91
+ * @param {Map<string, string[]>} tagMap - Map of tag -> array of ADR ids
92
+ * @returns {Array<{ tag: string, count: number, adrs: string[] }>}
93
+ */
94
+ function formatOutput(tagMap) {
95
+ const result = [];
96
+
97
+ for (const [tag, adrs] of tagMap.entries()) {
98
+ result.push({
99
+ tag,
100
+ count: adrs.length,
101
+ adrs: adrs.sort() // Sort ADR ids alphabetically within each tag
102
+ });
103
+ }
104
+
105
+ // Sort by count descending, then alphabetically by tag name for ties
106
+ result.sort((a, b) => {
107
+ if (b.count !== a.count) {
108
+ return b.count - a.count;
109
+ }
110
+ return a.tag.localeCompare(b.tag);
111
+ });
112
+
113
+ return result;
114
+ }
115
+
116
+ // Main execution
117
+ function main() {
118
+ const tagMap = collectTags();
119
+ const output = formatOutput(tagMap);
120
+
121
+ // Output JSON to stdout
122
+ console.log(JSON.stringify(output, null, 2));
123
+ }
124
+
125
+ main();