cc-dev-template 0.1.92 → 0.1.94
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/bin/install.js +21 -2
- package/package.json +1 -1
- package/src/agents/spec-writer.md +14 -9
- package/src/skills/ship/references/step-3-research.md +23 -10
- package/src/skills/ship/references/step-4-design.md +9 -11
- package/src/skills/ship/references/step-5-spec.md +7 -5
- package/src/scripts/read-guard-hook.json +0 -15
- package/src/scripts/read-guard.js +0 -146
package/bin/install.js
CHANGED
|
@@ -252,7 +252,6 @@ const settingsFile = path.join(CLAUDE_DIR, 'settings.json');
|
|
|
252
252
|
|
|
253
253
|
if (fs.existsSync(mergeSettingsPath)) {
|
|
254
254
|
const configs = [
|
|
255
|
-
{ file: 'read-guard-hook.json', name: 'Context guard for large reads' },
|
|
256
255
|
{ file: 'task-output-guard-hook.json', name: 'TaskOutput context guard' },
|
|
257
256
|
{ file: 'statusline-config.json', name: 'Custom status line' },
|
|
258
257
|
// Spinner verbs - choose one (Star Trek or Factorio)
|
|
@@ -344,7 +343,9 @@ const deprecatedFiles = [
|
|
|
344
343
|
path.join(CLAUDE_DIR, 'hooks', 'bash-overflow-guard.sh'),
|
|
345
344
|
path.join(CLAUDE_DIR, 'scripts', 'bash-overflow-hook.json'),
|
|
346
345
|
path.join(CLAUDE_DIR, 'scripts', 'env-config.json'),
|
|
347
|
-
path.join(CLAUDE_DIR, 'scripts', 'spinner-verbs-helldivers.json')
|
|
346
|
+
path.join(CLAUDE_DIR, 'scripts', 'spinner-verbs-helldivers.json'),
|
|
347
|
+
path.join(CLAUDE_DIR, 'scripts', 'read-guard.js'),
|
|
348
|
+
path.join(CLAUDE_DIR, 'scripts', 'read-guard-hook.json')
|
|
348
349
|
];
|
|
349
350
|
|
|
350
351
|
deprecatedFiles.forEach(file => {
|
|
@@ -388,6 +389,24 @@ if (fs.existsSync(settingsFile)) {
|
|
|
388
389
|
});
|
|
389
390
|
}
|
|
390
391
|
|
|
392
|
+
// Remove read-guard hooks from settings
|
|
393
|
+
if (settings.hooks) {
|
|
394
|
+
['PreToolUse'].forEach(hookType => {
|
|
395
|
+
if (settings.hooks[hookType] && Array.isArray(settings.hooks[hookType])) {
|
|
396
|
+
const originalLength = settings.hooks[hookType].length;
|
|
397
|
+
settings.hooks[hookType] = settings.hooks[hookType].filter(hook => {
|
|
398
|
+
const command = hook.hooks?.[0]?.command || '';
|
|
399
|
+
return !command.includes('read-guard');
|
|
400
|
+
});
|
|
401
|
+
if (settings.hooks[hookType].length < originalLength) {
|
|
402
|
+
console.log(`✓ Removed deprecated read-guard hook from ${hookType}`);
|
|
403
|
+
settingsModified = true;
|
|
404
|
+
cleanupPerformed = true;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
|
|
391
410
|
// Remove bash-overflow-guard hooks from settings
|
|
392
411
|
if (settings.hooks) {
|
|
393
412
|
['PostToolUse'].forEach(hookType => {
|
package/package.json
CHANGED
|
@@ -43,11 +43,15 @@ When prompted to review a spec:
|
|
|
43
43
|
|
|
44
44
|
1. Read `{spec_dir}/spec.md` and all upstream artifacts (intent.md, research.md, design.md)
|
|
45
45
|
2. Run every check in the review checklist below
|
|
46
|
-
3.
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
- **
|
|
50
|
-
|
|
46
|
+
3. **Focus on medium-to-high severity issues only.** Classify each issue:
|
|
47
|
+
- **HIGH**: Something legitimately forgotten, missing, or wrong that would cause implementation problems — missing API contract, wrong data model, contradicts research, missing edge case that could cause bugs
|
|
48
|
+
- **MEDIUM**: Ambiguity or gap that could lead an implementer astray — vague acceptance criteria, unclear integration point, unverifiable criterion
|
|
49
|
+
- **LOW**: Minor wording, slight clarifications, formatting, stylistic improvements — **ignore these entirely**, do not fix or report them
|
|
50
|
+
4. Fix every medium-to-high issue found directly in spec.md — do not report issues, fix them
|
|
51
|
+
5. After fixing, re-run the checklist to verify the fixes
|
|
52
|
+
6. Return one of three verdicts:
|
|
53
|
+
- **APPROVED** — zero medium-to-high issues found on any check. The spec is clean.
|
|
54
|
+
- **APPROVED_WITH_FIXES** — medium-to-high issues were found and fixed. Another reviewer must verify the fixes.
|
|
51
55
|
- **ISSUES REMAINING** — unfixable issues exist (e.g., missing prerequisites that need user action).
|
|
52
56
|
|
|
53
57
|
## Spec Format
|
|
@@ -163,11 +167,11 @@ Sections:
|
|
|
163
167
|
- Out of Scope: N exclusions
|
|
164
168
|
```
|
|
165
169
|
|
|
166
|
-
**Review mode (zero issues
|
|
170
|
+
**Review mode (zero medium-to-high issues — clean pass):**
|
|
167
171
|
```
|
|
168
172
|
APPROVED
|
|
169
173
|
|
|
170
|
-
0 issues found.
|
|
174
|
+
0 medium-to-high issues found.
|
|
171
175
|
All 12 checks passed.
|
|
172
176
|
```
|
|
173
177
|
|
|
@@ -176,9 +180,10 @@ All 12 checks passed.
|
|
|
176
180
|
APPROVED_WITH_FIXES
|
|
177
181
|
|
|
178
182
|
N issues found and fixed:
|
|
179
|
-
- [Check Name]: what was fixed
|
|
183
|
+
- [HIGH] [Check Name]: what was fixed
|
|
184
|
+
- [MEDIUM] [Check Name]: what was fixed
|
|
180
185
|
...
|
|
181
|
-
All 12 checks now pass
|
|
186
|
+
All 12 checks now pass for medium-to-high issues.
|
|
182
187
|
```
|
|
183
188
|
|
|
184
189
|
**Review mode (unfixable issues remain):**
|
|
@@ -1,30 +1,43 @@
|
|
|
1
1
|
# Objective Research
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Sub-agents research the codebase using ONLY the questions — they do not see the intent document. This produces factual, objective documentation about the codebase without implementation bias.
|
|
4
4
|
|
|
5
|
-
This is the critical contamination prevention step. The research
|
|
5
|
+
This is the critical contamination prevention step. The research agents answer questions about what EXISTS in the codebase. They do not know what feature is being built, so they cannot steer findings toward a particular implementation.
|
|
6
|
+
|
|
7
|
+
Questions are distributed across parallel researchers by category — each agent gets a focused subset, giving it more context per question and a more manageable scope.
|
|
6
8
|
|
|
7
9
|
## Create Tasks
|
|
8
10
|
|
|
9
11
|
Create these tasks and work through them in order:
|
|
10
12
|
|
|
11
|
-
1. "
|
|
12
|
-
2. "
|
|
13
|
-
3. "
|
|
13
|
+
1. "Group questions and distribute to parallel researchers" — spawn multiple objective-researchers
|
|
14
|
+
2. "Merge research" — combine results into a single file
|
|
15
|
+
3. "Review research with user" — present findings
|
|
16
|
+
4. "Begin design discussion" — proceed to the next phase
|
|
17
|
+
|
|
18
|
+
## Task 1: Distribute Research
|
|
19
|
+
|
|
20
|
+
Read `{spec_dir}/questions.md` yourself. Identify the category sections (the `##` headers the question-generator produces).
|
|
14
21
|
|
|
15
|
-
|
|
22
|
+
For each category, spawn an `objective-researcher` with that category's questions passed inline. Spawn ALL agents in parallel — use multiple Agent tool calls in a single message.
|
|
16
23
|
|
|
17
|
-
|
|
24
|
+
Each agent writes to a separate file to avoid write conflicts:
|
|
18
25
|
|
|
19
26
|
```
|
|
20
27
|
Agent tool:
|
|
21
28
|
subagent_type: "objective-researcher"
|
|
22
|
-
prompt: "Research the codebase to answer these questions. Write your findings to {spec_dir}/research.md.\n\n{paste
|
|
29
|
+
prompt: "Research the codebase to answer these questions. Write your findings to {spec_dir}/research-{category-slug}.md.\n\n{paste this category's questions here}"
|
|
23
30
|
```
|
|
24
31
|
|
|
32
|
+
If there are many small categories (6+), group related ones together to keep the agent count reasonable — 3 to 5 parallel agents is the sweet spot.
|
|
33
|
+
|
|
25
34
|
The objective-researcher has full codebase access (Read, Grep, Glob, Bash) but no knowledge of the feature being built. It receives only the questions via its prompt — it never reads from docs/.
|
|
26
35
|
|
|
27
|
-
## Task 2:
|
|
36
|
+
## Task 2: Merge Research
|
|
37
|
+
|
|
38
|
+
After all researchers complete, read each `research-{slug}.md` file. Concatenate them into a single `{spec_dir}/research.md` (preserving the section structure from each file). Then delete the individual `research-{slug}.md` files — downstream steps only need the merged file.
|
|
39
|
+
|
|
40
|
+
## Task 3: Review Research
|
|
28
41
|
|
|
29
42
|
Read `{spec_dir}/research.md` and present a summary to the user. Highlight:
|
|
30
43
|
|
|
@@ -36,7 +49,7 @@ The user may add context the researcher missed, or flag patterns that are outdat
|
|
|
36
49
|
|
|
37
50
|
If the research is thin or missing critical areas, spawn the objective-researcher again with additional targeted questions.
|
|
38
51
|
|
|
39
|
-
## Task
|
|
52
|
+
## Task 4: Proceed
|
|
40
53
|
|
|
41
54
|
Update `{spec_dir}/state.yaml` — set `phase: design`.
|
|
42
55
|
|
|
@@ -19,12 +19,7 @@ From the research document, identify:
|
|
|
19
19
|
|
|
20
20
|
**Patterns to Follow**: Code patterns from the codebase relevant to this feature. If the research found multiple patterns for the same thing (e.g., old way vs. new way of handling forms), list them all and flag for disambiguation.
|
|
21
21
|
|
|
22
|
-
**Design Questions**: Decisions that need human input before implementation.
|
|
23
|
-
|
|
24
|
-
- State the question clearly
|
|
25
|
-
- Provide Option A and Option B (grounded in what the research found)
|
|
26
|
-
- Note which option you'd recommend and why
|
|
27
|
-
- Leave room for the user to propose Option C
|
|
22
|
+
**Design Questions**: Decisions that need human input before implementation. Prepare an ordered list of questions, prioritizing foundational decisions first (architecture, patterns) before detail-level ones (error handling, edge cases).
|
|
28
23
|
|
|
29
24
|
Common design questions include:
|
|
30
25
|
|
|
@@ -36,13 +31,16 @@ Common design questions include:
|
|
|
36
31
|
|
|
37
32
|
## Task 2: Resolve Decisions
|
|
38
33
|
|
|
39
|
-
|
|
34
|
+
Walk through each design question ONE AT A TIME using the `AskUserQuestion` tool. For each question:
|
|
35
|
+
|
|
36
|
+
1. State the question clearly
|
|
37
|
+
2. Provide concrete options (A, B, etc.) grounded in what the research found
|
|
38
|
+
3. Include your recommendation and reasoning — tell the user which option you'd choose and why
|
|
39
|
+
4. Leave room for the user to propose an alternative
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
- If the user isn't sure, provide your reasoning
|
|
43
|
-
- If a decision requires understanding external technology the codebase doesn't use yet, note it as an open item — the spec phase can handle external research
|
|
41
|
+
Wait for the user's response before moving to the next question. If the user isn't sure, elaborate on your recommendation. If a decision requires understanding external technology the codebase doesn't use yet, note it as an open item — the spec phase can handle external research.
|
|
44
42
|
|
|
45
|
-
|
|
43
|
+
Continue until all design questions are resolved.
|
|
46
44
|
|
|
47
45
|
## Task 3: Write design.md
|
|
48
46
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Spec Generation
|
|
2
2
|
|
|
3
|
-
The orchestrator spawns a spec-writer agent to generate the spec, then spawns a fresh instance of the same agent to review and fix it. Each review is a clean context window — the reviewer didn't write the spec, so it reads with fresh eyes.
|
|
3
|
+
The orchestrator spawns a spec-writer agent to generate the spec, then spawns a fresh instance of the same agent to review and fix it. Each review is a clean context window — the reviewer didn't write the spec, so it reads with fresh eyes. The reviewer focuses on medium-to-high severity issues only — if a reviewer only fixes minor issues, the orchestrator moves on rather than over-rotating. If medium-to-high issues are fixed, those fixes must be verified by another fresh reviewer.
|
|
4
4
|
|
|
5
5
|
The spec is the last line of defense. Any error or ambiguity here multiplies through task breakdown and implementation.
|
|
6
6
|
|
|
@@ -38,17 +38,19 @@ Agent tool:
|
|
|
38
38
|
|
|
39
39
|
## Task 3: Review Loop
|
|
40
40
|
|
|
41
|
-
Spawn a FRESH instance of spec-writer in review mode
|
|
41
|
+
Spawn a FRESH instance of spec-writer in review mode. At least one review is mandatory.
|
|
42
42
|
|
|
43
43
|
```
|
|
44
44
|
Agent tool:
|
|
45
45
|
subagent_type: "spec-writer"
|
|
46
|
-
prompt: "Review the spec at {spec_dir}/spec.md against the upstream artifacts (intent.md, research.md, design.md). Run the full 12-point checklist. Fix every issue
|
|
46
|
+
prompt: "Review the spec at {spec_dir}/spec.md against the upstream artifacts (intent.md, research.md, design.md). Run the full 12-point checklist. Focus on medium-to-high severity issues — ignore minor wording or formatting. Fix every medium-to-high issue directly in spec.md. Return APPROVED if zero medium-to-high issues found, APPROVED_WITH_FIXES with severity tags if issues were found and fixed, or ISSUES REMAINING for anything you cannot auto-fix."
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
-
**If APPROVED** (zero issues found): The spec is verified clean. Move to Task 4.
|
|
49
|
+
**If APPROVED** (zero medium-to-high issues found): The spec is verified clean. Move to Task 4.
|
|
50
50
|
|
|
51
|
-
**If APPROVED_WITH_FIXES**:
|
|
51
|
+
**If APPROVED_WITH_FIXES**: Parse the severity of each fix from the reviewer's output:
|
|
52
|
+
- If ANY fix was **HIGH** or **MEDIUM** — those fixes need verification. Spawn another fresh instance to review again.
|
|
53
|
+
- If somehow all fixes were low-severity — the reviewer is finding diminishing returns. Move to Task 4.
|
|
52
54
|
|
|
53
55
|
**If ISSUES REMAINING**: Spawn another fresh instance to review again. The previous reviewer already fixed what it could — the next reviewer may catch different things or resolve what the last one couldn't.
|
|
54
56
|
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* read-guard.js - Block large file reads to preserve context
|
|
5
|
-
*
|
|
6
|
-
* This script intercepts Read tool calls and blocks reads of large files that would
|
|
7
|
-
* consume excessive context. It forces Claude to use more targeted approaches like
|
|
8
|
-
* Grep to find relevant sections, then Read with offset/limit parameters.
|
|
9
|
-
*
|
|
10
|
-
* Usage:
|
|
11
|
-
* echo '{"tool_input":{"file_path":"/path/to/file.js"}}' | node read-guard.js
|
|
12
|
-
*
|
|
13
|
-
* Input format (JSON via stdin):
|
|
14
|
-
* {
|
|
15
|
-
* "tool_input": {
|
|
16
|
-
* "file_path": "/absolute/path/to/file.js",
|
|
17
|
-
* "limit": 100, // optional - if present, allow the read
|
|
18
|
-
* "offset": 0 // optional
|
|
19
|
-
* }
|
|
20
|
-
* }
|
|
21
|
-
*
|
|
22
|
-
* Exit codes:
|
|
23
|
-
* 0 - Allow the read (outputs nothing or JSON to allow/deny)
|
|
24
|
-
*
|
|
25
|
-
* Environment variables:
|
|
26
|
-
* CONTEXT_GUARD_TOKEN_LIMIT - Token threshold (default: 5000)
|
|
27
|
-
*
|
|
28
|
-
* Token estimation:
|
|
29
|
-
* Rough heuristic: file_size_bytes / 4 ≈ tokens
|
|
30
|
-
* This catches obvious context bloat without needing a tokenizer.
|
|
31
|
-
*/
|
|
32
|
-
|
|
33
|
-
const fs = require('fs');
|
|
34
|
-
|
|
35
|
-
const TOKEN_THRESHOLD = parseInt(process.env.CONTEXT_GUARD_TOKEN_LIMIT || '5000', 10);
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Read JSON from stdin
|
|
39
|
-
* @returns {Promise<object | null>} - Parsed JSON or null if invalid
|
|
40
|
-
*/
|
|
41
|
-
async function readStdin() {
|
|
42
|
-
return new Promise((resolve) => {
|
|
43
|
-
let data = '';
|
|
44
|
-
|
|
45
|
-
process.stdin.setEncoding('utf8');
|
|
46
|
-
process.stdin.on('data', chunk => {
|
|
47
|
-
data += chunk;
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
process.stdin.on('end', () => {
|
|
51
|
-
try {
|
|
52
|
-
resolve(JSON.parse(data));
|
|
53
|
-
} catch {
|
|
54
|
-
resolve(null);
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
process.stdin.on('error', () => {
|
|
59
|
-
resolve(null);
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Format file size for display
|
|
66
|
-
* @param {number} bytes - File size in bytes
|
|
67
|
-
* @returns {string} - Human-readable size
|
|
68
|
-
*/
|
|
69
|
-
function formatSize(bytes) {
|
|
70
|
-
if (bytes < 1024) return `${bytes}B`;
|
|
71
|
-
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
|
|
72
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Main execution
|
|
77
|
-
*/
|
|
78
|
-
async function main() {
|
|
79
|
-
const inputData = await readStdin();
|
|
80
|
-
|
|
81
|
-
// If we can't parse input, allow the read
|
|
82
|
-
if (!inputData) {
|
|
83
|
-
process.exit(0);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const toolInput = inputData.tool_input || {};
|
|
87
|
-
const filePath = toolInput.file_path;
|
|
88
|
-
const limit = toolInput.limit;
|
|
89
|
-
|
|
90
|
-
// If limit is already specified, Claude is being intentional - allow it
|
|
91
|
-
if (limit !== undefined) {
|
|
92
|
-
process.exit(0);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Image files: token consumption based on dimensions, not file size
|
|
96
|
-
const imageExtensions = ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg', '.bmp', '.ico', '.tiff', '.tif'];
|
|
97
|
-
const ext = filePath.toLowerCase().slice(filePath.lastIndexOf('.'));
|
|
98
|
-
if (imageExtensions.includes(ext)) {
|
|
99
|
-
process.exit(0);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// If file doesn't exist or no path, let Read tool handle the error
|
|
103
|
-
if (!filePath || !fs.existsSync(filePath)) {
|
|
104
|
-
process.exit(0);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Get file stats
|
|
108
|
-
let stats;
|
|
109
|
-
try {
|
|
110
|
-
stats = fs.statSync(filePath);
|
|
111
|
-
} catch {
|
|
112
|
-
// Can't stat file, let Read tool handle it
|
|
113
|
-
process.exit(0);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Skip directories
|
|
117
|
-
if (stats.isDirectory()) {
|
|
118
|
-
process.exit(0);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Estimate tokens from file size
|
|
122
|
-
const fileSizeBytes = stats.size;
|
|
123
|
-
const estimatedTokens = Math.ceil(fileSizeBytes / 4);
|
|
124
|
-
|
|
125
|
-
// If under threshold, allow the read
|
|
126
|
-
if (estimatedTokens <= TOKEN_THRESHOLD) {
|
|
127
|
-
process.exit(0);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// Block the read with guidance
|
|
131
|
-
const output = {
|
|
132
|
-
hookSpecificOutput: {
|
|
133
|
-
hookEventName: "PreToolUse",
|
|
134
|
-
permissionDecision: "deny",
|
|
135
|
-
permissionDecisionReason: `This file (~${estimatedTokens.toLocaleString()} tokens, ${formatSize(fileSizeBytes)}) would consume significant context. Use Grep to find relevant sections first, then Read with offset/limit parameters to read specific portions. If you need the full file, use multiple parallel Read calls with offset/limit to read it in chunks.`
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
console.log(JSON.stringify(output));
|
|
140
|
-
process.exit(0);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
main().catch(() => {
|
|
144
|
-
// If anything goes wrong, allow the read to avoid disrupting workflow
|
|
145
|
-
process.exit(0);
|
|
146
|
-
});
|