knodin 0.7.4 → 0.7.6
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 +4 -1
- package/dist/bin/cli.js +108 -1859
- package/dist/bin/launcher.js +3 -10
- package/dist/chunks/chunk-DMQAGX77.js +654 -0
- package/dist/chunks/chunk-F4Z3Z766.js +4 -0
- package/dist/chunks/chunk-SIJAQVSX.js +3 -0
- package/dist/chunks/chunk-X6M4HUUE.js +2 -0
- package/dist/chunks/chunk-YPRMY2LP.js +8 -0
- package/dist/chunks/pure-compression-cli-4TA2TQD5.js +5 -0
- package/dist/chunks/server-7EDF4CBY.js +14 -0
- package/dist/chunks/structural-fast-path-KD5KQSPX.js +4 -0
- package/dist/src/init-progress-worker.js +2 -106
- package/dist/src/repair-progress-worker.js +2 -120
- package/docs/INSTALLATION.md +17 -1
- package/docs/releases/0.7.6.md +25 -0
- package/package.json +1 -110
- package/dist/src/agent-integration.js +0 -238
- package/dist/src/artifact-refresh.js +0 -81
- package/dist/src/cli-args.js +0 -274
- package/dist/src/cli-model.js +0 -358
- package/dist/src/codeflow-replay.js +0 -80
- package/dist/src/compact-structural.js +0 -96
- package/dist/src/competitive-cold-mcp.js +0 -40
- package/dist/src/competitive-constraints.js +0 -20
- package/dist/src/competitive-manifest.js +0 -411
- package/dist/src/competitive-measurement.js +0 -183
- package/dist/src/competitive-runner.js +0 -487
- package/dist/src/competitive-sandbox.js +0 -108
- package/dist/src/context-export.js +0 -422
- package/dist/src/context.js +0 -102
- package/dist/src/diagnostics.js +0 -449
- package/dist/src/docs-sections.js +0 -141
- package/dist/src/doctor.js +0 -380
- package/dist/src/engine/ann-hnsw.js +0 -271
- package/dist/src/engine/embeddings.js +0 -193
- package/dist/src/engine/file-walker.js +0 -43
- package/dist/src/engine/git-history.js +0 -289
- package/dist/src/engine/index.js +0 -13377
- package/dist/src/engine/perf.js +0 -115
- package/dist/src/engine/prune.js +0 -112
- package/dist/src/engine/scip-import.js +0 -408
- package/dist/src/engine/source-policy.js +0 -69
- package/dist/src/engine/sqlite.js +0 -71
- package/dist/src/engine/symbol-delete.js +0 -58
- package/dist/src/execution-profile.js +0 -203
- package/dist/src/failure-diagnosis.js +0 -649
- package/dist/src/fleet.js +0 -7
- package/dist/src/git-executable.js +0 -31
- package/dist/src/graph-query-health.js +0 -115
- package/dist/src/hook-manager-integration.js +0 -156
- package/dist/src/index-activity.js +0 -125
- package/dist/src/init-progress.js +0 -155
- package/dist/src/init.js +0 -1254
- package/dist/src/lifecycle-health.js +0 -250
- package/dist/src/lsp-readonly.js +0 -217
- package/dist/src/output-compression.js +0 -629
- package/dist/src/output-telemetry.js +0 -363
- package/dist/src/pr-triage.js +0 -638
- package/dist/src/progressive-evidence.js +0 -473
- package/dist/src/pure-compression-cli.js +0 -101
- package/dist/src/relationship-adapters.js +0 -370
- package/dist/src/release-attestation.js +0 -533
- package/dist/src/release-preflight.js +0 -510
- package/dist/src/repair-progress.js +0 -262
- package/dist/src/repository-init-process.js +0 -173
- package/dist/src/repository-management.js +0 -1231
- package/dist/src/response-budget.js +0 -194
- package/dist/src/server.js +0 -73
- package/dist/src/structural-fast-path.js +0 -338
- package/dist/src/structural-snapshot.js +0 -33
- package/dist/src/system-config.js +0 -615
- package/dist/src/terminal-help.js +0 -83
- package/dist/src/tools/knodin-tools.js +0 -1529
- package/dist/src/update-ceremony.js +0 -158
- package/dist/src/update-policy.js +0 -944
- package/dist/src/update-trust.js +0 -503
- package/dist/src/version.js +0 -13
- package/dist/src/visualization.js +0 -162
- package/dist/src/wait-for-fresh.js +0 -98
- package/dist/src/worktree-lifecycle.js +0 -231
- package/docs/CONTAINED-EXECUTION.md +0 -77
- package/docs/DIAGNOSTICS.md +0 -45
- package/docs/GIT-HISTORY-REVIEW.md +0 -39
- package/docs/PROGRESSIVE-EVIDENCE.md +0 -37
- package/docs/PT-ACCESS-RECOMMENDATION.md +0 -91
- package/docs/RELEASE-0.3-EVIDENCE.md +0 -73
- package/docs/SCIP-IMPORT.md +0 -57
- package/docs/SIGNED-UPDATES.md +0 -151
- package/docs/TELEMETRY.md +0 -46
- package/docs/assets/knodin-favicon.svg +0 -4
- package/docs/releases/0.3.0.md +0 -46
- package/docs/releases/0.4.0.md +0 -68
- package/docs/releases/0.4.1.md +0 -28
- package/docs/releases/0.4.2.md +0 -27
- package/docs/releases/0.4.3.md +0 -23
- package/docs/releases/0.5.0.md +0 -29
- package/docs/releases/0.5.1.md +0 -17
- package/docs/releases/0.6.0.md +0 -18
- package/docs/releases/0.7.0.md +0 -24
- package/docs/releases/0.7.1.md +0 -21
- package/docs/releases/0.7.2.md +0 -21
- package/docs/releases/0.7.3.md +0 -23
- package/docs/releases/0.7.4.md +0 -17
- package/schemas/release-attestation-v1.schema.json +0 -210
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
export const EXPECTED_RELATIONSHIPS = [
|
|
2
|
-
"packages/api/route.ts->packages/auth/service.ts",
|
|
3
|
-
"packages/api/route.ts->packages/audit/store.ts",
|
|
4
|
-
"packages/auth/service.ts->packages/data/users.ts",
|
|
5
|
-
];
|
|
6
|
-
export function normalizeCodeFlowRelationships(connections) {
|
|
7
|
-
return connections.map((value) => {
|
|
8
|
-
const edge = value;
|
|
9
|
-
return {
|
|
10
|
-
// CodeFlow exports callee/definition as source and caller as target.
|
|
11
|
-
from: String(edge.target ?? ""),
|
|
12
|
-
to: String(edge.source ?? ""),
|
|
13
|
-
kind: typeof edge.kind === "string" ? edge.kind : null,
|
|
14
|
-
extractor: typeof edge.extractor === "string" ? edge.extractor : null,
|
|
15
|
-
confidence: edge.confidence === "exact" || edge.confidence === "heuristic" ? edge.confidence : null,
|
|
16
|
-
sourceFile: typeof edge.sourceFile === "string" ? edge.sourceFile : null,
|
|
17
|
-
sourceLine: typeof edge.sourceLine === "number" ? edge.sourceLine : null,
|
|
18
|
-
evidence: typeof edge.evidence === "string" ? edge.evidence : null,
|
|
19
|
-
raw: value,
|
|
20
|
-
};
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
export function scoreRelationships(relationships) {
|
|
24
|
-
const actual = new Set(relationships.map((edge) => `${edge.from}->${edge.to}`));
|
|
25
|
-
const expected = new Set(EXPECTED_RELATIONSHIPS);
|
|
26
|
-
const truePositives = [...expected].filter((edge) => actual.has(edge));
|
|
27
|
-
const falseNegatives = [...expected].filter((edge) => !actual.has(edge));
|
|
28
|
-
const falsePositives = [...actual].filter((edge) => !expected.has(edge));
|
|
29
|
-
const malformed = relationships.filter((edge) => !edge.from || !edge.to);
|
|
30
|
-
return {
|
|
31
|
-
truePositives,
|
|
32
|
-
falsePositives,
|
|
33
|
-
falseNegatives,
|
|
34
|
-
precision: actual.size === 0 ? 0 : truePositives.length / actual.size,
|
|
35
|
-
recall: truePositives.length / expected.size,
|
|
36
|
-
unsupportedEdgeRate: falseNegatives.length / expected.size,
|
|
37
|
-
malformedRelationships: malformed.length,
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
export function blastRadiusCompleteness(relationships) {
|
|
41
|
-
const origin = "packages/data/users.ts";
|
|
42
|
-
const expected = new Set(["packages/auth/service.ts", "packages/api/route.ts"]);
|
|
43
|
-
const adjacency = new Map();
|
|
44
|
-
for (const edge of relationships) {
|
|
45
|
-
if (!adjacency.has(edge.to))
|
|
46
|
-
adjacency.set(edge.to, new Set());
|
|
47
|
-
adjacency.get(edge.to)?.add(edge.from);
|
|
48
|
-
}
|
|
49
|
-
const found = new Set();
|
|
50
|
-
const queue = [origin];
|
|
51
|
-
while (queue.length) {
|
|
52
|
-
const current = queue.shift();
|
|
53
|
-
for (const dependent of adjacency.get(current) ?? []) {
|
|
54
|
-
if (dependent === origin || found.has(dependent))
|
|
55
|
-
continue;
|
|
56
|
-
found.add(dependent);
|
|
57
|
-
queue.push(dependent);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
return {
|
|
61
|
-
origin,
|
|
62
|
-
expected: [...expected],
|
|
63
|
-
found: [...found].sort(),
|
|
64
|
-
missing: [...expected].filter((file) => !found.has(file)),
|
|
65
|
-
completeness: [...expected].filter((file) => found.has(file)).length / expected.size,
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
export function provenanceCoverage(relationships) {
|
|
69
|
-
const count = relationships.length;
|
|
70
|
-
const rate = (predicate) => count === 0 ? 0 : relationships.filter(predicate).length / count;
|
|
71
|
-
return {
|
|
72
|
-
relationships: count,
|
|
73
|
-
relationKind: rate((edge) => edge.kind !== null),
|
|
74
|
-
extractorIdentity: rate((edge) => edge.extractor !== null),
|
|
75
|
-
exactOrHeuristicConfidence: rate((edge) => edge.confidence !== null),
|
|
76
|
-
sourceFile: rate((edge) => edge.sourceFile !== null),
|
|
77
|
-
sourceLine: rate((edge) => edge.sourceLine !== null),
|
|
78
|
-
boundedSourceEvidence: rate((edge) => edge.evidence !== null),
|
|
79
|
-
};
|
|
80
|
-
}
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
const IDENTITY_PREFIX = "sym_";
|
|
2
|
-
/** A stable, repository-scoped shorthand. Prefix collisions remain ambiguity-safe
|
|
3
|
-
* because selectors are expanded as prefixes rather than guessed as one symbol. */
|
|
4
|
-
export function compactIdentity(identity) {
|
|
5
|
-
if (!identity)
|
|
6
|
-
return "~?";
|
|
7
|
-
const body = identity.startsWith(IDENTITY_PREFIX)
|
|
8
|
-
? identity.slice(IDENTITY_PREFIX.length)
|
|
9
|
-
: identity;
|
|
10
|
-
return `~${body.slice(0, 6)}`;
|
|
11
|
-
}
|
|
12
|
-
export function expandCompactIdentity(identity) {
|
|
13
|
-
return identity?.startsWith("~") ? `${IDENTITY_PREFIX}${identity.slice(1)}*` : identity;
|
|
14
|
-
}
|
|
15
|
-
function freshness(value) {
|
|
16
|
-
if (value === "reconciled")
|
|
17
|
-
return "reconciled";
|
|
18
|
-
if (value === "unknown")
|
|
19
|
-
return "unknown";
|
|
20
|
-
return "fresh";
|
|
21
|
-
}
|
|
22
|
-
function terseSignature(row) {
|
|
23
|
-
const signature = row.signature?.replace(/\s+/g, " ").trim() ?? "";
|
|
24
|
-
if (!signature)
|
|
25
|
-
return "";
|
|
26
|
-
const python = /^(.*?:)(?:\s|$)/.exec(signature)?.[1];
|
|
27
|
-
return python ?? signature;
|
|
28
|
-
}
|
|
29
|
-
function rowLine(row, repeatFile) {
|
|
30
|
-
const nested = row.parent?.symbol ? `${row.parent.symbol}/` : "";
|
|
31
|
-
const filePrefix = repeatFile ? `${row.file ?? "?"}:` : "";
|
|
32
|
-
const location = `${filePrefix}${row.line ?? "?"}`;
|
|
33
|
-
const signature = terseSignature(row);
|
|
34
|
-
const signatureSuffix = signature ? ` ${signature}` : "";
|
|
35
|
-
return `${compactIdentity(row.identity)} ${row.kind ?? "?"} ${nested}${row.symbol ?? "?"}@${location}${signatureSuffix}`;
|
|
36
|
-
}
|
|
37
|
-
function withinBytes(header, rows, byteBudget) {
|
|
38
|
-
let selected = rows;
|
|
39
|
-
if (byteBudget !== undefined) {
|
|
40
|
-
while (selected.length > 0 &&
|
|
41
|
-
Buffer.byteLength([header(selected.length), ...selected].join("\n"), "utf8") > byteBudget)
|
|
42
|
-
selected = selected.slice(0, -1);
|
|
43
|
-
}
|
|
44
|
-
const output = [header(selected.length), ...selected].join("\n");
|
|
45
|
-
return byteBudget !== undefined && Buffer.byteLength(output, "utf8") > byteBudget ? "" : output;
|
|
46
|
-
}
|
|
47
|
-
export function compactQueryResult(result, byteBudget) {
|
|
48
|
-
if (result.ambiguity)
|
|
49
|
-
return compactAmbiguity(result.ambiguity.candidates, result.staleness);
|
|
50
|
-
const total = result.count;
|
|
51
|
-
const state = freshness(result.staleness);
|
|
52
|
-
if (result.pattern === "project_overview") {
|
|
53
|
-
const rows = result.results.map((row) => `${row.symbol ?? row.file ?? "."} ${row.fileCount ?? 0} ${row.sizeBytes ?? 0}B`);
|
|
54
|
-
return withinBytes((n) => `${state} ${n}/${total}`, rows, byteBudget);
|
|
55
|
-
}
|
|
56
|
-
const repeatFile = result.pattern === "batch_outline";
|
|
57
|
-
const rows = result.results.map((row) => rowLine(row, repeatFile));
|
|
58
|
-
return withinBytes((n) => {
|
|
59
|
-
const continuation = result.hasMore ? "+" : "";
|
|
60
|
-
const target = result.target ? ` ${result.target}` : "";
|
|
61
|
-
return `${state} ${n}/${total}${continuation}${target}`;
|
|
62
|
-
}, rows, byteBudget);
|
|
63
|
-
}
|
|
64
|
-
export function compactSearchResult(page, query, byteBudget) {
|
|
65
|
-
const normalize = (value) => value.toLocaleLowerCase().replace(/[^a-z0-9]/g, "");
|
|
66
|
-
const normalized = normalize(query);
|
|
67
|
-
const matches = page.results.filter((row) => normalize(row.symbol).includes(normalized));
|
|
68
|
-
const state = freshness(matches[0]?.staleness ?? page.results[0]?.staleness);
|
|
69
|
-
const rows = matches.map((row) => {
|
|
70
|
-
const source = row.source ? ` ${row.source}` : "";
|
|
71
|
-
return `${compactIdentity(row.identity)} ${row.kind} @${row.filePath}${source}`;
|
|
72
|
-
});
|
|
73
|
-
return withinBytes((n) => `${state} ${n}/${matches.length}${page.hasMore ? "+" : ""} ${query}`, rows, byteBudget);
|
|
74
|
-
}
|
|
75
|
-
export function compactExplainResult(result, selectorFile, byteBudget) {
|
|
76
|
-
if (result.ambiguity)
|
|
77
|
-
return compactAmbiguity(result.ambiguity.candidates, result.staleness);
|
|
78
|
-
const numbered = result.source ?? "";
|
|
79
|
-
const firstLine = Number(/^(\d+): /.exec(numbered)?.[1] ?? 0);
|
|
80
|
-
const source = numbered
|
|
81
|
-
.split("\n")
|
|
82
|
-
.map((line) => line.replace(/^\d+: /, ""))
|
|
83
|
-
.join("\n");
|
|
84
|
-
const header = `${freshness(result.staleness)} ${compactIdentity(result.identity)} ${selectorFile ?? "?"}:${firstLine || "?"}`;
|
|
85
|
-
const output = `${header}\n${source}`;
|
|
86
|
-
if (byteBudget === undefined || Buffer.byteLength(output, "utf8") <= byteBudget)
|
|
87
|
-
return output;
|
|
88
|
-
const omitted = `${header}\nomitted ${Buffer.byteLength(source, "utf8")}B`;
|
|
89
|
-
return Buffer.byteLength(omitted, "utf8") <= byteBudget ? omitted : "";
|
|
90
|
-
}
|
|
91
|
-
function compactAmbiguity(candidates, staleness) {
|
|
92
|
-
return [
|
|
93
|
-
`ambiguous ${freshness(staleness)} ${candidates.length}`,
|
|
94
|
-
...candidates.map((candidate) => `${compactIdentity(candidate.identity)} ${candidate.kind} ${candidate.file}:${candidate.line}`),
|
|
95
|
-
].join("\n");
|
|
96
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
2
|
-
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
3
|
-
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
4
|
-
import { sampleOperation } from "./competitive-measurement.js";
|
|
5
|
-
function textOf(value) {
|
|
6
|
-
return (value.content ?? [])
|
|
7
|
-
.filter((item) => item.type === "text")
|
|
8
|
-
.map((item) => item.text ?? "")
|
|
9
|
-
.join("\n");
|
|
10
|
-
}
|
|
11
|
-
/** Measure five cold calls, rebuilding the MCP process before every recorded call. */
|
|
12
|
-
export async function measureColdMcp(command, args, cwd, side, clientName) {
|
|
13
|
-
let last;
|
|
14
|
-
let error;
|
|
15
|
-
const { measurement } = await sampleOperation(async () => {
|
|
16
|
-
const transport = new StdioClientTransport({ command, args, cwd, stderr: "pipe" });
|
|
17
|
-
const client = new Client({ name: clientName, version: "1" }, { capabilities: {} });
|
|
18
|
-
try {
|
|
19
|
-
await client.connect(transport);
|
|
20
|
-
last = await client.callTool({ name: side.tool, arguments: side.args });
|
|
21
|
-
error = undefined;
|
|
22
|
-
}
|
|
23
|
-
catch (cause) {
|
|
24
|
-
error = cause instanceof Error ? cause.message : String(cause);
|
|
25
|
-
}
|
|
26
|
-
finally {
|
|
27
|
-
await transport.close().catch(() => undefined);
|
|
28
|
-
}
|
|
29
|
-
return last;
|
|
30
|
-
}, { mode: "cold" });
|
|
31
|
-
const response = last ? textOf(last) : "";
|
|
32
|
-
return {
|
|
33
|
-
ok: !error && !last?.isError,
|
|
34
|
-
error,
|
|
35
|
-
...measurement,
|
|
36
|
-
responseBytes: Buffer.byteLength(response),
|
|
37
|
-
responseSha256: createHash("sha256").update(response).digest("hex"),
|
|
38
|
-
response,
|
|
39
|
-
};
|
|
40
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/** Verifies the local-only, single-gateway contract that qualifies a competitive replay. */
|
|
2
|
-
export function assessCompetitiveConstraints(tools) {
|
|
3
|
-
const mcpToolNames = tools.map((tool) => tool.name).sort();
|
|
4
|
-
const schemaBytes = Buffer.byteLength(JSON.stringify(tools));
|
|
5
|
-
const violations = [];
|
|
6
|
-
if (tools.length !== 1)
|
|
7
|
-
violations.push(`Expected one MCP tool, found ${tools.length}`);
|
|
8
|
-
if (mcpToolNames.length !== 1 || mcpToolNames[0] !== "knodin")
|
|
9
|
-
violations.push(`Expected only the knodin gateway, found ${mcpToolNames.join(", ") || "none"}`);
|
|
10
|
-
return {
|
|
11
|
-
passed: violations.length === 0,
|
|
12
|
-
mcpToolCount: tools.length,
|
|
13
|
-
mcpToolNames,
|
|
14
|
-
schemaBytes,
|
|
15
|
-
schemaTokens: Math.ceil(schemaBytes / 4),
|
|
16
|
-
localOnly: true,
|
|
17
|
-
optionalServices: ["local GitHub CLI integration (prs operation)"],
|
|
18
|
-
violations,
|
|
19
|
-
};
|
|
20
|
-
}
|
|
@@ -1,411 +0,0 @@
|
|
|
1
|
-
const bunHarness = (script) => ({ output }) => ["bun", `scripts/${script}`, output];
|
|
2
|
-
export const COMPETITIVE_MANIFEST = [
|
|
3
|
-
{
|
|
4
|
-
id: "gitnexus",
|
|
5
|
-
name: "GitNexus",
|
|
6
|
-
version: "1.6.9",
|
|
7
|
-
roadmap: ["C2", "C4", "C5", "C6", "C7", "C8", "C9", "C10", "C24", "C25", "C26"],
|
|
8
|
-
baseline: "gitnexus-vs-knodin.raw.json",
|
|
9
|
-
requirements: [
|
|
10
|
-
{ type: "command", value: "gitnexus" },
|
|
11
|
-
{ type: "command", value: "bun" },
|
|
12
|
-
],
|
|
13
|
-
versionCommand: ["gitnexus", "--version"],
|
|
14
|
-
prepare: [["gitnexus", "analyze"]],
|
|
15
|
-
command: bunHarness("gitnexus-bakeoff.ts"),
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
id: "codegraph",
|
|
19
|
-
name: "CodeGraph",
|
|
20
|
-
version: "1.5.0",
|
|
21
|
-
roadmap: ["C2", "C3", "C11", "C24", "C25"],
|
|
22
|
-
baseline: "codegraph-vs-knodin.raw.json",
|
|
23
|
-
requirements: [
|
|
24
|
-
{ type: "command", value: "codegraph" },
|
|
25
|
-
{ type: "command", value: "bun" },
|
|
26
|
-
],
|
|
27
|
-
versionCommand: ["codegraph", "--version"],
|
|
28
|
-
command: bunHarness("codegraph-bakeoff.ts"),
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
id: "code-review-graph",
|
|
32
|
-
name: "code-review-graph",
|
|
33
|
-
version: "2.3.7",
|
|
34
|
-
roadmap: ["C3", "C5", "C11", "C12", "C15", "C17", "C24", "C26"],
|
|
35
|
-
baseline: "code-review-graph-vs-knodin.raw.json",
|
|
36
|
-
requirements: [
|
|
37
|
-
{ type: "command", value: "code-review-graph" },
|
|
38
|
-
{ type: "command", value: "bun" },
|
|
39
|
-
],
|
|
40
|
-
versionCommand: ["code-review-graph", "--version"],
|
|
41
|
-
prepare: [["code-review-graph", "build"]],
|
|
42
|
-
command: bunHarness("code-review-graph-bakeoff.ts"),
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
id: "graphify",
|
|
46
|
-
name: "Graphify",
|
|
47
|
-
version: "0.9.23",
|
|
48
|
-
roadmap: ["C2", "C3", "C11", "C12", "C13", "C17", "C24", "C26", "C41"],
|
|
49
|
-
baseline: "graphify-vs-knodin.raw.json",
|
|
50
|
-
requirements: [
|
|
51
|
-
{ type: "command", value: "graphify" },
|
|
52
|
-
{ type: "command", value: "graphify-mcp" },
|
|
53
|
-
{ type: "command", value: "bun" },
|
|
54
|
-
],
|
|
55
|
-
versionCommand: ["graphify", "--version"],
|
|
56
|
-
prepare: [
|
|
57
|
-
["graphify", "extract", ".", "--code-only", "--no-cluster"],
|
|
58
|
-
["graphify", "cluster-only", ".", "--no-label", "--no-viz"],
|
|
59
|
-
],
|
|
60
|
-
command: bunHarness("graphify-bakeoff.ts"),
|
|
61
|
-
caseMappings: [
|
|
62
|
-
{
|
|
63
|
-
idPattern: "^neighbors-calls-(?:path|default)(?:-cold)?$",
|
|
64
|
-
useCase: "direct call neighbors",
|
|
65
|
-
mode: "warm",
|
|
66
|
-
scope: {
|
|
67
|
-
competitorOperation: "get_neighbors",
|
|
68
|
-
knodinOperation: "query:traverse",
|
|
69
|
-
dimensions: ["target", "direction=both", "relation=call", "depth=1", "items=200"],
|
|
70
|
-
},
|
|
71
|
-
budgets: { bytes: null, tokens: null, items: 200 },
|
|
72
|
-
reason: "Both sides return direct inbound and outbound call neighbors for createEngine.",
|
|
73
|
-
oracleId: "create-engine-both",
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
idPattern: "^god-nodes-10-default(?:-cold)?$",
|
|
77
|
-
useCase: "bounded architectural hubs",
|
|
78
|
-
mode: "warm",
|
|
79
|
-
scope: {
|
|
80
|
-
competitorOperation: "god_nodes",
|
|
81
|
-
knodinOperation: "map:minimal",
|
|
82
|
-
dimensions: ["repository scope", "items=10", "hub ranking"],
|
|
83
|
-
},
|
|
84
|
-
budgets: { bytes: null, tokens: null, items: 10 },
|
|
85
|
-
reason: "Both sides return the ten highest-ranked architectural hubs.",
|
|
86
|
-
oracleId: "architecture-facet",
|
|
87
|
-
},
|
|
88
|
-
],
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
id: "serena",
|
|
92
|
-
name: "Serena",
|
|
93
|
-
version: "1.6.2.dev0",
|
|
94
|
-
roadmap: ["C11", "C12", "C15", "C24", "C25"],
|
|
95
|
-
baseline: "serena-vs-knodin.raw.json",
|
|
96
|
-
requirements: [
|
|
97
|
-
{ type: "command", value: "serena" },
|
|
98
|
-
{ type: "command", value: "bun" },
|
|
99
|
-
],
|
|
100
|
-
versionCommand: ["serena", "--version"],
|
|
101
|
-
command: ({ output, fixture }) => ["bun", "scripts/serena-bakeoff.ts", fixture, output],
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
id: "codebase-memory",
|
|
105
|
-
name: "codebase-memory-mcp",
|
|
106
|
-
version: "0.9.0",
|
|
107
|
-
roadmap: ["C4", "C10", "C11", "C12", "C13", "C16", "C24", "C25", "C26", "C41"],
|
|
108
|
-
baseline: "codebase-memory-vs-knodin.raw.json",
|
|
109
|
-
requirements: [
|
|
110
|
-
{ type: "command", value: "codebase-memory-mcp" },
|
|
111
|
-
{ type: "command", value: "bun" },
|
|
112
|
-
],
|
|
113
|
-
versionCommand: ["codebase-memory-mcp", "--version"],
|
|
114
|
-
command: bunHarness("codebase-memory-bakeoff.ts"),
|
|
115
|
-
caseMappings: [
|
|
116
|
-
{
|
|
117
|
-
idPattern: "^search-graph-e0-c0(?:-cold)?$",
|
|
118
|
-
useCase: "bounded graph search",
|
|
119
|
-
mode: "warm",
|
|
120
|
-
scope: {
|
|
121
|
-
competitorOperation: "search_graph",
|
|
122
|
-
knodinOperation: "search",
|
|
123
|
-
dimensions: ["query=create engine", "offset=0", "items=10", "connected=false"],
|
|
124
|
-
},
|
|
125
|
-
budgets: { bytes: null, tokens: null, items: 10 },
|
|
126
|
-
reason: "Both sides run the same unexpanded first-page query with the same item limit.",
|
|
127
|
-
oracleId: "create-engine-definition",
|
|
128
|
-
},
|
|
129
|
-
{
|
|
130
|
-
idPattern: "^trace-inbound-calls-r0-t1(?:-cold)?$",
|
|
131
|
-
useCase: "typed call traversal",
|
|
132
|
-
mode: "warm",
|
|
133
|
-
scope: {
|
|
134
|
-
competitorOperation: "trace_path",
|
|
135
|
-
knodinOperation: "query:traverse",
|
|
136
|
-
dimensions: [
|
|
137
|
-
"target=createEngine",
|
|
138
|
-
"direction",
|
|
139
|
-
"relation=call",
|
|
140
|
-
"depth=3",
|
|
141
|
-
"include_tests=true",
|
|
142
|
-
],
|
|
143
|
-
},
|
|
144
|
-
budgets: { bytes: null, tokens: null, items: 100 },
|
|
145
|
-
reason: "Both sides use the same target, direction, call relation, depth, and test scope.",
|
|
146
|
-
oracleId: "create-engine-callers",
|
|
147
|
-
},
|
|
148
|
-
{
|
|
149
|
-
idPattern: "^trace-outbound-calls-r0-t1(?:-cold)?$",
|
|
150
|
-
useCase: "typed call traversal",
|
|
151
|
-
mode: "warm",
|
|
152
|
-
scope: {
|
|
153
|
-
competitorOperation: "trace_path",
|
|
154
|
-
knodinOperation: "query:traverse",
|
|
155
|
-
dimensions: [
|
|
156
|
-
"target=createEngine",
|
|
157
|
-
"direction",
|
|
158
|
-
"relation=call",
|
|
159
|
-
"depth=3",
|
|
160
|
-
"include_tests=true",
|
|
161
|
-
],
|
|
162
|
-
},
|
|
163
|
-
budgets: { bytes: null, tokens: null, items: 100 },
|
|
164
|
-
reason: "Both sides use the same target, outbound direction, call relation, depth, and test scope.",
|
|
165
|
-
oracleId: "create-engine-callees",
|
|
166
|
-
},
|
|
167
|
-
{
|
|
168
|
-
idPattern: "^trace-both-calls-r0-t1(?:-cold)?$",
|
|
169
|
-
useCase: "typed call traversal",
|
|
170
|
-
mode: "warm",
|
|
171
|
-
scope: {
|
|
172
|
-
competitorOperation: "trace_path",
|
|
173
|
-
knodinOperation: "query:traverse",
|
|
174
|
-
dimensions: [
|
|
175
|
-
"target=createEngine",
|
|
176
|
-
"direction",
|
|
177
|
-
"relation=call",
|
|
178
|
-
"depth=3",
|
|
179
|
-
"include_tests=true",
|
|
180
|
-
],
|
|
181
|
-
},
|
|
182
|
-
budgets: { bytes: null, tokens: null, items: 100 },
|
|
183
|
-
reason: "Both sides use the same target, bidirectional scope, call relation, depth, and test scope.",
|
|
184
|
-
oracleId: "create-engine-both",
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
idPattern: "^architecture-(?:languages|packages|entry_points|hotspots|boundaries|layers)(?:-cold)?$",
|
|
188
|
-
useCase: "single architecture facet",
|
|
189
|
-
mode: "warm",
|
|
190
|
-
scope: {
|
|
191
|
-
competitorOperation: "get_architecture",
|
|
192
|
-
knodinOperation: "query:architecture_overview",
|
|
193
|
-
dimensions: ["one named facet", "repository scope", "source inclusion=metadata"],
|
|
194
|
-
},
|
|
195
|
-
budgets: { bytes: null, tokens: null, items: null },
|
|
196
|
-
reason: "Each row requests one architecture facet that knodin supports independently.",
|
|
197
|
-
oracleId: "engine-package",
|
|
198
|
-
},
|
|
199
|
-
],
|
|
200
|
-
},
|
|
201
|
-
{
|
|
202
|
-
id: "grepai",
|
|
203
|
-
name: "grepai",
|
|
204
|
-
version: "0.35.0",
|
|
205
|
-
roadmap: ["C3", "C11", "C12", "C16", "C17", "C24", "C41"],
|
|
206
|
-
baseline: "grepai-vs-knodin.raw.json",
|
|
207
|
-
requirements: [
|
|
208
|
-
{ type: "command", value: "grepai" },
|
|
209
|
-
{ type: "command", value: "bun" },
|
|
210
|
-
],
|
|
211
|
-
versionCommand: ["grepai", "version"],
|
|
212
|
-
prepare: [
|
|
213
|
-
["grepai", "init", "--provider", "ollama", "--backend", "gob", "--yes"],
|
|
214
|
-
["node", "--import", "tsx", "scripts/wait-grepai-ready.ts"],
|
|
215
|
-
],
|
|
216
|
-
command: bunHarness("grepai-bakeoff.ts"),
|
|
217
|
-
caseMappings: [
|
|
218
|
-
{
|
|
219
|
-
idPattern: "^status-json-v0(?:-cold)?$",
|
|
220
|
-
useCase: "cached index status",
|
|
221
|
-
mode: "warm",
|
|
222
|
-
scope: {
|
|
223
|
-
competitorOperation: "grepai_index_status",
|
|
224
|
-
knodinOperation: "status:cached",
|
|
225
|
-
dimensions: ["cached summary", "repository scope", "non-verbose"],
|
|
226
|
-
},
|
|
227
|
-
budgets: { bytes: null, tokens: null, items: null },
|
|
228
|
-
reason: "Both sides return a cached, non-deep index status summary.",
|
|
229
|
-
oracleId: "indexed-status",
|
|
230
|
-
},
|
|
231
|
-
{
|
|
232
|
-
idPattern: "^status-json-v1(?:-cold)?$",
|
|
233
|
-
useCase: "verified index lifecycle audit",
|
|
234
|
-
mode: "warm",
|
|
235
|
-
scope: {
|
|
236
|
-
competitorOperation: "grepai_index_status:verbose",
|
|
237
|
-
knodinOperation: "status:deep",
|
|
238
|
-
dimensions: ["verified deep audit", "repository scope", "verbose"],
|
|
239
|
-
},
|
|
240
|
-
budgets: { bytes: null, tokens: null, items: null },
|
|
241
|
-
reason: "Both sides verify repository index state rather than returning cached summaries.",
|
|
242
|
-
oracleId: "indexed-status",
|
|
243
|
-
},
|
|
244
|
-
{
|
|
245
|
-
idPattern: "^search-json-c0-l5-all(?:-cold)?$",
|
|
246
|
-
useCase: "bounded semantic search",
|
|
247
|
-
mode: "warm",
|
|
248
|
-
scope: {
|
|
249
|
-
competitorOperation: "grepai_search",
|
|
250
|
-
knodinOperation: "search",
|
|
251
|
-
dimensions: ["query=index freshness reconciliation", "repository scope", "items"],
|
|
252
|
-
},
|
|
253
|
-
budgets: { bytes: null, tokens: null, items: 5 },
|
|
254
|
-
reason: "Both sides use the same semantic query, repository scope, and row limit.",
|
|
255
|
-
oracleId: "freshness-search",
|
|
256
|
-
},
|
|
257
|
-
{
|
|
258
|
-
idPattern: "^grepai_trace_callers-json-c0(?:-cold)?$",
|
|
259
|
-
useCase: "direct call neighbors",
|
|
260
|
-
mode: "warm",
|
|
261
|
-
scope: {
|
|
262
|
-
competitorOperation: "grepai_trace_callers",
|
|
263
|
-
knodinOperation: "query:callers_of",
|
|
264
|
-
dimensions: ["target=createEngine", "direction=callers", "depth=1", "relation=call"],
|
|
265
|
-
},
|
|
266
|
-
budgets: { bytes: null, tokens: null, items: null },
|
|
267
|
-
reason: "Both sides return the same direct call-neighbor direction for createEngine.",
|
|
268
|
-
oracleId: "create-engine-callers",
|
|
269
|
-
},
|
|
270
|
-
{
|
|
271
|
-
idPattern: "^grepai_trace_callees-json-c0(?:-cold)?$",
|
|
272
|
-
useCase: "direct call neighbors",
|
|
273
|
-
mode: "warm",
|
|
274
|
-
scope: {
|
|
275
|
-
competitorOperation: "grepai_trace_callees",
|
|
276
|
-
knodinOperation: "query:callees_of",
|
|
277
|
-
dimensions: ["target=createEngine", "direction=callees", "depth=1", "relation=call"],
|
|
278
|
-
},
|
|
279
|
-
budgets: { bytes: null, tokens: null, items: null },
|
|
280
|
-
reason: "Both sides return direct callees of createEngine.",
|
|
281
|
-
oracleId: "create-engine-callees",
|
|
282
|
-
},
|
|
283
|
-
],
|
|
284
|
-
},
|
|
285
|
-
{
|
|
286
|
-
id: "repomix",
|
|
287
|
-
name: "Repomix",
|
|
288
|
-
version: "1.17.0",
|
|
289
|
-
roadmap: ["C3", "C14", "C24", "C41"],
|
|
290
|
-
baseline: "repomix-vs-knodin.raw.json",
|
|
291
|
-
requirements: [
|
|
292
|
-
{ type: "command", value: "repomix" },
|
|
293
|
-
{ type: "command", value: "bun" },
|
|
294
|
-
],
|
|
295
|
-
versionCommand: ["repomix", "--version"],
|
|
296
|
-
command: ({ output, fixture }) => ["bun", "scripts/repomix-bakeoff.ts", fixture, output],
|
|
297
|
-
caseMappings: [
|
|
298
|
-
{
|
|
299
|
-
idPattern: "^pack-(?:xml|markdown|json)-c0(?:-cold)?$",
|
|
300
|
-
useCase: "two-file context pack",
|
|
301
|
-
mode: "warm",
|
|
302
|
-
scope: {
|
|
303
|
-
competitorOperation: "pack_codebase",
|
|
304
|
-
knodinOperation: "pack:export",
|
|
305
|
-
dimensions: ["format", "two includes", "test exclusion", "compression=false"],
|
|
306
|
-
},
|
|
307
|
-
budgets: { bytes: null, tokens: null, items: 2 },
|
|
308
|
-
reason: "Both sides pack the same two full files in the same supported format without compression.",
|
|
309
|
-
oracleId: "pack-two-files",
|
|
310
|
-
},
|
|
311
|
-
{
|
|
312
|
-
idPattern: "^read-(?:xml|markdown|json)-c0-(?:all|head|middle)$",
|
|
313
|
-
useCase: "bounded packed artifact read",
|
|
314
|
-
mode: "warm",
|
|
315
|
-
scope: {
|
|
316
|
-
competitorOperation: "read_repomix_output",
|
|
317
|
-
knodinOperation: "pack:read",
|
|
318
|
-
dimensions: ["same saved artifact", "same inclusive line range"],
|
|
319
|
-
},
|
|
320
|
-
budgets: { bytes: null, tokens: null, items: null },
|
|
321
|
-
reason: "Both sides read the same inclusive range from their immediately preceding pack.",
|
|
322
|
-
oracleId: "packed-read",
|
|
323
|
-
},
|
|
324
|
-
{
|
|
325
|
-
idPattern: "^grep-(?:xml|markdown|json)-c0-i(?:0|1)-x0$",
|
|
326
|
-
useCase: "exact packed artifact grep",
|
|
327
|
-
mode: "warm",
|
|
328
|
-
scope: {
|
|
329
|
-
competitorOperation: "grep_repomix_output",
|
|
330
|
-
knodinOperation: "pack:grep",
|
|
331
|
-
dimensions: ["same saved artifact", "same regex", "same case mode", "context=0"],
|
|
332
|
-
},
|
|
333
|
-
budgets: { bytes: null, tokens: null, items: null },
|
|
334
|
-
reason: "Both sides grep their equivalent packs with the same expression and no context lines.",
|
|
335
|
-
oracleId: "grep-create-engine",
|
|
336
|
-
},
|
|
337
|
-
],
|
|
338
|
-
},
|
|
339
|
-
{
|
|
340
|
-
id: "aider",
|
|
341
|
-
name: "Aider repo-map",
|
|
342
|
-
version: "0.86.2",
|
|
343
|
-
roadmap: ["C3", "C14", "C24"],
|
|
344
|
-
baseline: "aider-vs-knodin.raw.json",
|
|
345
|
-
requirements: [
|
|
346
|
-
{ type: "command", value: "aider" },
|
|
347
|
-
{ type: "command", value: "bun" },
|
|
348
|
-
],
|
|
349
|
-
versionCommand: ["aider", "--version"],
|
|
350
|
-
command: bunHarness("aider-repomap-bakeoff.ts"),
|
|
351
|
-
},
|
|
352
|
-
{
|
|
353
|
-
id: "code2prompt",
|
|
354
|
-
name: "code2prompt",
|
|
355
|
-
version: "4.2.0",
|
|
356
|
-
roadmap: ["C3", "C5", "C14", "C24", "C41"],
|
|
357
|
-
baseline: "code2prompt-vs-knodin.raw.json",
|
|
358
|
-
requirements: [
|
|
359
|
-
{ type: "command", value: "code2prompt" },
|
|
360
|
-
{ type: "command", value: "bun" },
|
|
361
|
-
],
|
|
362
|
-
versionCommand: ["code2prompt", "--version"],
|
|
363
|
-
command: bunHarness("code2prompt-bakeoff.ts"),
|
|
364
|
-
caseMappings: [
|
|
365
|
-
{
|
|
366
|
-
idPattern: "^format-(?:markdown|json|xml)-l(?:0|1)-t0-a0-c1(?:-cold)?$",
|
|
367
|
-
useCase: "two-file context pack",
|
|
368
|
-
mode: "warm",
|
|
369
|
-
scope: {
|
|
370
|
-
competitorOperation: "code2prompt",
|
|
371
|
-
knodinOperation: "pack:export",
|
|
372
|
-
dimensions: [
|
|
373
|
-
"format",
|
|
374
|
-
"line numbers",
|
|
375
|
-
"directory tree=false",
|
|
376
|
-
"relative paths",
|
|
377
|
-
"two includes",
|
|
378
|
-
],
|
|
379
|
-
},
|
|
380
|
-
budgets: { bytes: null, tokens: null, items: 2 },
|
|
381
|
-
reason: "Both sides pack the same two files with matching format, line, tree, and path settings.",
|
|
382
|
-
oracleId: "pack-two-files",
|
|
383
|
-
},
|
|
384
|
-
],
|
|
385
|
-
},
|
|
386
|
-
{
|
|
387
|
-
id: "claude-context",
|
|
388
|
-
name: "claude-context-mcp",
|
|
389
|
-
version: "0.1.15",
|
|
390
|
-
roadmap: ["C11", "C12", "C16", "C24"],
|
|
391
|
-
baseline: "claude-context-vs-knodin.raw.json",
|
|
392
|
-
requirements: [
|
|
393
|
-
{ type: "command", value: "claude-context-mcp" },
|
|
394
|
-
{ type: "command", value: "bun" },
|
|
395
|
-
{ type: "tcp", host: "127.0.0.1", port: 11434, label: "Ollama" },
|
|
396
|
-
{ type: "tcp", host: "127.0.0.1", port: 19530, label: "Milvus" },
|
|
397
|
-
],
|
|
398
|
-
versionCommand: ["bun", "pm", "ls", "-g"],
|
|
399
|
-
command: ({ output, fixture }) => ["bun", "scripts/claude-context-bakeoff.ts", fixture, output],
|
|
400
|
-
},
|
|
401
|
-
{
|
|
402
|
-
id: "mcp-codebase-index",
|
|
403
|
-
name: "mcp-codebase-index",
|
|
404
|
-
version: "1.6.0",
|
|
405
|
-
roadmap: ["C16", "C24"],
|
|
406
|
-
baseline: "mcp-codebase-index-blocker.raw.json",
|
|
407
|
-
requirements: [{ type: "command", value: "mcp-codebase-index" }],
|
|
408
|
-
versionCommand: ["bun", "pm", "ls", "-g"],
|
|
409
|
-
blocker: "Mandatory hosted Gemini embeddings violate the local-only protocol.",
|
|
410
|
-
},
|
|
411
|
-
];
|