@damper/cli 0.6.6 → 0.6.7
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/dist/index.js +1 -1
- package/dist/services/context-bootstrap.d.ts +10 -0
- package/dist/services/context-bootstrap.js +23 -19
- package/dist/services/damper-api.d.ts +21 -0
- package/dist/services/damper-api.js +15 -1
- package/dist/templates/CLAUDE_APPEND.md.js +6 -0
- package/dist/templates/TASK_CONTEXT.md.d.ts +3 -2
- package/dist/templates/TASK_CONTEXT.md.js +14 -7
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { statusCommand } from './commands/status.js';
|
|
|
5
5
|
import { cleanupCommand } from './commands/cleanup.js';
|
|
6
6
|
import { setupCommand } from './commands/setup.js';
|
|
7
7
|
import { releaseCommand } from './commands/release.js';
|
|
8
|
-
const VERSION = '0.6.
|
|
8
|
+
const VERSION = '0.6.7';
|
|
9
9
|
function showHelp() {
|
|
10
10
|
console.log(`
|
|
11
11
|
${pc.bold('@damper/cli')} - Agent orchestration for Damper tasks
|
|
@@ -9,6 +9,16 @@ export interface BootstrapResult {
|
|
|
9
9
|
taskContextPath: string;
|
|
10
10
|
claudeMdUpdated: boolean;
|
|
11
11
|
}
|
|
12
|
+
export interface SectionBlockIndex {
|
|
13
|
+
section: string;
|
|
14
|
+
blocks: Array<{
|
|
15
|
+
id: string;
|
|
16
|
+
heading: string | null;
|
|
17
|
+
level: number;
|
|
18
|
+
charCount: number;
|
|
19
|
+
}>;
|
|
20
|
+
totalChars: number;
|
|
21
|
+
}
|
|
12
22
|
/**
|
|
13
23
|
* Fetch all relevant context from Damper and write local files
|
|
14
24
|
*/
|
|
@@ -6,6 +6,24 @@ import { generateClaudeAppend } from '../templates/CLAUDE_APPEND.md.js';
|
|
|
6
6
|
const TASK_CONTEXT_FILE = 'TASK_CONTEXT.md';
|
|
7
7
|
const CLAUDE_MD_FILE = 'CLAUDE.md';
|
|
8
8
|
const TASK_SECTION_MARKER = '## Current Task:';
|
|
9
|
+
/**
|
|
10
|
+
* Fetch block indices for relevant sections.
|
|
11
|
+
* Only fetches the headings/structure - no content.
|
|
12
|
+
* The agent will use get_section_block_content to load what it needs.
|
|
13
|
+
*/
|
|
14
|
+
async function fetchBlockIndices(api, relevantSections) {
|
|
15
|
+
const indices = [];
|
|
16
|
+
for (const sectionName of relevantSections) {
|
|
17
|
+
try {
|
|
18
|
+
const blockIndex = await api.getSectionBlocks(sectionName);
|
|
19
|
+
indices.push(blockIndex);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
console.log(pc.dim(` Could not fetch blocks for: ${sectionName}`));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return indices;
|
|
26
|
+
}
|
|
9
27
|
/**
|
|
10
28
|
* Fetch all relevant context from Damper and write local files
|
|
11
29
|
*/
|
|
@@ -15,26 +33,12 @@ export async function bootstrapContext(options) {
|
|
|
15
33
|
const task = await api.getTask(taskId);
|
|
16
34
|
console.log(pc.dim('Fetching project context...'));
|
|
17
35
|
const context = await api.getProjectContext(taskId);
|
|
18
|
-
// Fetch
|
|
19
|
-
const sections = [];
|
|
36
|
+
// Fetch block indices (not content) for relevant sections
|
|
20
37
|
const relevantSections = context.relevantSections || [];
|
|
38
|
+
let blockIndices = [];
|
|
21
39
|
if (relevantSections.length > 0) {
|
|
22
|
-
console.log(pc.dim(`Fetching ${relevantSections.length} relevant
|
|
23
|
-
|
|
24
|
-
try {
|
|
25
|
-
const result = await api.getContextSection(sectionName);
|
|
26
|
-
// Handle both single section and glob pattern responses
|
|
27
|
-
if ('pattern' in result && result.sections) {
|
|
28
|
-
sections.push(...result.sections);
|
|
29
|
-
}
|
|
30
|
-
else if ('section' in result && 'content' in result) {
|
|
31
|
-
sections.push(result);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
catch (err) {
|
|
35
|
-
console.log(pc.dim(` Could not fetch section: ${sectionName}`));
|
|
36
|
-
}
|
|
37
|
-
}
|
|
40
|
+
console.log(pc.dim(`Fetching block indices for ${relevantSections.length} relevant sections...`));
|
|
41
|
+
blockIndices = await fetchBlockIndices(api, relevantSections);
|
|
38
42
|
}
|
|
39
43
|
// Fetch templates
|
|
40
44
|
console.log(pc.dim('Fetching templates...'));
|
|
@@ -51,7 +55,7 @@ export async function bootstrapContext(options) {
|
|
|
51
55
|
const taskContext = generateTaskContext({
|
|
52
56
|
task,
|
|
53
57
|
criticalRules: context.criticalRules || [],
|
|
54
|
-
|
|
58
|
+
blockIndices,
|
|
55
59
|
templates,
|
|
56
60
|
modules,
|
|
57
61
|
damperInstructions: instructions.content,
|
|
@@ -131,6 +131,27 @@ export declare class DamperApi {
|
|
|
131
131
|
}>;
|
|
132
132
|
isEmpty: boolean;
|
|
133
133
|
}>;
|
|
134
|
+
getSectionBlocks(section: string): Promise<{
|
|
135
|
+
section: string;
|
|
136
|
+
blocks: Array<{
|
|
137
|
+
id: string;
|
|
138
|
+
heading: string | null;
|
|
139
|
+
level: number;
|
|
140
|
+
charCount: number;
|
|
141
|
+
}>;
|
|
142
|
+
totalChars: number;
|
|
143
|
+
}>;
|
|
144
|
+
getSectionBlockContent(section: string, blockIds: string[]): Promise<{
|
|
145
|
+
section: string;
|
|
146
|
+
blocks: Array<{
|
|
147
|
+
id: string;
|
|
148
|
+
heading: string | null;
|
|
149
|
+
level: number;
|
|
150
|
+
content: string;
|
|
151
|
+
charCount: number;
|
|
152
|
+
}>;
|
|
153
|
+
totalChars: number;
|
|
154
|
+
}>;
|
|
134
155
|
listTemplates(): Promise<{
|
|
135
156
|
templates: Array<{
|
|
136
157
|
name: string;
|
|
@@ -69,6 +69,16 @@ export class DamperApi {
|
|
|
69
69
|
async listContextSections() {
|
|
70
70
|
return this.request('GET', '/api/agent/context');
|
|
71
71
|
}
|
|
72
|
+
// Context Blocks
|
|
73
|
+
async getSectionBlocks(section) {
|
|
74
|
+
const encodedSection = encodeURIComponent(section);
|
|
75
|
+
return this.request('GET', `/api/agent/context/${encodedSection}/blocks`);
|
|
76
|
+
}
|
|
77
|
+
async getSectionBlockContent(section, blockIds) {
|
|
78
|
+
const encodedSection = encodeURIComponent(section);
|
|
79
|
+
const encodedBlockIds = blockIds.map(id => encodeURIComponent(id)).join(',');
|
|
80
|
+
return this.request('GET', `/api/agent/context/${encodedSection}/blocks/${encodedBlockIds}`);
|
|
81
|
+
}
|
|
72
82
|
// Templates
|
|
73
83
|
async listTemplates() {
|
|
74
84
|
return this.request('GET', '/api/agent/templates');
|
|
@@ -95,7 +105,10 @@ This project uses Damper MCP for task tracking. **You MUST follow this workflow.
|
|
|
95
105
|
|
|
96
106
|
### At Session Start (MANDATORY)
|
|
97
107
|
1. \`get_project_context\` - **READ THIS FIRST.** Contains architecture, conventions, and critical project info.
|
|
98
|
-
2.
|
|
108
|
+
2. Load relevant architecture context using blocks (token-efficient):
|
|
109
|
+
- If TASK_CONTEXT.md has an "Available Architecture Context" section, use \`get_section_block_content(section, blockIds)\` to load only the blocks relevant to your task
|
|
110
|
+
- Otherwise, use \`get_section_blocks(section)\` to see what's available, then fetch specific blocks
|
|
111
|
+
- Only fall back to \`get_context_section\` if you need an entire section
|
|
99
112
|
3. \`list_tasks\` - Check for existing tasks to work on
|
|
100
113
|
4. If working on a task: \`start_task\` to lock it
|
|
101
114
|
|
|
@@ -104,6 +117,7 @@ This project uses Damper MCP for task tracking. **You MUST follow this workflow.
|
|
|
104
117
|
- \`add_note\` for decisions: "Decision: chose X because Y"
|
|
105
118
|
- \`update_subtask\` to mark subtask progress
|
|
106
119
|
- **Follow patterns from project context** - Don't reinvent; use existing conventions
|
|
120
|
+
- When you need architecture context mid-task, use \`get_section_block_content\` to load specific blocks rather than full sections
|
|
107
121
|
|
|
108
122
|
### Feedback & Changelog Integration
|
|
109
123
|
- \`link_feedback_to_task\` - Link user feedback IDs to your task (helps track what customer requests led to the feature)
|
|
@@ -17,6 +17,12 @@ Read TASK_CONTEXT.md first, then create a plan for user approval. Do NOT write c
|
|
|
17
17
|
**IMPORTANT**: Read TASK_CONTEXT.md for full task details and architecture context.
|
|
18
18
|
If you feel you've lost context, re-read that file.
|
|
19
19
|
${planSection}
|
|
20
|
+
**NEVER commit these files** (they are generated by the CLI and gitignored):
|
|
21
|
+
- \`CLAUDE.md\` changes (this task section is temporary)
|
|
22
|
+
- \`TASK_CONTEXT.md\`
|
|
23
|
+
- \`.mcp.json\`
|
|
24
|
+
- \`.claude/settings.local.json\`
|
|
25
|
+
|
|
20
26
|
**Your responsibilities (via Damper MCP):**
|
|
21
27
|
1. Use \`add_commit\` after each git commit
|
|
22
28
|
2. Use \`add_note\` for important decisions
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type { TaskDetail,
|
|
1
|
+
import type { TaskDetail, Module } from '../services/damper-api.js';
|
|
2
|
+
import type { SectionBlockIndex } from '../services/context-bootstrap.js';
|
|
2
3
|
interface TaskContextOptions {
|
|
3
4
|
task: TaskDetail;
|
|
4
5
|
criticalRules: string[];
|
|
5
|
-
|
|
6
|
+
blockIndices: SectionBlockIndex[];
|
|
6
7
|
templates: Array<{
|
|
7
8
|
name: string;
|
|
8
9
|
description?: string | null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export function generateTaskContext(options) {
|
|
2
|
-
const { task, criticalRules,
|
|
2
|
+
const { task, criticalRules, blockIndices, templates, modules, damperInstructions } = options;
|
|
3
3
|
const typeIcon = task.type === 'bug' ? 'Bug' : task.type === 'feature' ? 'Feature' : task.type === 'improvement' ? 'Improvement' : 'Task';
|
|
4
4
|
const lines = [];
|
|
5
5
|
// Header
|
|
@@ -80,14 +80,21 @@ export function generateTaskContext(options) {
|
|
|
80
80
|
}
|
|
81
81
|
lines.push('');
|
|
82
82
|
}
|
|
83
|
-
// Project Context
|
|
84
|
-
if (
|
|
85
|
-
lines.push('##
|
|
83
|
+
// Project Context Block Index (load-on-demand)
|
|
84
|
+
if (blockIndices.length > 0) {
|
|
85
|
+
lines.push('## Available Architecture Context');
|
|
86
86
|
lines.push('');
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
lines.push('**BEFORE starting work**, load the blocks relevant to your task using the MCP tool:');
|
|
88
|
+
lines.push('`get_section_block_content(section, blockIds)` — pass the section name and an array of block IDs from the list below.');
|
|
89
|
+
lines.push('Only load what you need to keep token usage low.');
|
|
90
|
+
lines.push('');
|
|
91
|
+
for (const index of blockIndices) {
|
|
92
|
+
lines.push(`### ${index.section} (${index.totalChars} chars)`);
|
|
89
93
|
lines.push('');
|
|
90
|
-
|
|
94
|
+
for (const block of index.blocks) {
|
|
95
|
+
const heading = block.heading ? block.heading.replace(/^#+\s*/, '') : '(intro)';
|
|
96
|
+
lines.push(`- \`${block.id}\`: ${heading} (${block.charCount} chars)`);
|
|
97
|
+
}
|
|
91
98
|
lines.push('');
|
|
92
99
|
}
|
|
93
100
|
}
|