k-harness 0.3.0 → 0.5.0

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/src/init.js CHANGED
@@ -24,6 +24,72 @@ function writeFile(targetDir, relPath, content, overwrite) {
24
24
  return true;
25
25
  }
26
26
 
27
+ // ─── Shared definitions ──────────────────────────────────────
28
+
29
+ const SKILLS = [
30
+ { id: 'test-integrity', desc: 'Ensure test mocks stay synchronized when interfaces change. Use when modifying repository or service interfaces.' },
31
+ { id: 'security-checklist', desc: 'Security risk inspection before commits. Use when reviewing code for security issues.' },
32
+ { id: 'investigate', desc: 'Investigate and diagnose issues. Use when debugging or analyzing unexpected behavior.' },
33
+ { id: 'impact-analysis', desc: 'Assess change blast radius. Use when modifying shared modules or interfaces.' },
34
+ { id: 'feature-breakdown', desc: 'Break down features into implementable stories. Use when planning new features.' },
35
+ { id: 'bootstrap', desc: 'Onboard project into K-Harness. Scans codebase and fills state files. Use after k-harness init or when state files are empty.' },
36
+ { id: 'learn', desc: 'Capture session lessons and update state files. Use at the end of every session.' },
37
+ { id: 'pivot', desc: 'Propagate direction changes across all state files. Use when project goals, technology, scope, or architecture changes.' },
38
+ ];
39
+
40
+ const AGENTS = [
41
+ { id: 'reviewer', file: 'agents/reviewer.md', desc: 'Code review + auto-fix. Validates quality, security, and test integrity before commits.' },
42
+ { id: 'sprint-manager', file: 'agents/sprint-manager.md', desc: 'Sprint/Story state tracking, next task guidance, scope drift prevention.' },
43
+ { id: 'planner', file: 'agents/planner.md', desc: 'Feature planning and dependency management. Analyze architecture, break down features.' },
44
+ ];
45
+
46
+ const STATE_FILES = [
47
+ 'project-state.md',
48
+ 'failure-patterns.md',
49
+ 'dependency-map.md',
50
+ 'features.md',
51
+ 'project-brief.md',
52
+ ];
53
+
54
+ const AGENT_MEMORY_FILES = [
55
+ 'agent-memory/reviewer.md',
56
+ 'agent-memory/planner.md',
57
+ 'agent-memory/sprint-manager.md',
58
+ ];
59
+
60
+ const STATE_DEST_DIR = 'docs';
61
+
62
+ // ─── Shared writers ──────────────────────────────────────────
63
+
64
+ function writeStateFiles(targetDir, overwrite) {
65
+ for (const file of STATE_FILES) {
66
+ writeFile(targetDir, `${STATE_DEST_DIR}/${file}`, readTemplate(file), overwrite);
67
+ }
68
+ for (const file of AGENT_MEMORY_FILES) {
69
+ writeFile(targetDir, `${STATE_DEST_DIR}/${file}`, readTemplate(file), overwrite);
70
+ }
71
+ }
72
+
73
+ function writeSkills(targetDir, skillsDir, overwrite) {
74
+ for (const skill of SKILLS) {
75
+ const content = readTemplate(`skills/${skill.id}.md`);
76
+ const skillMd =
77
+ `---\nname: ${skill.id}\ndescription: '${skill.desc}'\n---\n\n` +
78
+ content;
79
+ writeFile(targetDir, `${skillsDir}/${skill.id}/SKILL.md`, skillMd, overwrite);
80
+ }
81
+ }
82
+
83
+ function writeAgentsAsSkills(targetDir, skillsDir, overwrite) {
84
+ for (const agent of AGENTS) {
85
+ const content = readTemplate(agent.file);
86
+ const skillMd =
87
+ `---\nname: ${agent.id}\ndescription: '${agent.desc}'\n---\n\n` +
88
+ content;
89
+ writeFile(targetDir, `${skillsDir}/${agent.id}/SKILL.md`, skillMd, overwrite);
90
+ }
91
+ }
92
+
27
93
  // ─── IDE Generators ──────────────────────────────────────────
28
94
 
29
95
  function generateVscode(targetDir, overwrite) {
@@ -45,38 +111,20 @@ function generateVscode(targetDir, overwrite) {
45
111
  backendRules;
46
112
  writeFile(targetDir, '.vscode/instructions/backend.instructions.md', backendWithFrontmatter, overwrite);
47
113
 
48
- // Skills (.github/skills — VS Code default search path)
49
- writeFile(targetDir, '.github/skills/test-integrity/SKILL.md', readTemplate('skills/test-integrity.md'), overwrite);
50
- writeFile(targetDir, '.github/skills/security-checklist/SKILL.md', readTemplate('skills/security-checklist.md'), overwrite);
51
- writeFile(targetDir, '.github/skills/investigate/SKILL.md', readTemplate('skills/investigate.md'), overwrite);
52
- writeFile(targetDir, '.github/skills/impact-analysis/SKILL.md', readTemplate('skills/impact-analysis.md'), overwrite);
53
- writeFile(targetDir, '.github/skills/feature-breakdown/SKILL.md', readTemplate('skills/feature-breakdown.md'), overwrite);
54
-
55
- // Agents (.github/agents — VS Code default search path)
56
- const reviewerContent = readTemplate('agents/reviewer.md');
57
- const reviewerAgent =
58
- '---\nname: reviewer\ndescription: "Code review + auto-fix. Validates quality, security, and test integrity before commits."\n---\n\n' +
59
- reviewerContent;
60
- writeFile(targetDir, '.github/agents/reviewer.agent.md', reviewerAgent, overwrite);
61
-
62
- const sprintContent = readTemplate('agents/sprint-manager.md');
63
- const sprintAgent =
64
- '---\nname: sprint-manager\ndescription: "Sprint/Story state tracking, next task guidance, scope drift prevention."\n---\n\n' +
65
- sprintContent;
66
- writeFile(targetDir, '.github/agents/sprint-manager.agent.md', sprintAgent, overwrite);
67
-
68
- const plannerContent = readTemplate('agents/planner.md');
69
- const plannerAgent =
70
- '---\nname: planner\ndescription: "Feature planning and dependency management. Analyze architecture, break down features, track module relationships."\n---\n\n' +
71
- plannerContent;
72
- writeFile(targetDir, '.github/agents/planner.agent.md', plannerAgent, overwrite);
114
+ // Skills (.github/skills — VS Code default search path, SKILL.md with frontmatter)
115
+ writeSkills(targetDir, '.github/skills', overwrite);
116
+
117
+ // Agents (.github/agents — VS Code uses .agent.md format with frontmatter)
118
+ for (const agent of AGENTS) {
119
+ const content = readTemplate(agent.file);
120
+ const agentMd =
121
+ `---\nname: ${agent.id}\ndescription: "${agent.desc}"\n---\n\n` +
122
+ content;
123
+ writeFile(targetDir, `.github/agents/${agent.id}.agent.md`, agentMd, overwrite);
124
+ }
73
125
 
74
126
  // State files
75
- writeFile(targetDir, 'project-state.md', readTemplate('project-state.md'), overwrite);
76
- writeFile(targetDir, 'failure-patterns.md', readTemplate('failure-patterns.md'), overwrite);
77
- writeFile(targetDir, 'dependency-map.md', readTemplate('dependency-map.md'), overwrite);
78
- writeFile(targetDir, 'features.md', readTemplate('features.md'), overwrite);
79
- writeFile(targetDir, 'project-brief.md', readTemplate('project-brief.md'), overwrite);
127
+ writeStateFiles(targetDir, overwrite);
80
128
  }
81
129
 
82
130
  function generateClaude(targetDir, overwrite) {
@@ -90,19 +138,11 @@ function generateClaude(targetDir, overwrite) {
90
138
  ].join('');
91
139
  writeFile(targetDir, 'CLAUDE.md', merged, overwrite);
92
140
 
93
- // Skills (Claude uses same SKILL.md format)
94
- writeFile(targetDir, '.claude/skills/test-integrity/SKILL.md', readTemplate('skills/test-integrity.md'), overwrite);
95
- writeFile(targetDir, '.claude/skills/security-checklist/SKILL.md', readTemplate('skills/security-checklist.md'), overwrite);
96
- writeFile(targetDir, '.claude/skills/investigate/SKILL.md', readTemplate('skills/investigate.md'), overwrite);
97
- writeFile(targetDir, '.claude/skills/impact-analysis/SKILL.md', readTemplate('skills/impact-analysis.md'), overwrite);
98
- writeFile(targetDir, '.claude/skills/feature-breakdown/SKILL.md', readTemplate('skills/feature-breakdown.md'), overwrite);
141
+ // Skills (SKILL.md with frontmatter for slash commands)
142
+ writeSkills(targetDir, '.claude/skills', overwrite);
99
143
 
100
144
  // State files
101
- writeFile(targetDir, 'project-state.md', readTemplate('project-state.md'), overwrite);
102
- writeFile(targetDir, 'failure-patterns.md', readTemplate('failure-patterns.md'), overwrite);
103
- writeFile(targetDir, 'dependency-map.md', readTemplate('dependency-map.md'), overwrite);
104
- writeFile(targetDir, 'features.md', readTemplate('features.md'), overwrite);
105
- writeFile(targetDir, 'project-brief.md', readTemplate('project-brief.md'), overwrite);
145
+ writeStateFiles(targetDir, overwrite);
106
146
  }
107
147
 
108
148
  function generateCursor(targetDir, overwrite) {
@@ -126,35 +166,25 @@ function generateCursor(targetDir, overwrite) {
126
166
  writeFile(targetDir, '.cursor/rules/backend.mdc', backendMdc, overwrite);
127
167
 
128
168
  // Skills as rules
129
- const skills = ['test-integrity', 'security-checklist', 'investigate', 'impact-analysis', 'feature-breakdown'];
130
- for (const skill of skills) {
131
- const content = readTemplate(`skills/${skill}.md`);
169
+ for (const skill of SKILLS) {
170
+ const content = readTemplate(`skills/${skill.id}.md`);
132
171
  const mdc =
133
- `---\ndescription: Skill — ${skill}\nalwaysApply: false\n---\n\n` +
172
+ `---\ndescription: Skill — ${skill.id}\nalwaysApply: false\n---\n\n` +
134
173
  content;
135
- writeFile(targetDir, `.cursor/rules/${skill}.mdc`, mdc, overwrite);
174
+ writeFile(targetDir, `.cursor/rules/${skill.id}.mdc`, mdc, overwrite);
136
175
  }
137
176
 
138
177
  // Agents as rules
139
- const agents = [
140
- { name: 'reviewer', file: 'agents/reviewer.md' },
141
- { name: 'sprint-manager', file: 'agents/sprint-manager.md' },
142
- { name: 'planner', file: 'agents/planner.md' },
143
- ];
144
- for (const agent of agents) {
178
+ for (const agent of AGENTS) {
145
179
  const content = readTemplate(agent.file);
146
180
  const mdc =
147
- `---\ndescription: Agent — ${agent.name}\nalwaysApply: false\n---\n\n` +
181
+ `---\ndescription: Agent — ${agent.id}\nalwaysApply: false\n---\n\n` +
148
182
  content;
149
- writeFile(targetDir, `.cursor/rules/${agent.name}.mdc`, mdc, overwrite);
183
+ writeFile(targetDir, `.cursor/rules/${agent.id}.mdc`, mdc, overwrite);
150
184
  }
151
185
 
152
186
  // State files
153
- writeFile(targetDir, 'project-state.md', readTemplate('project-state.md'), overwrite);
154
- writeFile(targetDir, 'failure-patterns.md', readTemplate('failure-patterns.md'), overwrite);
155
- writeFile(targetDir, 'dependency-map.md', readTemplate('dependency-map.md'), overwrite);
156
- writeFile(targetDir, 'features.md', readTemplate('features.md'), overwrite);
157
- writeFile(targetDir, 'project-brief.md', readTemplate('project-brief.md'), overwrite);
187
+ writeStateFiles(targetDir, overwrite);
158
188
  }
159
189
 
160
190
  function generateCodex(targetDir, overwrite) {
@@ -168,19 +198,11 @@ function generateCodex(targetDir, overwrite) {
168
198
  ].join('');
169
199
  writeFile(targetDir, 'AGENTS.md', merged, overwrite);
170
200
 
171
- // Skills (Codex uses .agents/skills/ format)
172
- writeFile(targetDir, '.agents/skills/test-integrity/SKILL.md', readTemplate('skills/test-integrity.md'), overwrite);
173
- writeFile(targetDir, '.agents/skills/security-checklist/SKILL.md', readTemplate('skills/security-checklist.md'), overwrite);
174
- writeFile(targetDir, '.agents/skills/investigate/SKILL.md', readTemplate('skills/investigate.md'), overwrite);
175
- writeFile(targetDir, '.agents/skills/impact-analysis/SKILL.md', readTemplate('skills/impact-analysis.md'), overwrite);
176
- writeFile(targetDir, '.agents/skills/feature-breakdown/SKILL.md', readTemplate('skills/feature-breakdown.md'), overwrite);
201
+ // Skills (SKILL.md with frontmatter for slash commands)
202
+ writeSkills(targetDir, '.agents/skills', overwrite);
177
203
 
178
204
  // State files
179
- writeFile(targetDir, 'project-state.md', readTemplate('project-state.md'), overwrite);
180
- writeFile(targetDir, 'failure-patterns.md', readTemplate('failure-patterns.md'), overwrite);
181
- writeFile(targetDir, 'dependency-map.md', readTemplate('dependency-map.md'), overwrite);
182
- writeFile(targetDir, 'features.md', readTemplate('features.md'), overwrite);
183
- writeFile(targetDir, 'project-brief.md', readTemplate('project-brief.md'), overwrite);
205
+ writeStateFiles(targetDir, overwrite);
184
206
  }
185
207
 
186
208
  function generateWindsurf(targetDir, overwrite) {
@@ -190,24 +212,18 @@ function generateWindsurf(targetDir, overwrite) {
190
212
  readTemplate('testing-rules.md'),
191
213
  readTemplate('backend-rules.md'),
192
214
  '---\n\n# Skills\n\n',
193
- readTemplate('skills/test-integrity.md'),
194
- readTemplate('skills/security-checklist.md'),
195
- readTemplate('skills/investigate.md'),
196
- readTemplate('skills/impact-analysis.md'),
197
- readTemplate('skills/feature-breakdown.md'),
198
- '---\n\n# Agents\n\n',
199
- readTemplate('agents/reviewer.md'),
200
- readTemplate('agents/sprint-manager.md'),
201
- readTemplate('agents/planner.md'),
202
215
  ];
216
+ for (const skill of SKILLS) {
217
+ sections.push(readTemplate(`skills/${skill.id}.md`));
218
+ }
219
+ sections.push('---\n\n# Agents\n\n');
220
+ for (const agent of AGENTS) {
221
+ sections.push(readTemplate(agent.file));
222
+ }
203
223
  writeFile(targetDir, '.windsurfrules', sections.join('\n\n---\n\n'), overwrite);
204
224
 
205
225
  // State files
206
- writeFile(targetDir, 'project-state.md', readTemplate('project-state.md'), overwrite);
207
- writeFile(targetDir, 'failure-patterns.md', readTemplate('failure-patterns.md'), overwrite);
208
- writeFile(targetDir, 'dependency-map.md', readTemplate('dependency-map.md'), overwrite);
209
- writeFile(targetDir, 'features.md', readTemplate('features.md'), overwrite);
210
- writeFile(targetDir, 'project-brief.md', readTemplate('project-brief.md'), overwrite);
226
+ writeStateFiles(targetDir, overwrite);
211
227
  }
212
228
 
213
229
  function generateAugment(targetDir, overwrite) {
@@ -231,41 +247,11 @@ function generateAugment(targetDir, overwrite) {
231
247
  writeFile(targetDir, '.augment/rules/backend.md', backendRule, overwrite);
232
248
 
233
249
  // .augment/skills/ — SKILL.md format (enables / slash commands)
234
- const skills = [
235
- { id: 'test-integrity', desc: 'Ensure test mocks stay synchronized when interfaces change. Use when modifying repository or service interfaces.' },
236
- { id: 'security-checklist', desc: 'Security risk inspection before commits. Use when reviewing code for security issues.' },
237
- { id: 'investigate', desc: 'Investigate and diagnose issues. Use when debugging or analyzing unexpected behavior.' },
238
- { id: 'impact-analysis', desc: 'Assess change blast radius. Use when modifying shared modules or interfaces.' },
239
- { id: 'feature-breakdown', desc: 'Break down features into implementable stories. Use when planning new features.' },
240
- ];
241
- for (const skill of skills) {
242
- const content = readTemplate(`skills/${skill.id}.md`);
243
- const skillMd =
244
- `---\nname: ${skill.id}\ndescription: '${skill.desc}'\n---\n\n` +
245
- content;
246
- writeFile(targetDir, `.augment/skills/${skill.id}/SKILL.md`, skillMd, overwrite);
247
- }
248
-
249
- // Agents as skills (invokable via / commands)
250
- const agents = [
251
- { id: 'reviewer', file: 'agents/reviewer.md', desc: 'Code review + auto-fix. Validates quality, security, and test integrity before commits.' },
252
- { id: 'sprint-manager', file: 'agents/sprint-manager.md', desc: 'Sprint/Story state tracking, next task guidance, scope drift prevention.' },
253
- { id: 'planner', file: 'agents/planner.md', desc: 'Feature planning and dependency management. Analyze architecture, break down features.' },
254
- ];
255
- for (const agent of agents) {
256
- const content = readTemplate(agent.file);
257
- const skillMd =
258
- `---\nname: ${agent.id}\ndescription: '${agent.desc}'\n---\n\n` +
259
- content;
260
- writeFile(targetDir, `.augment/skills/${agent.id}/SKILL.md`, skillMd, overwrite);
261
- }
250
+ writeSkills(targetDir, '.augment/skills', overwrite);
251
+ writeAgentsAsSkills(targetDir, '.augment/skills', overwrite);
262
252
 
263
253
  // State files
264
- writeFile(targetDir, 'project-state.md', readTemplate('project-state.md'), overwrite);
265
- writeFile(targetDir, 'failure-patterns.md', readTemplate('failure-patterns.md'), overwrite);
266
- writeFile(targetDir, 'dependency-map.md', readTemplate('dependency-map.md'), overwrite);
267
- writeFile(targetDir, 'features.md', readTemplate('features.md'), overwrite);
268
- writeFile(targetDir, 'project-brief.md', readTemplate('project-brief.md'), overwrite);
254
+ writeStateFiles(targetDir, overwrite);
269
255
  }
270
256
 
271
257
  function generateAntigravity(targetDir, overwrite) {
@@ -289,41 +275,11 @@ function generateAntigravity(targetDir, overwrite) {
289
275
  writeFile(targetDir, '.agent/rules/backend.md', backendRule, overwrite);
290
276
 
291
277
  // .agent/skills/ — SKILL.md format (enables / slash commands)
292
- const skills = [
293
- { id: 'test-integrity', desc: 'Ensure test mocks stay synchronized when interfaces change. Use when modifying repository or service interfaces.' },
294
- { id: 'security-checklist', desc: 'Security risk inspection before commits. Use when reviewing code for security issues.' },
295
- { id: 'investigate', desc: 'Investigate and diagnose issues. Use when debugging or analyzing unexpected behavior.' },
296
- { id: 'impact-analysis', desc: 'Assess change blast radius. Use when modifying shared modules or interfaces.' },
297
- { id: 'feature-breakdown', desc: 'Break down features into implementable stories. Use when planning new features.' },
298
- ];
299
- for (const skill of skills) {
300
- const content = readTemplate(`skills/${skill.id}.md`);
301
- const skillMd =
302
- `---\nname: ${skill.id}\ndescription: '${skill.desc}'\n---\n\n` +
303
- content;
304
- writeFile(targetDir, `.agent/skills/${skill.id}/SKILL.md`, skillMd, overwrite);
305
- }
306
-
307
- // Agents as skills (invokable via / commands)
308
- const agents = [
309
- { id: 'reviewer', file: 'agents/reviewer.md', desc: 'Code review + auto-fix. Validates quality, security, and test integrity before commits.' },
310
- { id: 'sprint-manager', file: 'agents/sprint-manager.md', desc: 'Sprint/Story state tracking, next task guidance, scope drift prevention.' },
311
- { id: 'planner', file: 'agents/planner.md', desc: 'Feature planning and dependency management. Analyze architecture, break down features.' },
312
- ];
313
- for (const agent of agents) {
314
- const content = readTemplate(agent.file);
315
- const skillMd =
316
- `---\nname: ${agent.id}\ndescription: '${agent.desc}'\n---\n\n` +
317
- content;
318
- writeFile(targetDir, `.agent/skills/${agent.id}/SKILL.md`, skillMd, overwrite);
319
- }
278
+ writeSkills(targetDir, '.agent/skills', overwrite);
279
+ writeAgentsAsSkills(targetDir, '.agent/skills', overwrite);
320
280
 
321
281
  // State files
322
- writeFile(targetDir, 'project-state.md', readTemplate('project-state.md'), overwrite);
323
- writeFile(targetDir, 'failure-patterns.md', readTemplate('failure-patterns.md'), overwrite);
324
- writeFile(targetDir, 'dependency-map.md', readTemplate('dependency-map.md'), overwrite);
325
- writeFile(targetDir, 'features.md', readTemplate('features.md'), overwrite);
326
- writeFile(targetDir, 'project-brief.md', readTemplate('project-brief.md'), overwrite);
282
+ writeStateFiles(targetDir, overwrite);
327
283
  }
328
284
 
329
285
  // ─── IDE registry ────────────────────────────────────────────
@@ -424,7 +380,7 @@ async function run(argv) {
424
380
  const gen = GENERATORS[ide];
425
381
  console.log(`\n Installing for ${gen.name}...\n`);
426
382
  gen.fn(args.dir, args.overwrite);
427
- console.log(`\n Done! Edit project-state.md to set up your first sprint.\n`);
383
+ console.log(`\n Done! Edit docs/project-state.md to set up your first sprint.\n`);
428
384
  }
429
385
  }
430
386