cc-dev-template 0.1.27 → 0.1.28
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
CHANGED
|
@@ -96,11 +96,21 @@ if (fs.existsSync(skillsDir)) {
|
|
|
96
96
|
console.log('\nHooks:');
|
|
97
97
|
const hooksDir = path.join(SRC_DIR, 'hooks');
|
|
98
98
|
if (fs.existsSync(hooksDir)) {
|
|
99
|
-
const
|
|
99
|
+
const hookShellScripts = fs.readdirSync(hooksDir).filter(f => f.endsWith('.sh'));
|
|
100
|
+
const hookJsScripts = fs.readdirSync(hooksDir).filter(f => f.endsWith('.js'));
|
|
100
101
|
const hookConfigs = fs.readdirSync(hooksDir).filter(f => f.endsWith('.json'));
|
|
101
102
|
|
|
102
103
|
// Copy shell scripts and make executable
|
|
103
|
-
|
|
104
|
+
hookShellScripts.forEach(file => {
|
|
105
|
+
const src = path.join(hooksDir, file);
|
|
106
|
+
const dest = path.join(CLAUDE_DIR, 'hooks', file);
|
|
107
|
+
fs.copyFileSync(src, dest);
|
|
108
|
+
fs.chmodSync(dest, 0o755); // Make executable
|
|
109
|
+
console.log(` ${file}`);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// Copy JS scripts and make executable
|
|
113
|
+
hookJsScripts.forEach(file => {
|
|
104
114
|
const src = path.join(hooksDir, file);
|
|
105
115
|
const dest = path.join(CLAUDE_DIR, 'hooks', file);
|
|
106
116
|
fs.copyFileSync(src, dest);
|
|
@@ -115,7 +125,8 @@ if (fs.existsSync(hooksDir)) {
|
|
|
115
125
|
fs.copyFileSync(src, dest);
|
|
116
126
|
});
|
|
117
127
|
|
|
118
|
-
|
|
128
|
+
const totalHooks = hookShellScripts.length + hookJsScripts.length;
|
|
129
|
+
console.log(`✓ ${totalHooks} hooks installed`);
|
|
119
130
|
} else {
|
|
120
131
|
console.log(' No hooks to install');
|
|
121
132
|
}
|
|
@@ -229,7 +240,8 @@ if (fs.existsSync(mergeSettingsPath)) {
|
|
|
229
240
|
{ file: 'statusline-config.json', name: 'Custom status line' },
|
|
230
241
|
{ file: 'orchestration-hook.json', name: 'Orchestration guidance hook' },
|
|
231
242
|
{ file: 'bash-overflow-hook.json', name: 'Bash overflow guard hook' },
|
|
232
|
-
{ file: 'bash-precheck-hook.json', name: 'Bash precheck hook' }
|
|
243
|
+
{ file: 'bash-precheck-hook.json', name: 'Bash precheck hook' },
|
|
244
|
+
{ file: 'plan-agent-hook.json', name: 'Plan agent context injection hook' }
|
|
233
245
|
];
|
|
234
246
|
|
|
235
247
|
configs.forEach(({ file, name }) => {
|
package/package.json
CHANGED
|
@@ -9,14 +9,25 @@ cat << 'EOF'
|
|
|
9
9
|
<orchestration-guidance>
|
|
10
10
|
You are an ORCHESTRATOR, not an implementer. Your main thread is for coordination only.
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
## THE WORKFLOW: Explore → Plan → Execute
|
|
13
|
+
|
|
14
|
+
Never make code changes without a plan. Follow this sequence:
|
|
15
|
+
|
|
16
|
+
1. **EXPLORE** - Use Task (haiku) to understand current state: file search, code patterns, dependencies
|
|
17
|
+
2. **PLAN** - Use Task with subagent_type: "Plan" to design the change based on current state
|
|
18
|
+
3. **EXECUTE** - Use Task (opus) to implement the approved plan
|
|
19
|
+
|
|
20
|
+
## DELEGATE AGGRESSIVELY
|
|
21
|
+
|
|
22
|
+
- Use Task with model: haiku for read-only exploration
|
|
23
|
+
- Use Task with model: opus for ALL reasoning and implementation
|
|
24
|
+
- Use Task with subagent_type: "Plan" before any non-trivial changes
|
|
16
25
|
- Launch multiple agents in parallel when tasks are independent
|
|
17
26
|
- The only tools you use directly: Task, TodoWrite, AskUserQuestion
|
|
18
27
|
|
|
19
|
-
DISPATCH WITH CLARITY
|
|
28
|
+
## DISPATCH WITH CLARITY
|
|
29
|
+
|
|
30
|
+
Every sub-agent prompt must include:
|
|
20
31
|
1. Concrete objective: What specific outcome is needed
|
|
21
32
|
2. Acceptance criteria: How to verify the task is complete
|
|
22
33
|
3. Assumptions: Context the agent should validate before proceeding
|
|
@@ -24,13 +35,16 @@ DISPATCH WITH CLARITY - Every sub-agent prompt must include:
|
|
|
24
35
|
|
|
25
36
|
This ensures smooth feedback: sub-agents surface blockers early rather than going down wrong paths.
|
|
26
37
|
|
|
27
|
-
YOUR ROLE
|
|
38
|
+
## YOUR ROLE
|
|
39
|
+
|
|
28
40
|
1. Decompose problems into discrete tasks
|
|
29
41
|
2. Dispatch sub-agents with clear objectives and acceptance criteria
|
|
30
42
|
3. Verify results meet requirements
|
|
31
43
|
4. Synthesize findings for the user
|
|
32
44
|
|
|
33
|
-
SUCCESS LOOKS LIKE
|
|
45
|
+
## SUCCESS LOOKS LIKE
|
|
46
|
+
|
|
47
|
+
Your main thread has almost no Read, Grep, Glob, Edit, or Write calls. Sub-agents do the work; you orchestrate and verify.
|
|
34
48
|
|
|
35
49
|
ONLY handle directly: Single-command bash (git status, npm test), trivial typo fixes where you already know the exact line.
|
|
36
50
|
</orchestration-guidance>
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* plan-agent-context.js - PreToolUse hook for Plan sub-agent
|
|
4
|
+
*
|
|
5
|
+
* Intercepts Task calls with subagent_type: "Plan" and injects:
|
|
6
|
+
* 1. All project ADRs (since sub-agents can't spawn other sub-agents)
|
|
7
|
+
* 2. Planning guidance (web search for libraries, remove ambiguities)
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const yaml = require('js-yaml');
|
|
13
|
+
|
|
14
|
+
// Read hook input from stdin
|
|
15
|
+
let input = '';
|
|
16
|
+
process.stdin.setEncoding('utf8');
|
|
17
|
+
process.stdin.on('data', chunk => input += chunk);
|
|
18
|
+
process.stdin.on('end', () => {
|
|
19
|
+
try {
|
|
20
|
+
const hookInput = JSON.parse(input);
|
|
21
|
+
const result = processHook(hookInput);
|
|
22
|
+
console.log(JSON.stringify(result));
|
|
23
|
+
} catch (err) {
|
|
24
|
+
// On error, allow the tool call to proceed unchanged
|
|
25
|
+
console.log(JSON.stringify({ decision: "allow" }));
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
function processHook(hookInput) {
|
|
30
|
+
const toolInput = hookInput.tool_input || {};
|
|
31
|
+
|
|
32
|
+
// Only intercept Plan agent calls
|
|
33
|
+
if (toolInput.subagent_type !== 'Plan') {
|
|
34
|
+
return { decision: "allow" };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Collect ADRs
|
|
38
|
+
const adrs = collectADRs();
|
|
39
|
+
|
|
40
|
+
// Build the planning guidance
|
|
41
|
+
const planningGuidance = buildPlanningGuidance(adrs);
|
|
42
|
+
|
|
43
|
+
// Inject into the prompt
|
|
44
|
+
const originalPrompt = toolInput.prompt || '';
|
|
45
|
+
const augmentedPrompt = `${planningGuidance}\n\n---\n\nORIGINAL TASK:\n${originalPrompt}`;
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
decision: "allow",
|
|
49
|
+
updatedInput: {
|
|
50
|
+
...toolInput,
|
|
51
|
+
prompt: augmentedPrompt
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function collectADRs() {
|
|
57
|
+
const adrDir = path.join(process.cwd(), '.claude', 'adrs');
|
|
58
|
+
const adrs = [];
|
|
59
|
+
|
|
60
|
+
if (!fs.existsSync(adrDir)) {
|
|
61
|
+
return adrs;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const files = fs.readdirSync(adrDir).filter(f => f.endsWith('.yaml'));
|
|
65
|
+
|
|
66
|
+
for (const file of files) {
|
|
67
|
+
try {
|
|
68
|
+
const content = fs.readFileSync(path.join(adrDir, file), 'utf8');
|
|
69
|
+
const adr = yaml.load(content);
|
|
70
|
+
if (adr && adr.status !== 'Superseded') {
|
|
71
|
+
adrs.push({
|
|
72
|
+
id: adr.id,
|
|
73
|
+
title: adr.title,
|
|
74
|
+
description: adr.description,
|
|
75
|
+
constraints: adr.constraints,
|
|
76
|
+
decision: adr.decision
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
} catch (err) {
|
|
80
|
+
// Skip malformed ADRs
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return adrs;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function buildPlanningGuidance(adrs) {
|
|
88
|
+
let guidance = `<plan-agent-context>
|
|
89
|
+
## Planning Guidelines
|
|
90
|
+
|
|
91
|
+
You are creating an implementation plan. Follow these principles:
|
|
92
|
+
|
|
93
|
+
### Research Before Planning
|
|
94
|
+
- If the plan involves third-party libraries, APIs, or features not yet in the codebase, use WebSearch or WebFetch to get current documentation
|
|
95
|
+
- Do not assume library APIs - verify them with up-to-date sources
|
|
96
|
+
- Check compatibility with the project's infrastructure and existing patterns
|
|
97
|
+
|
|
98
|
+
### Remove Ambiguity
|
|
99
|
+
- Each step in your plan should be concrete and actionable
|
|
100
|
+
- If requirements are unclear, surface the ambiguity rather than making assumptions
|
|
101
|
+
- Identify decision points that need user input before execution
|
|
102
|
+
|
|
103
|
+
### ADR Compliance
|
|
104
|
+
The plan must respect these architectural decisions:
|
|
105
|
+
|
|
106
|
+
`;
|
|
107
|
+
|
|
108
|
+
if (adrs.length === 0) {
|
|
109
|
+
guidance += `(No ADRs found in this project)\n`;
|
|
110
|
+
} else {
|
|
111
|
+
for (const adr of adrs) {
|
|
112
|
+
guidance += `### ${adr.id}: ${adr.title}\n`;
|
|
113
|
+
if (adr.description) {
|
|
114
|
+
guidance += `${adr.description.trim()}\n`;
|
|
115
|
+
}
|
|
116
|
+
if (adr.constraints) {
|
|
117
|
+
if (adr.constraints.must && adr.constraints.must.length > 0) {
|
|
118
|
+
guidance += `**MUST:**\n`;
|
|
119
|
+
for (const c of adr.constraints.must) {
|
|
120
|
+
guidance += `- ${c}\n`;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (adr.constraints.must_not && adr.constraints.must_not.length > 0) {
|
|
124
|
+
guidance += `**MUST NOT:**\n`;
|
|
125
|
+
for (const c of adr.constraints.must_not) {
|
|
126
|
+
guidance += `- ${c}\n`;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (adr.decision) {
|
|
131
|
+
guidance += `**Decision:** ${adr.decision.trim()}\n`;
|
|
132
|
+
}
|
|
133
|
+
guidance += `\n`;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
guidance += `</plan-agent-context>`;
|
|
138
|
+
|
|
139
|
+
return guidance;
|
|
140
|
+
}
|