knit-mcp 0.7.0 → 0.8.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/README.md +21 -0
- package/dist/{cache-WGZ2C7BZ.js → cache-RRKF2IZ5.js} +5 -5
- package/dist/{instructions-33TUHLTK.js → chunk-4PFEG4GQ.js} +1 -0
- package/dist/{chunk-7PPC6IG6.js → chunk-JJ367RK5.js} +163 -1
- package/dist/{chunk-SLN5ABF5.js → chunk-MOOVNMIN.js} +1 -160
- package/dist/{chunk-3XR77YJM.js → chunk-N7R4P42P.js} +265 -9
- package/dist/{chunk-HBMF62U4.js → chunk-SBJMHDBM.js} +4 -0
- package/dist/{chunk-TRZ3LD6B.js → chunk-TSIXVZCT.js} +11 -1
- package/dist/chunk-UTVFELXS.js +9 -0
- package/dist/chunk-WMESQUZU.js +25 -0
- package/dist/{chunk-QMH2DT6K.js → chunk-WN4AQFMO.js} +25 -11
- package/dist/cli.js +19 -16
- package/dist/{export-IKPBLZOO.js → export-KALLYKWG.js} +2 -2
- package/dist/{install-agents-AXT6DMYM.js → install-agents-DLSH3FNC.js} +6 -6
- package/dist/instructions-YPXOZZHI.js +6 -0
- package/dist/notifier-4L27HKHI.js +10 -0
- package/dist/{refresh-MSN5YNPS.js → refresh-N4O2QLYS.js} +7 -7
- package/dist/{status-XN6VHO66.js → status-YK2KBG57.js} +1 -1
- package/dist/{tools-KRPOUYNT.js → tools-GN6GM55U.js} +459 -24
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -59,6 +59,27 @@ Adds the Knit MCP server to your Claude Code config (`~/.claude.json`). No per-p
|
|
|
59
59
|
|
|
60
60
|
**Supported shells:** macOS, Linux, WSL, Git Bash, and Windows PowerShell. The generated hooks use POSIX-style single-quoted `node -e '…'` payloads. Windows `cmd.exe` does not treat single quotes as delimiters and is not supported as the hook-runner shell — on Windows, use PowerShell (default in modern Windows Terminal) or Git Bash. If you hit a hook error on Windows, file an issue with the shell you're using.
|
|
61
61
|
|
|
62
|
+
### Quiet mode (no hook enforcement)
|
|
63
|
+
|
|
64
|
+
Knit ships Protocol Guard in `warn` mode by default — hooks print reminders, they never block. If you want it fully silent (no PreToolUse classification gate, no reminder messages), run this once inside Claude Code:
|
|
65
|
+
|
|
66
|
+
> `knit_set_protocol_strictness({ level: "off" })`
|
|
67
|
+
|
|
68
|
+
The other hooks (LEARN compliance, KB metrics, final build verification) stay as observability nudges — they print, they don't gate. To remove them too, see Uninstall below.
|
|
69
|
+
|
|
70
|
+
### Uninstall
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
rm -rf ~/.knit # all per-project + global memory
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Then:
|
|
77
|
+
1. Remove `"knit-brain"` from `mcpServers` in `~/.claude.json`
|
|
78
|
+
2. Delete the `<!-- knit:start --> ... <!-- knit:end -->` block from each project's `CLAUDE.md`
|
|
79
|
+
3. Remove `_knitOwned` entries from each project's `.claude/settings.local.json` (or delete the file if Knit was the only thing in it)
|
|
80
|
+
|
|
81
|
+
Total time: ~30 seconds per project. Knit doesn't write anywhere else on your machine.
|
|
82
|
+
|
|
62
83
|
## How data is stored
|
|
63
84
|
|
|
64
85
|
Knit data is centralized — not in every repo's working tree:
|
|
@@ -2,13 +2,13 @@ import {
|
|
|
2
2
|
detectProjectRoot,
|
|
3
3
|
getBrain,
|
|
4
4
|
refreshBrain
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-WN4AQFMO.js";
|
|
6
|
+
import "./chunk-N7R4P42P.js";
|
|
7
|
+
import "./chunk-MOOVNMIN.js";
|
|
8
|
+
import "./chunk-JJ367RK5.js";
|
|
7
9
|
import "./chunk-M3YZOJNW.js";
|
|
8
|
-
import "./chunk-3XR77YJM.js";
|
|
9
|
-
import "./chunk-7PPC6IG6.js";
|
|
10
10
|
import "./chunk-BAUQEFYY.js";
|
|
11
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-SBJMHDBM.js";
|
|
12
12
|
export {
|
|
13
13
|
detectProjectRoot,
|
|
14
14
|
getBrain,
|
|
@@ -24,6 +24,7 @@ The protocol enforces a 4-tier classifier:
|
|
|
24
24
|
- Complex: cross-domain, types/auth-touching, high-fanout, or any task spanning more than one commit \u2014 full 6 phases with auto plan mode on RESEARCH.
|
|
25
25
|
|
|
26
26
|
Knit provides inputs; you make the calls. When in doubt, under-classify \u2014 easier to escalate mid-task than to downgrade.`;
|
|
27
|
+
|
|
27
28
|
export {
|
|
28
29
|
KNIT_INSTRUCTIONS
|
|
29
30
|
};
|
|
@@ -271,6 +271,162 @@ function detectGit(root) {
|
|
|
271
271
|
return { isRepo, defaultBranch, hasRemote };
|
|
272
272
|
}
|
|
273
273
|
|
|
274
|
+
// src/generators/claude-md.ts
|
|
275
|
+
var KNIT_MARKER_START = "<!-- knit:start -->";
|
|
276
|
+
var KNIT_MARKER_END = "<!-- knit:end -->";
|
|
277
|
+
var LEGACY_ENGRAM_MARKER_START = "<!-- engram:start -->";
|
|
278
|
+
var LEGACY_ENGRAM_MARKER_END = "<!-- engram:end -->";
|
|
279
|
+
function generateClaudeMd(config, knowledge, falsePositives) {
|
|
280
|
+
const sections = [
|
|
281
|
+
generateHeader(config),
|
|
282
|
+
generateSessionStartup(),
|
|
283
|
+
knowledge ? generateProjectMap(knowledge) : null,
|
|
284
|
+
generateDomainArchitecture(config),
|
|
285
|
+
falsePositives && falsePositives.length > 0 ? generateFalsePositives(falsePositives) : null,
|
|
286
|
+
generateBuildGates(config),
|
|
287
|
+
generateTierVocabulary(),
|
|
288
|
+
generateWorkflowPointer()
|
|
289
|
+
];
|
|
290
|
+
const body = sections.filter(Boolean).join("\n\n---\n\n");
|
|
291
|
+
return `${KNIT_MARKER_START}
|
|
292
|
+
|
|
293
|
+
${body}
|
|
294
|
+
|
|
295
|
+
${KNIT_MARKER_END}
|
|
296
|
+
`;
|
|
297
|
+
}
|
|
298
|
+
function spliceKnitBlock(existing, newBlock) {
|
|
299
|
+
const markerPairs = [
|
|
300
|
+
[KNIT_MARKER_START, KNIT_MARKER_END],
|
|
301
|
+
[LEGACY_ENGRAM_MARKER_START, LEGACY_ENGRAM_MARKER_END]
|
|
302
|
+
];
|
|
303
|
+
for (const [startMarker, endMarker] of markerPairs) {
|
|
304
|
+
const startIdx = existing.indexOf(startMarker);
|
|
305
|
+
const endIdx = existing.indexOf(endMarker);
|
|
306
|
+
if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
|
|
307
|
+
const before = existing.slice(0, startIdx);
|
|
308
|
+
const after = existing.slice(endIdx + endMarker.length);
|
|
309
|
+
return { content: before + newBlock.trimEnd() + after, mode: "replaced" };
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return { content: existing, mode: "sidecar-needed" };
|
|
313
|
+
}
|
|
314
|
+
function generateHeader(config) {
|
|
315
|
+
const stackParts = [
|
|
316
|
+
config.stack.language !== "unknown" ? config.stack.language : null,
|
|
317
|
+
config.stack.framework
|
|
318
|
+
].filter(Boolean);
|
|
319
|
+
const stackDesc = stackParts.length > 0 ? `${stackParts.join(" + ")} project. ` : "";
|
|
320
|
+
return `# ${config.name}
|
|
321
|
+
|
|
322
|
+
${stackDesc}Knit-powered workflow. The protocol depth is fetched on demand via \`knit_get_workflow({phase})\` \u2014 this file holds only project-specific facts.`;
|
|
323
|
+
}
|
|
324
|
+
function generateSessionStartup() {
|
|
325
|
+
return `## Session start
|
|
326
|
+
|
|
327
|
+
First action: call \`knit_load_session\`. One MCP call returns last sessions, handoff, learnings, false positives. If \`handoff.md\` exists at the repo root, resume that work first.
|
|
328
|
+
|
|
329
|
+
Protocol Guard runs in \`warn\` mode by default \u2014 adjust with \`knit_set_protocol_strictness\`.`;
|
|
330
|
+
}
|
|
331
|
+
function generateProjectMap(knowledge) {
|
|
332
|
+
const { summary } = knowledge;
|
|
333
|
+
let content = `## Project Map (auto-generated)
|
|
334
|
+
|
|
335
|
+
`;
|
|
336
|
+
if (summary.entryPoints.length > 0) {
|
|
337
|
+
content += `**Entry points:** \`${summary.entryPoints.join("`, `")}\`
|
|
338
|
+
`;
|
|
339
|
+
}
|
|
340
|
+
if (summary.highFanoutFiles.length > 0) {
|
|
341
|
+
const shown = summary.highFanoutFiles.slice(0, 5);
|
|
342
|
+
content += `**High-fanout (change carefully):** \`${shown.join("`, `")}\``;
|
|
343
|
+
if (summary.highFanoutFiles.length > 5) {
|
|
344
|
+
content += ` (+${summary.highFanoutFiles.length - 5} more \u2014 \`knit_find_fanout\`)`;
|
|
345
|
+
}
|
|
346
|
+
content += "\n";
|
|
347
|
+
}
|
|
348
|
+
if (summary.untestedFiles.length > 0) {
|
|
349
|
+
const shown = summary.untestedFiles.slice(0, 3);
|
|
350
|
+
content += `**Untested:** \`${shown.join("`, `")}\``;
|
|
351
|
+
if (summary.untestedFiles.length > 3) {
|
|
352
|
+
content += ` (+${summary.untestedFiles.length - 3} more \u2014 \`knit_query_tests({filter:"untested"})\`)`;
|
|
353
|
+
}
|
|
354
|
+
content += "\n";
|
|
355
|
+
}
|
|
356
|
+
if (summary.largestFiles.length > 0) {
|
|
357
|
+
const top3 = summary.largestFiles.slice(0, 3);
|
|
358
|
+
const list = top3.map((f) => `\`${f.path}\` (${f.lines})`).join(", ");
|
|
359
|
+
content += `**Largest:** ${list}
|
|
360
|
+
`;
|
|
361
|
+
}
|
|
362
|
+
content += `
|
|
363
|
+
**Stats:** ${summary.totalFiles} files, ${summary.totalLines.toLocaleString()} lines`;
|
|
364
|
+
const langs = Object.entries(summary.languageBreakdown).sort((a, b) => b[1] - a[1]).slice(0, 3).map(([ext, count]) => `${ext}: ${count}`);
|
|
365
|
+
if (langs.length > 0) content += ` (${langs.join(", ")})`;
|
|
366
|
+
return content;
|
|
367
|
+
}
|
|
368
|
+
function generateDomainArchitecture(config) {
|
|
369
|
+
if (!config.domains || config.domains.length === 0) {
|
|
370
|
+
return `## Domain Architecture
|
|
371
|
+
|
|
372
|
+
No domains detected. Use \`knit_setup_project\` to describe your project \u2014 Knit will configure domains and review agents.`;
|
|
373
|
+
}
|
|
374
|
+
const rows = config.domains.map((d) => {
|
|
375
|
+
const patterns = d.filePatterns.slice(0, 3).join(", ");
|
|
376
|
+
const agents = d.agents.join(", ");
|
|
377
|
+
return `### ${d.name}
|
|
378
|
+
**Files:** \`${patterns}\`
|
|
379
|
+
**Concern:** ${d.description}
|
|
380
|
+
**Review agents:** \`${agents}\``;
|
|
381
|
+
}).join("\n\n");
|
|
382
|
+
return `## Domain Architecture
|
|
383
|
+
|
|
384
|
+
${rows}`;
|
|
385
|
+
}
|
|
386
|
+
function generateFalsePositives(fps) {
|
|
387
|
+
const items = fps.slice(0, 10).map((fp) => `- **${fp.summary}** \u2014 ${fp.lesson}`).join("\n");
|
|
388
|
+
return `## Known False Positives
|
|
389
|
+
|
|
390
|
+
Review agents should NOT re-flag these \u2014 they're confirmed non-issues from prior sessions:
|
|
391
|
+
|
|
392
|
+
${items}`;
|
|
393
|
+
}
|
|
394
|
+
function generateBuildGates(config) {
|
|
395
|
+
const gates = [];
|
|
396
|
+
if (config.stack.typecheckCommand) gates.push(`- \`${config.stack.typecheckCommand}\``);
|
|
397
|
+
if (config.stack.lintCommand) gates.push(`- \`${config.stack.lintCommand}\``);
|
|
398
|
+
if (config.stack.testFramework) {
|
|
399
|
+
const pm = config.packageManager === "unknown" ? "npm" : config.packageManager;
|
|
400
|
+
gates.push(`- \`${pm} test\``);
|
|
401
|
+
}
|
|
402
|
+
if (config.stack.buildCommand) gates.push(`- \`${config.stack.buildCommand}\``);
|
|
403
|
+
if (gates.length === 0) {
|
|
404
|
+
return `## Build Gates
|
|
405
|
+
|
|
406
|
+
No build gates auto-detected. Add typecheck/lint/test/build commands to your package.json.`;
|
|
407
|
+
}
|
|
408
|
+
return `## Build Gates
|
|
409
|
+
|
|
410
|
+
All must pass before commit:
|
|
411
|
+
|
|
412
|
+
${gates.join("\n")}`;
|
|
413
|
+
}
|
|
414
|
+
function generateTierVocabulary() {
|
|
415
|
+
return `## Tier vocabulary
|
|
416
|
+
|
|
417
|
+
| Tier | When |
|
|
418
|
+
|------|------|
|
|
419
|
+
| **Inquiry** | Read-only ("what", "where", "audit") \u2014 just answer. |
|
|
420
|
+
| **Trivial** | One-line fix \u2014 execute \u2192 verify. |
|
|
421
|
+
| **Standard** | Single-domain bug fix or feature \u2014 research \u2192 execute \u2192 review. |
|
|
422
|
+
| **Complex** | Cross-domain, touches types/auth, high-fanout, or multi-commit arc \u2014 full 6 phases + auto plan mode. |`;
|
|
423
|
+
}
|
|
424
|
+
function generateWorkflowPointer() {
|
|
425
|
+
return `## Workflow on demand
|
|
426
|
+
|
|
427
|
+
Fetch any phase via \`knit_get_workflow({phase})\`. Call with no phase to list available sections.`;
|
|
428
|
+
}
|
|
429
|
+
|
|
274
430
|
export {
|
|
275
431
|
VOLTAGENT_PINNED_SHA,
|
|
276
432
|
VOLTAGENT_REF,
|
|
@@ -278,5 +434,11 @@ export {
|
|
|
278
434
|
categoryOf,
|
|
279
435
|
rawAgentUrl,
|
|
280
436
|
isBundledCore,
|
|
281
|
-
scanProject
|
|
437
|
+
scanProject,
|
|
438
|
+
KNIT_MARKER_START,
|
|
439
|
+
KNIT_MARKER_END,
|
|
440
|
+
LEGACY_ENGRAM_MARKER_START,
|
|
441
|
+
LEGACY_ENGRAM_MARKER_END,
|
|
442
|
+
generateClaudeMd,
|
|
443
|
+
spliceKnitBlock
|
|
282
444
|
};
|
|
@@ -358,166 +358,7 @@ function buildReverseDependencies(importGraph) {
|
|
|
358
358
|
return reverse;
|
|
359
359
|
}
|
|
360
360
|
|
|
361
|
-
// src/generators/claude-md.ts
|
|
362
|
-
var KNIT_MARKER_START = "<!-- knit:start -->";
|
|
363
|
-
var KNIT_MARKER_END = "<!-- knit:end -->";
|
|
364
|
-
var LEGACY_ENGRAM_MARKER_START = "<!-- engram:start -->";
|
|
365
|
-
var LEGACY_ENGRAM_MARKER_END = "<!-- engram:end -->";
|
|
366
|
-
function generateClaudeMd(config, knowledge, falsePositives) {
|
|
367
|
-
const sections = [
|
|
368
|
-
generateHeader(config),
|
|
369
|
-
generateSessionStartup(),
|
|
370
|
-
knowledge ? generateProjectMap(knowledge) : null,
|
|
371
|
-
generateDomainArchitecture(config),
|
|
372
|
-
falsePositives && falsePositives.length > 0 ? generateFalsePositives(falsePositives) : null,
|
|
373
|
-
generateBuildGates(config),
|
|
374
|
-
generateTierVocabulary(),
|
|
375
|
-
generateWorkflowPointer()
|
|
376
|
-
];
|
|
377
|
-
const body = sections.filter(Boolean).join("\n\n---\n\n");
|
|
378
|
-
return `${KNIT_MARKER_START}
|
|
379
|
-
|
|
380
|
-
${body}
|
|
381
|
-
|
|
382
|
-
${KNIT_MARKER_END}
|
|
383
|
-
`;
|
|
384
|
-
}
|
|
385
|
-
function spliceKnitBlock(existing, newBlock) {
|
|
386
|
-
const markerPairs = [
|
|
387
|
-
[KNIT_MARKER_START, KNIT_MARKER_END],
|
|
388
|
-
[LEGACY_ENGRAM_MARKER_START, LEGACY_ENGRAM_MARKER_END]
|
|
389
|
-
];
|
|
390
|
-
for (const [startMarker, endMarker] of markerPairs) {
|
|
391
|
-
const startIdx = existing.indexOf(startMarker);
|
|
392
|
-
const endIdx = existing.indexOf(endMarker);
|
|
393
|
-
if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
|
|
394
|
-
const before = existing.slice(0, startIdx);
|
|
395
|
-
const after = existing.slice(endIdx + endMarker.length);
|
|
396
|
-
return { content: before + newBlock.trimEnd() + after, mode: "replaced" };
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
return { content: existing, mode: "sidecar-needed" };
|
|
400
|
-
}
|
|
401
|
-
function generateHeader(config) {
|
|
402
|
-
const stackParts = [
|
|
403
|
-
config.stack.language !== "unknown" ? config.stack.language : null,
|
|
404
|
-
config.stack.framework
|
|
405
|
-
].filter(Boolean);
|
|
406
|
-
const stackDesc = stackParts.length > 0 ? `${stackParts.join(" + ")} project. ` : "";
|
|
407
|
-
return `# ${config.name}
|
|
408
|
-
|
|
409
|
-
${stackDesc}Knit-powered workflow. The protocol depth is fetched on demand via \`knit_get_workflow({phase})\` \u2014 this file holds only project-specific facts.`;
|
|
410
|
-
}
|
|
411
|
-
function generateSessionStartup() {
|
|
412
|
-
return `## Session start
|
|
413
|
-
|
|
414
|
-
First action: call \`knit_load_session\`. One MCP call returns last sessions, handoff, learnings, false positives. If \`handoff.md\` exists at the repo root, resume that work first.
|
|
415
|
-
|
|
416
|
-
Protocol Guard runs in \`warn\` mode by default \u2014 adjust with \`knit_set_protocol_strictness\`.`;
|
|
417
|
-
}
|
|
418
|
-
function generateProjectMap(knowledge) {
|
|
419
|
-
const { summary } = knowledge;
|
|
420
|
-
let content = `## Project Map (auto-generated)
|
|
421
|
-
|
|
422
|
-
`;
|
|
423
|
-
if (summary.entryPoints.length > 0) {
|
|
424
|
-
content += `**Entry points:** \`${summary.entryPoints.join("`, `")}\`
|
|
425
|
-
`;
|
|
426
|
-
}
|
|
427
|
-
if (summary.highFanoutFiles.length > 0) {
|
|
428
|
-
const shown = summary.highFanoutFiles.slice(0, 5);
|
|
429
|
-
content += `**High-fanout (change carefully):** \`${shown.join("`, `")}\``;
|
|
430
|
-
if (summary.highFanoutFiles.length > 5) {
|
|
431
|
-
content += ` (+${summary.highFanoutFiles.length - 5} more \u2014 \`knit_find_fanout\`)`;
|
|
432
|
-
}
|
|
433
|
-
content += "\n";
|
|
434
|
-
}
|
|
435
|
-
if (summary.untestedFiles.length > 0) {
|
|
436
|
-
const shown = summary.untestedFiles.slice(0, 3);
|
|
437
|
-
content += `**Untested:** \`${shown.join("`, `")}\``;
|
|
438
|
-
if (summary.untestedFiles.length > 3) {
|
|
439
|
-
content += ` (+${summary.untestedFiles.length - 3} more \u2014 \`knit_query_tests({filter:"untested"})\`)`;
|
|
440
|
-
}
|
|
441
|
-
content += "\n";
|
|
442
|
-
}
|
|
443
|
-
if (summary.largestFiles.length > 0) {
|
|
444
|
-
const top3 = summary.largestFiles.slice(0, 3);
|
|
445
|
-
const list = top3.map((f) => `\`${f.path}\` (${f.lines})`).join(", ");
|
|
446
|
-
content += `**Largest:** ${list}
|
|
447
|
-
`;
|
|
448
|
-
}
|
|
449
|
-
content += `
|
|
450
|
-
**Stats:** ${summary.totalFiles} files, ${summary.totalLines.toLocaleString()} lines`;
|
|
451
|
-
const langs = Object.entries(summary.languageBreakdown).sort((a, b) => b[1] - a[1]).slice(0, 3).map(([ext, count]) => `${ext}: ${count}`);
|
|
452
|
-
if (langs.length > 0) content += ` (${langs.join(", ")})`;
|
|
453
|
-
return content;
|
|
454
|
-
}
|
|
455
|
-
function generateDomainArchitecture(config) {
|
|
456
|
-
if (!config.domains || config.domains.length === 0) {
|
|
457
|
-
return `## Domain Architecture
|
|
458
|
-
|
|
459
|
-
No domains detected. Use \`knit_setup_project\` to describe your project \u2014 Knit will configure domains and review agents.`;
|
|
460
|
-
}
|
|
461
|
-
const rows = config.domains.map((d) => {
|
|
462
|
-
const patterns = d.filePatterns.slice(0, 3).join(", ");
|
|
463
|
-
const agents = d.agents.join(", ");
|
|
464
|
-
return `### ${d.name}
|
|
465
|
-
**Files:** \`${patterns}\`
|
|
466
|
-
**Concern:** ${d.description}
|
|
467
|
-
**Review agents:** \`${agents}\``;
|
|
468
|
-
}).join("\n\n");
|
|
469
|
-
return `## Domain Architecture
|
|
470
|
-
|
|
471
|
-
${rows}`;
|
|
472
|
-
}
|
|
473
|
-
function generateFalsePositives(fps) {
|
|
474
|
-
const items = fps.slice(0, 10).map((fp) => `- **${fp.summary}** \u2014 ${fp.lesson}`).join("\n");
|
|
475
|
-
return `## Known False Positives
|
|
476
|
-
|
|
477
|
-
Review agents should NOT re-flag these \u2014 they're confirmed non-issues from prior sessions:
|
|
478
|
-
|
|
479
|
-
${items}`;
|
|
480
|
-
}
|
|
481
|
-
function generateBuildGates(config) {
|
|
482
|
-
const gates = [];
|
|
483
|
-
if (config.stack.typecheckCommand) gates.push(`- \`${config.stack.typecheckCommand}\``);
|
|
484
|
-
if (config.stack.lintCommand) gates.push(`- \`${config.stack.lintCommand}\``);
|
|
485
|
-
if (config.stack.testFramework) {
|
|
486
|
-
const pm = config.packageManager === "unknown" ? "npm" : config.packageManager;
|
|
487
|
-
gates.push(`- \`${pm} test\``);
|
|
488
|
-
}
|
|
489
|
-
if (config.stack.buildCommand) gates.push(`- \`${config.stack.buildCommand}\``);
|
|
490
|
-
if (gates.length === 0) {
|
|
491
|
-
return `## Build Gates
|
|
492
|
-
|
|
493
|
-
No build gates auto-detected. Add typecheck/lint/test/build commands to your package.json.`;
|
|
494
|
-
}
|
|
495
|
-
return `## Build Gates
|
|
496
|
-
|
|
497
|
-
All must pass before commit:
|
|
498
|
-
|
|
499
|
-
${gates.join("\n")}`;
|
|
500
|
-
}
|
|
501
|
-
function generateTierVocabulary() {
|
|
502
|
-
return `## Tier vocabulary
|
|
503
|
-
|
|
504
|
-
| Tier | When |
|
|
505
|
-
|------|------|
|
|
506
|
-
| **Inquiry** | Read-only ("what", "where", "audit") \u2014 just answer. |
|
|
507
|
-
| **Trivial** | One-line fix \u2014 execute \u2192 verify. |
|
|
508
|
-
| **Standard** | Single-domain bug fix or feature \u2014 research \u2192 execute \u2192 review. |
|
|
509
|
-
| **Complex** | Cross-domain, touches types/auth, high-fanout, or multi-commit arc \u2014 full 6 phases + auto plan mode. |`;
|
|
510
|
-
}
|
|
511
|
-
function generateWorkflowPointer() {
|
|
512
|
-
return `## Workflow on demand
|
|
513
|
-
|
|
514
|
-
Fetch any phase via \`knit_get_workflow({phase})\`. Call with no phase to list available sections.`;
|
|
515
|
-
}
|
|
516
|
-
|
|
517
361
|
export {
|
|
518
362
|
buildKnowledge,
|
|
519
|
-
buildReverseDependencies
|
|
520
|
-
KNIT_MARKER_START,
|
|
521
|
-
generateClaudeMd,
|
|
522
|
-
spliceKnitBlock
|
|
363
|
+
buildReverseDependencies
|
|
523
364
|
};
|