knit-mcp 0.6.4 → 0.7.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 +25 -0
- package/dist/{cache-7HTB4MTJ.js → cache-WGZ2C7BZ.js} +4 -4
- package/dist/{chunk-Y3I4NAKM.js → chunk-3XR77YJM.js} +22 -13
- package/dist/{chunk-YI37OAJ7.js → chunk-HBMF62U4.js} +4 -0
- package/dist/{chunk-QU46A5ZT.js → chunk-QMH2DT6K.js} +6 -6
- package/dist/{chunk-QMICM263.js → chunk-SLN5ABF5.js} +38 -67
- package/dist/{chunk-FEOG4WTP.js → chunk-TRZ3LD6B.js} +1 -1
- package/dist/cli.js +9 -8
- package/dist/{export-D2FXGKBO.js → export-IKPBLZOO.js} +4 -4
- package/dist/{install-agents-JS7WB5E6.js → install-agents-AXT6DMYM.js} +4 -4
- package/dist/instructions-33TUHLTK.js +29 -0
- package/dist/{refresh-UNT4HGYT.js → refresh-MSN5YNPS.js} +2 -2
- package/dist/{status-H2CU72CE.js → status-XN6VHO66.js} +1 -1
- package/dist/{tools-PB7IDFNS.js → tools-KRPOUYNT.js} +391 -82
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,6 +26,29 @@ Knit makes Claude Code do the right thing automatically because it can't predict
|
|
|
26
26
|
|
|
27
27
|
It's a **single product**, not three. Every design choice has to win on memory + tokens + workflow together.
|
|
28
28
|
|
|
29
|
+
## What's new in v0.7.0
|
|
30
|
+
|
|
31
|
+
- **Universal protocol injection.** Knit sets the MCP server-level `instructions` field, so every MCP client (Claude Code, Cursor, Codex) sees Knit's flow at session start — *before* tool descriptions. Session 1 follows the protocol instead of stumbling onto it.
|
|
32
|
+
- **Tier-gated tool surface.** 38 tools split into three tiers: Tier 1 (26 universal — memory, knowledge graph, workflow, classification, false-positive suppression, reflection, Protocol Guard config, diagnostics) is always exposed. Tier 2 (team worktrees, subagent installer) auto-activates when the project shape matches (≥3 detected domains, `.claude/agents/` exists) or via explicit opt-in. Tier 3 (admin/setup) is opt-in only. Solo-domain projects no longer see 9 team-worktree tools cluttering their decision space.
|
|
33
|
+
- **`knit_list_features`** is the discoverability escape hatch — always available, always tells you what's hidden and exactly how to enable it (`knit_enable_feature({feature: "teams" | "subagents" | "admin"})`). Persisted to `~/.knit/projects/<hash>/features.json` so the choice survives sessions.
|
|
34
|
+
- **Inquiry tier in the classifier.** Read-only "what / where / audit / explain" tasks now route to `tier: "inquiry"` with no plan mode and no phases — fixes a long-standing over-routing bug where audit-style questions hijacked Complex.
|
|
35
|
+
- **CLAUDE.md cut ~88%** (16.7 KB → ~2 KB on typical projects). The per-turn context tax dropped sharply; all project-specific content (header, project map, domain architecture, build gates, false positives) stays intact.
|
|
36
|
+
- **Lazy / minimal response modes.** `knit_load_session` returns the lean core by default; opt into more via `include=patterns,teams,metrics,recent_sessions,full_learnings,full_knowledge,all`. `knit_classify_task` returns the minimal shape by default; pass `verbose=true` for the diagnostic fields.
|
|
37
|
+
- **Legacy CLAUDE.md migration.** Users upgrading from v0.5.x with `<!-- engram:start -->/<!-- engram:end -->` markers are auto-migrated — the legacy block is replaced cleanly with the new lean block instead of leaving an orphan.
|
|
38
|
+
|
|
39
|
+
### Per-session token-budget table
|
|
40
|
+
|
|
41
|
+
| Surface | v0.6.5 | v0.7.0 | Cut |
|
|
42
|
+
|---|---|---|---|
|
|
43
|
+
| CLAUDE.md per-turn | ~16.7 KB | ~2 KB | 88% |
|
|
44
|
+
| Tool registry (typical project) | ~6–8 KB | ~3–4 KB | ~50% |
|
|
45
|
+
| `knit_classify_task` response | ~500 tok | ~150 tok | 70% |
|
|
46
|
+
| `knit_load_session` response | ~3–5 KB | ~1.5 KB | ~60% |
|
|
47
|
+
|
|
48
|
+
### Upgrade note
|
|
49
|
+
|
|
50
|
+
After running `npx knit-mcp@latest setup` (or just updating the version pin), **restart Claude Code**. The MCP server's `instructions` field and tier-gated `tools/list` only flow into the system prompt at handshake — the cached process from before the upgrade keeps the v0.6.5 behavior until restart.
|
|
51
|
+
|
|
29
52
|
## Setup (one time)
|
|
30
53
|
|
|
31
54
|
```bash
|
|
@@ -34,6 +57,8 @@ npx knit-mcp@latest setup
|
|
|
34
57
|
|
|
35
58
|
Adds the Knit MCP server to your Claude Code config (`~/.claude.json`). No per-project setup. Open Claude Code in any project and the first MCP tool call auto-initializes everything.
|
|
36
59
|
|
|
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
|
+
|
|
37
62
|
## How data is stored
|
|
38
63
|
|
|
39
64
|
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-QMH2DT6K.js";
|
|
6
|
+
import "./chunk-SLN5ABF5.js";
|
|
7
7
|
import "./chunk-M3YZOJNW.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-3XR77YJM.js";
|
|
9
9
|
import "./chunk-7PPC6IG6.js";
|
|
10
10
|
import "./chunk-BAUQEFYY.js";
|
|
11
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-HBMF62U4.js";
|
|
12
12
|
export {
|
|
13
13
|
detectProjectRoot,
|
|
14
14
|
getBrain,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
projectAgentFile,
|
|
12
12
|
projectAgentsDir,
|
|
13
13
|
sessionsJsonlPath
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-HBMF62U4.js";
|
|
15
15
|
|
|
16
16
|
// src/engine/install-agents.ts
|
|
17
17
|
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
@@ -124,19 +124,27 @@ function bundledCoreDir() {
|
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
// src/generators/agent-md.ts
|
|
127
|
-
var
|
|
128
|
-
var
|
|
127
|
+
var KNIT_AGENT_MARKER_START = "<!-- knit:context:start -->";
|
|
128
|
+
var KNIT_AGENT_MARKER_END = "<!-- knit:context:end -->";
|
|
129
|
+
var LEGACY_ENGRAM_AGENT_MARKER_START = "<!-- engram:context:start -->";
|
|
130
|
+
var LEGACY_ENGRAM_AGENT_MARKER_END = "<!-- engram:context:end -->";
|
|
129
131
|
function personalizeAgent(baseMd, inputs) {
|
|
130
132
|
const block = buildContextBlock(inputs);
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
133
|
+
const candidates = [
|
|
134
|
+
[KNIT_AGENT_MARKER_START, KNIT_AGENT_MARKER_END],
|
|
135
|
+
[LEGACY_ENGRAM_AGENT_MARKER_START, LEGACY_ENGRAM_AGENT_MARKER_END]
|
|
136
|
+
];
|
|
137
|
+
for (const [startMarker, endMarker] of candidates) {
|
|
138
|
+
const startIdx = baseMd.indexOf(startMarker);
|
|
139
|
+
const endIdx = baseMd.indexOf(endMarker);
|
|
140
|
+
if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
|
|
141
|
+
const before = baseMd.slice(0, startIdx);
|
|
142
|
+
const after = baseMd.slice(endIdx + endMarker.length);
|
|
143
|
+
return `${before.trimEnd()}
|
|
137
144
|
|
|
138
145
|
${block}
|
|
139
146
|
${after.trimStart() ? "\n" + after.trimStart() : ""}`;
|
|
147
|
+
}
|
|
140
148
|
}
|
|
141
149
|
return `${baseMd.trimEnd()}
|
|
142
150
|
|
|
@@ -146,7 +154,7 @@ ${block}
|
|
|
146
154
|
function buildContextBlock(inputs) {
|
|
147
155
|
const { config, knowledge, relevantLearnings, falsePositives } = inputs;
|
|
148
156
|
const lines = [];
|
|
149
|
-
lines.push(
|
|
157
|
+
lines.push(KNIT_AGENT_MARKER_START);
|
|
150
158
|
lines.push("");
|
|
151
159
|
lines.push("## Project context (knit-managed; do not edit by hand)");
|
|
152
160
|
lines.push("");
|
|
@@ -186,13 +194,13 @@ function buildContextBlock(inputs) {
|
|
|
186
194
|
}
|
|
187
195
|
lines.push("## Knit MCP tools you can call");
|
|
188
196
|
lines.push("");
|
|
189
|
-
lines.push("You have access to
|
|
197
|
+
lines.push("You have access to Knit's MCP. Call these when you need depth:");
|
|
190
198
|
lines.push("- `knit_query_dependents(file_path)` \u2014 what depends on a file");
|
|
191
199
|
lines.push("- `knit_get_false_positives()` \u2014 full FP list, not just what's above");
|
|
192
200
|
lines.push("- `knit_search_learnings(domains)` \u2014 search past lessons by tag");
|
|
193
201
|
lines.push("- `knit_search_sessions(query)` \u2014 has a past session touched this area?");
|
|
194
202
|
lines.push("");
|
|
195
|
-
lines.push(
|
|
203
|
+
lines.push(KNIT_AGENT_MARKER_END);
|
|
196
204
|
return lines.join("\n");
|
|
197
205
|
}
|
|
198
206
|
function selectRelevantLearnings(allLearnings, agentName, limit = 5) {
|
|
@@ -231,7 +239,8 @@ async function installAgentsForProject(rootPath, config, knowledge, knowledgeBas
|
|
|
231
239
|
if (existsSync2(outFile) && !opts.refresh) {
|
|
232
240
|
try {
|
|
233
241
|
const existing = readFileSync2(outFile, "utf-8");
|
|
234
|
-
|
|
242
|
+
const isKnitManaged = existing.includes(KNIT_AGENT_MARKER_START) || existing.includes(LEGACY_ENGRAM_AGENT_MARKER_START);
|
|
243
|
+
if (!isKnitManaged) {
|
|
235
244
|
result.skippedUserCurated.push(name);
|
|
236
245
|
continue;
|
|
237
246
|
}
|
|
@@ -87,6 +87,9 @@ function classificationMarkerPath(rootPath) {
|
|
|
87
87
|
function sessionMarkerPath(rootPath) {
|
|
88
88
|
return join2(projectDataDir(rootPath), ".session-loaded");
|
|
89
89
|
}
|
|
90
|
+
function featuresConfigPath(rootPath) {
|
|
91
|
+
return join2(projectDataDir(rootPath), "features.json");
|
|
92
|
+
}
|
|
90
93
|
function learningsDir(rootPath) {
|
|
91
94
|
return join2(projectDataDir(rootPath), "learnings");
|
|
92
95
|
}
|
|
@@ -133,6 +136,7 @@ export {
|
|
|
133
136
|
protocolConfigPath,
|
|
134
137
|
classificationMarkerPath,
|
|
135
138
|
sessionMarkerPath,
|
|
139
|
+
featuresConfigPath,
|
|
136
140
|
learningsDir,
|
|
137
141
|
learningsFilePath,
|
|
138
142
|
sessionsLogPath,
|
|
@@ -4,14 +4,14 @@ import {
|
|
|
4
4
|
buildReverseDependencies,
|
|
5
5
|
generateClaudeMd,
|
|
6
6
|
spliceKnitBlock
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-SLN5ABF5.js";
|
|
8
8
|
import {
|
|
9
9
|
readLearnings
|
|
10
10
|
} from "./chunk-M3YZOJNW.js";
|
|
11
11
|
import {
|
|
12
12
|
installAgentsForProject,
|
|
13
13
|
pruneSessionsByAge
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-3XR77YJM.js";
|
|
15
15
|
import {
|
|
16
16
|
scanProject
|
|
17
17
|
} from "./chunk-7PPC6IG6.js";
|
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
sessionsJsonlPath,
|
|
39
39
|
sessionsLogPath,
|
|
40
40
|
teamsPath
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-HBMF62U4.js";
|
|
42
42
|
|
|
43
43
|
// src/mcp/cache.ts
|
|
44
44
|
import { execSync } from "child_process";
|
|
@@ -55,7 +55,7 @@ function generateLearningsContent(config) {
|
|
|
55
55
|
|
|
56
56
|
---
|
|
57
57
|
|
|
58
|
-
## ${date} Project initialized with
|
|
58
|
+
## ${date} Project initialized with Knit workflow
|
|
59
59
|
**Domain(s):** All \u2014 workflow infrastructure
|
|
60
60
|
**Approach:** Auto-detected stack (${config.stack.language}${config.stack.framework ? " + " + config.stack.framework : ""}), generated ${config.domains.length} domains, wired hooks for ${config.targetAgent}.
|
|
61
61
|
**Outcome:** Success \u2014 workflow infrastructure in place
|
|
@@ -630,8 +630,8 @@ function writeProjectClaudeMd(rootPath, config, knowledge) {
|
|
|
630
630
|
const sidecarDir = join(rootPath, ".claude");
|
|
631
631
|
const sidecarPath = join(sidecarDir, "KNIT.md");
|
|
632
632
|
mkdirSync(sidecarDir, { recursive: true });
|
|
633
|
-
const sidecar = `<!-- This file is
|
|
634
|
-
<!-- Your CLAUDE.md exists without
|
|
633
|
+
const sidecar = `<!-- This file is Knit's per-project workflow. -->
|
|
634
|
+
<!-- Your CLAUDE.md exists without Knit markers, so Knit wrote here instead of clobbering it. -->
|
|
635
635
|
<!-- To include this content in CLAUDE.md, add: @.claude/KNIT.md -->
|
|
636
636
|
|
|
637
637
|
${block}`;
|
|
@@ -361,6 +361,8 @@ function buildReverseDependencies(importGraph) {
|
|
|
361
361
|
// src/generators/claude-md.ts
|
|
362
362
|
var KNIT_MARKER_START = "<!-- knit:start -->";
|
|
363
363
|
var KNIT_MARKER_END = "<!-- knit:end -->";
|
|
364
|
+
var LEGACY_ENGRAM_MARKER_START = "<!-- engram:start -->";
|
|
365
|
+
var LEGACY_ENGRAM_MARKER_END = "<!-- engram:end -->";
|
|
364
366
|
function generateClaudeMd(config, knowledge, falsePositives) {
|
|
365
367
|
const sections = [
|
|
366
368
|
generateHeader(config),
|
|
@@ -370,8 +372,7 @@ function generateClaudeMd(config, knowledge, falsePositives) {
|
|
|
370
372
|
falsePositives && falsePositives.length > 0 ? generateFalsePositives(falsePositives) : null,
|
|
371
373
|
generateBuildGates(config),
|
|
372
374
|
generateTierVocabulary(),
|
|
373
|
-
generateWorkflowPointer()
|
|
374
|
-
generatePhaseStatus()
|
|
375
|
+
generateWorkflowPointer()
|
|
375
376
|
];
|
|
376
377
|
const body = sections.filter(Boolean).join("\n\n---\n\n");
|
|
377
378
|
return `${KNIT_MARKER_START}
|
|
@@ -382,12 +383,18 @@ ${KNIT_MARKER_END}
|
|
|
382
383
|
`;
|
|
383
384
|
}
|
|
384
385
|
function spliceKnitBlock(existing, newBlock) {
|
|
385
|
-
const
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
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
|
+
}
|
|
391
398
|
}
|
|
392
399
|
return { content: existing, mode: "sidecar-needed" };
|
|
393
400
|
}
|
|
@@ -399,23 +406,14 @@ function generateHeader(config) {
|
|
|
399
406
|
const stackDesc = stackParts.length > 0 ? `${stackParts.join(" + ")} project. ` : "";
|
|
400
407
|
return `# ${config.name}
|
|
401
408
|
|
|
402
|
-
${stackDesc}
|
|
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.`;
|
|
403
410
|
}
|
|
404
411
|
function generateSessionStartup() {
|
|
405
412
|
return `## Session start
|
|
406
413
|
|
|
407
|
-
First action: call \`knit_load_session\`. One MCP call returns last sessions, handoff, learnings, false positives,
|
|
408
|
-
|
|
409
|
-
After that, state readiness in one line:
|
|
410
|
-
> Session loaded. Learnings: N. Handoff: yes/no. Branch: X. Recent sessions: N.
|
|
411
|
-
|
|
412
|
-
If \`handoff.md\` exists at the repo root, resume that work first.
|
|
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.
|
|
413
415
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
## Protocol Guard
|
|
417
|
-
|
|
418
|
-
This project ships with runtime enforcement of the engram protocol via PreToolUse and SessionStart hooks. Strictness levels: \`off\` (no checks), \`warn\` (reminder, default), \`block\` (hard-fail Edit/Write without prior \`knit_classify_task\`). Change via \`knit_set_protocol_strictness({ level })\`. Inspect via \`knit_get_protocol_strictness\`. The gate exists because protocol compliance is structurally easy to skip \u2014 make it impossible instead.`;
|
|
416
|
+
Protocol Guard runs in \`warn\` mode by default \u2014 adjust with \`knit_set_protocol_strictness\`.`;
|
|
419
417
|
}
|
|
420
418
|
function generateProjectMap(knowledge) {
|
|
421
419
|
const { summary } = knowledge;
|
|
@@ -427,30 +425,30 @@ function generateProjectMap(knowledge) {
|
|
|
427
425
|
`;
|
|
428
426
|
}
|
|
429
427
|
if (summary.highFanoutFiles.length > 0) {
|
|
430
|
-
const shown = summary.highFanoutFiles.slice(0,
|
|
431
|
-
content += `**High-fanout
|
|
432
|
-
if (summary.highFanoutFiles.length >
|
|
433
|
-
content += ` (+${summary.highFanoutFiles.length -
|
|
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\`)`;
|
|
434
432
|
}
|
|
435
433
|
content += "\n";
|
|
436
434
|
}
|
|
437
435
|
if (summary.untestedFiles.length > 0) {
|
|
438
|
-
const shown = summary.untestedFiles.slice(0,
|
|
439
|
-
content += `**Untested
|
|
440
|
-
if (summary.untestedFiles.length >
|
|
441
|
-
content += ` (+${summary.untestedFiles.length -
|
|
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"})\`)`;
|
|
442
440
|
}
|
|
443
441
|
content += "\n";
|
|
444
442
|
}
|
|
445
443
|
if (summary.largestFiles.length > 0) {
|
|
446
444
|
const top3 = summary.largestFiles.slice(0, 3);
|
|
447
|
-
const list = top3.map((f) => `\`${f.path}\` (${f.lines}
|
|
448
|
-
content += `**Largest
|
|
445
|
+
const list = top3.map((f) => `\`${f.path}\` (${f.lines})`).join(", ");
|
|
446
|
+
content += `**Largest:** ${list}
|
|
449
447
|
`;
|
|
450
448
|
}
|
|
451
449
|
content += `
|
|
452
450
|
**Stats:** ${summary.totalFiles} files, ${summary.totalLines.toLocaleString()} lines`;
|
|
453
|
-
const langs = Object.entries(summary.languageBreakdown).sort((a, b) => b[1] - a[1]).slice(0,
|
|
451
|
+
const langs = Object.entries(summary.languageBreakdown).sort((a, b) => b[1] - a[1]).slice(0, 3).map(([ext, count]) => `${ext}: ${count}`);
|
|
454
452
|
if (langs.length > 0) content += ` (${langs.join(", ")})`;
|
|
455
453
|
return content;
|
|
456
454
|
}
|
|
@@ -458,7 +456,7 @@ function generateDomainArchitecture(config) {
|
|
|
458
456
|
if (!config.domains || config.domains.length === 0) {
|
|
459
457
|
return `## Domain Architecture
|
|
460
458
|
|
|
461
|
-
No domains detected. Use \`knit_setup_project\` to describe your project \u2014
|
|
459
|
+
No domains detected. Use \`knit_setup_project\` to describe your project \u2014 Knit will configure domains and review agents.`;
|
|
462
460
|
}
|
|
463
461
|
const rows = config.domains.map((d) => {
|
|
464
462
|
const patterns = d.filePatterns.slice(0, 3).join(", ");
|
|
@@ -501,46 +499,19 @@ All must pass before commit:
|
|
|
501
499
|
${gates.join("\n")}`;
|
|
502
500
|
}
|
|
503
501
|
function generateTierVocabulary() {
|
|
504
|
-
return `## Tier vocabulary
|
|
505
|
-
|
|
506
|
-
You classify each task. No regex, no auto-rules.
|
|
502
|
+
return `## Tier vocabulary
|
|
507
503
|
|
|
508
|
-
| Tier |
|
|
509
|
-
|
|
510
|
-
| **Inquiry** | Read-only
|
|
511
|
-
| **Trivial** | One-line fix
|
|
512
|
-
| **Standard** |
|
|
513
|
-
| **Complex** | Cross-domain, touches types/auth
|
|
514
|
-
|
|
515
|
-
Default to under-classifying. Escalate mid-task if needed.
|
|
516
|
-
|
|
517
|
-
Call \`knit_get_workflow({phase: "tier"})\` for the full decision aid.`;
|
|
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. |`;
|
|
518
510
|
}
|
|
519
511
|
function generateWorkflowPointer() {
|
|
520
512
|
return `## Workflow on demand
|
|
521
513
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
\`\`\`
|
|
525
|
-
knit_get_workflow({phase: "research"}) // RESEARCH phase details
|
|
526
|
-
knit_get_workflow({phase: "plan"}) // PLAN phase + plan-mode rules
|
|
527
|
-
knit_get_workflow({phase: "execute"}) // EXECUTE + TDD
|
|
528
|
-
knit_get_workflow({phase: "optimize"}) // OPTIMIZE + role briefings
|
|
529
|
-
knit_get_workflow({phase: "review"}) // REVIEW gates
|
|
530
|
-
knit_get_workflow({phase: "learn"}) // LEARN quality gate
|
|
531
|
-
knit_get_workflow({phase: "handoff"}) // session handoff
|
|
532
|
-
knit_get_workflow({phase: "ship"}) // commit + ship + production
|
|
533
|
-
knit_get_workflow({phase: "tdd"}) // RED \u2192 GREEN \u2192 REFACTOR
|
|
534
|
-
knit_get_workflow({phase: "tools"}) // engram MCP tools reference
|
|
535
|
-
\`\`\`
|
|
536
|
-
|
|
537
|
-
Call with no \`phase\` to list all sections.`;
|
|
538
|
-
}
|
|
539
|
-
function generatePhaseStatus() {
|
|
540
|
-
return `## Phase Status
|
|
541
|
-
|
|
542
|
-
- **Setup:** \u2705 Engram-generated
|
|
543
|
-
- **Active development:** \u{1F680} In progress`;
|
|
514
|
+
Fetch any phase via \`knit_get_workflow({phase})\`. Call with no phase to list available sections.`;
|
|
544
515
|
}
|
|
545
516
|
|
|
546
517
|
export {
|
package/dist/cli.js
CHANGED
|
@@ -25,10 +25,10 @@ async function runCLI() {
|
|
|
25
25
|
const gradient = (await import("gradient-string")).default;
|
|
26
26
|
const chalk = (await import("chalk")).default;
|
|
27
27
|
const { setupCommand } = await import("./setup-5TUUWLIJ.js");
|
|
28
|
-
const { statusCommand } = await import("./status-
|
|
29
|
-
const { refreshCommand } = await import("./refresh-
|
|
30
|
-
const { installAgentsCommand } = await import("./install-agents-
|
|
31
|
-
const { exportCommand } = await import("./export-
|
|
28
|
+
const { statusCommand } = await import("./status-XN6VHO66.js");
|
|
29
|
+
const { refreshCommand } = await import("./refresh-MSN5YNPS.js");
|
|
30
|
+
const { installAgentsCommand } = await import("./install-agents-AXT6DMYM.js");
|
|
31
|
+
const { exportCommand } = await import("./export-IKPBLZOO.js");
|
|
32
32
|
const ENGRAM_GRADIENT = gradient(["#7c3aed", "#2563eb", "#06b6d4"]);
|
|
33
33
|
const banner = `
|
|
34
34
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
@@ -94,15 +94,16 @@ async function runMCP() {
|
|
|
94
94
|
const { Server } = await import("@modelcontextprotocol/sdk/server/index.js");
|
|
95
95
|
const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js");
|
|
96
96
|
const { ListToolsRequestSchema, CallToolRequestSchema } = await import("@modelcontextprotocol/sdk/types.js");
|
|
97
|
-
const { getBrain, detectProjectRoot, refreshBrain } = await import("./cache-
|
|
98
|
-
const {
|
|
97
|
+
const { getBrain, detectProjectRoot, refreshBrain } = await import("./cache-WGZ2C7BZ.js");
|
|
98
|
+
const { getActiveToolDefinitionsForBrain, handleToolCall } = await import("./tools-KRPOUYNT.js");
|
|
99
|
+
const { KNIT_INSTRUCTIONS } = await import("./instructions-33TUHLTK.js");
|
|
99
100
|
const ROOT_PATH = detectProjectRoot();
|
|
100
101
|
const server = new Server(
|
|
101
102
|
{ name: "knit-brain", version: VERSION },
|
|
102
|
-
{ capabilities: { tools: {} } }
|
|
103
|
+
{ capabilities: { tools: {} }, instructions: KNIT_INSTRUCTIONS }
|
|
103
104
|
);
|
|
104
105
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
105
|
-
tools:
|
|
106
|
+
tools: getActiveToolDefinitionsForBrain(getBrain(ROOT_PATH))
|
|
106
107
|
}));
|
|
107
108
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
108
109
|
const { name, arguments: params } = request.params;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getRecentGlobalLearnings
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-TRZ3LD6B.js";
|
|
4
4
|
import {
|
|
5
5
|
loadKnowledgeBase
|
|
6
6
|
} from "./chunk-BAUQEFYY.js";
|
|
7
7
|
import {
|
|
8
8
|
globalLearningsPath,
|
|
9
9
|
knitRoot
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-HBMF62U4.js";
|
|
11
11
|
|
|
12
12
|
// src/commands/export.ts
|
|
13
13
|
import { existsSync, mkdirSync, readdirSync, writeFileSync, statSync } from "fs";
|
|
@@ -90,7 +90,7 @@ async function exportObsidian(vaultPath, options) {
|
|
|
90
90
|
}
|
|
91
91
|
const globalCount = exported.length - perProjectCount;
|
|
92
92
|
writeFileSync(
|
|
93
|
-
join(vaultPath, "
|
|
93
|
+
join(vaultPath, "Knit Index.md"),
|
|
94
94
|
renderIndex(exported, perProjectCount, globalCount, projectEntryCounts),
|
|
95
95
|
"utf-8"
|
|
96
96
|
);
|
|
@@ -193,7 +193,7 @@ function renderIndex(exported, perProjectCount, globalCount, projectEntryCounts)
|
|
|
193
193
|
arr.push(e);
|
|
194
194
|
perProjectByName.set(e.projectName, arr);
|
|
195
195
|
}
|
|
196
|
-
let out = `#
|
|
196
|
+
let out = `# Knit Knowledge Index
|
|
197
197
|
|
|
198
198
|
Generated ${(/* @__PURE__ */ new Date()).toISOString()}. ${perProjectCount} per-project learnings + ${globalCount} global learnings.
|
|
199
199
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getBrain
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-QMH2DT6K.js";
|
|
4
|
+
import "./chunk-SLN5ABF5.js";
|
|
5
5
|
import "./chunk-M3YZOJNW.js";
|
|
6
6
|
import {
|
|
7
7
|
installAgentsForProject
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-3XR77YJM.js";
|
|
9
9
|
import "./chunk-7PPC6IG6.js";
|
|
10
10
|
import "./chunk-BAUQEFYY.js";
|
|
11
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-HBMF62U4.js";
|
|
12
12
|
|
|
13
13
|
// src/commands/install-agents.ts
|
|
14
14
|
import { existsSync } from "fs";
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// src/mcp/instructions.ts
|
|
2
|
+
var KNIT_INSTRUCTIONS = `Knit is a memory + workflow layer for this project. It provides per-project memory across sessions, a knowledge graph (imports/exports/tests), and a tier-routed workflow protocol.
|
|
3
|
+
|
|
4
|
+
ALWAYS at session start:
|
|
5
|
+
1. Call knit_load_session \u2014 returns prior handoff, top learnings, false positives. If has_unfinished_work is true, resume that handoff instead of starting fresh.
|
|
6
|
+
2. For any non-trivial task, call knit_classify_task BEFORE editing or writing \u2014 returns tier (inquiry / trivial / standard / complex) and phases.
|
|
7
|
+
3. If tier=complex with auto_plan_mode=true, call EnterPlanMode immediately. Do not start editing.
|
|
8
|
+
4. If tier=inquiry, just answer \u2014 no plan mode, no phases. Re-classify only if scope grows into writes.
|
|
9
|
+
5. Before reporting a task done, call knit_record_learning if anything non-obvious surfaced (not a substring restatement of prior learnings).
|
|
10
|
+
|
|
11
|
+
When to reach for other Knit tools:
|
|
12
|
+
- knit_query_imports / knit_query_exports / knit_query_dependents / knit_query_tests \u2014 use instead of grep when the knowledge index is fresh.
|
|
13
|
+
- knit_search_learnings \u2014 call before re-investigating a domain. The point of memory is to skip what you've already learned.
|
|
14
|
+
- knit_search_sessions \u2014 answers "have I done this before?"
|
|
15
|
+
- knit_search_global_learnings \u2014 same, but across all your projects (Knit's cross-project pool).
|
|
16
|
+
- knit_get_workflow({phase}) \u2014 fetch protocol depth for one phase on demand. Do not try to remember the workflow; ask for it.
|
|
17
|
+
- knit_list_features \u2014 if you want to do X but the tool isn't visible, this surfaces what's hidden and how to enable it.
|
|
18
|
+
- knit_save_handoff \u2014 call when context degrades or session ends so the next session resumes cleanly.
|
|
19
|
+
|
|
20
|
+
The protocol enforces a 4-tier classifier:
|
|
21
|
+
- Inquiry: read-only "what / where / audit / explain" \u2014 just answer.
|
|
22
|
+
- Trivial: single-file obvious change \u2014 EXECUTE \u2192 VERIFY \u2192 LEARN.
|
|
23
|
+
- Standard: bug fix or single-domain feature \u2014 RESEARCH \u2192 EXECUTE \u2192 OPTIMIZE \u2192 REVIEW \u2192 LEARN.
|
|
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
|
+
|
|
26
|
+
Knit provides inputs; you make the calls. When in doubt, under-classify \u2014 easier to escalate mid-task than to downgrade.`;
|
|
27
|
+
export {
|
|
28
|
+
KNIT_INSTRUCTIONS
|
|
29
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildKnowledge,
|
|
3
3
|
generateClaudeMd
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-SLN5ABF5.js";
|
|
5
5
|
import {
|
|
6
6
|
findFalsePositives
|
|
7
7
|
} from "./chunk-M3YZOJNW.js";
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
knowledgePath,
|
|
13
13
|
learningsDir,
|
|
14
14
|
projectDataDir
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-HBMF62U4.js";
|
|
16
16
|
|
|
17
17
|
// src/commands/refresh.ts
|
|
18
18
|
import { readFileSync, readdirSync, writeFileSync, existsSync } from "fs";
|