knodin 0.8.2 → 0.8.3
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 +29 -12
- package/dist/bin/cli.js +20 -3
- package/dist/src/docs-sections.js +1 -0
- package/dist/src/engine/index.js +911 -55
- package/dist/src/init-progress-worker.js +4 -40
- package/dist/src/progress-worker-runtime.js +46 -0
- package/dist/src/repair-progress-worker.js +3 -40
- package/dist/src/resource-reachability.js +456 -0
- package/dist/src/response-budget.js +69 -65
- package/dist/src/tools/knodin-tools.js +12 -7
- package/docs/BEHAVIORAL-CONTRACT.md +47 -5
- package/docs/CLI.md +10 -0
- package/docs/COMPARISON.md +10 -0
- package/docs/DEMO.md +49 -0
- package/docs/MCP.md +5 -0
- package/docs/releases/0.8.3.md +47 -0
- package/package.json +13 -1
- package/roadmap/competitive-roadmap.md +95 -0
|
@@ -48,6 +48,71 @@ const PROTECTED_CONTRACT_KEYS = new Set([
|
|
|
48
48
|
function isTruncatableDetail(entry) {
|
|
49
49
|
return typeof entry.key !== "string" || !PROTECTED_CONTRACT_KEYS.has(entry.key);
|
|
50
50
|
}
|
|
51
|
+
function synchronizeNestedCapabilityBudget(root, metadata, operation) {
|
|
52
|
+
const cross = root.crossSubstratePath;
|
|
53
|
+
if (!cross)
|
|
54
|
+
return;
|
|
55
|
+
if (metadata.truncated) {
|
|
56
|
+
cross.truncated = true;
|
|
57
|
+
cross.continuation = `Repeat ${operation} with a larger byte/token budget to recover complete source evidence.`;
|
|
58
|
+
const omission = "Flow or Apex source evidence was shortened by the response budget.";
|
|
59
|
+
cross.omissions ??= [];
|
|
60
|
+
if (!cross.omissions.includes(omission))
|
|
61
|
+
cross.omissions.push(omission);
|
|
62
|
+
}
|
|
63
|
+
const measuredBudget = {
|
|
64
|
+
byteLimit: metadata.byteLimit,
|
|
65
|
+
tokenLimit: metadata.tokenLimit,
|
|
66
|
+
itemLimit: metadata.itemLimit,
|
|
67
|
+
serializedBytes: 0,
|
|
68
|
+
estimatedTokens: 0,
|
|
69
|
+
};
|
|
70
|
+
cross.budget = cross.budget ? { ...cross.budget, ...measuredBudget } : measuredBudget;
|
|
71
|
+
for (let iteration = 0; iteration < 4; iteration++) {
|
|
72
|
+
const serializedBytes = bytes(cross);
|
|
73
|
+
const estimatedTokens = Math.ceil(serializedBytes / 4);
|
|
74
|
+
if (cross.budget.serializedBytes === serializedBytes &&
|
|
75
|
+
cross.budget.estimatedTokens === estimatedTokens)
|
|
76
|
+
break;
|
|
77
|
+
cross.budget.serializedBytes = serializedBytes;
|
|
78
|
+
cross.budget.estimatedTokens = estimatedTokens;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function truncatePayloadToBytes(root, byteLimit) {
|
|
82
|
+
let truncated = false;
|
|
83
|
+
while (bytes(root) > byteLimit) {
|
|
84
|
+
const candidate = collectStrings(root)
|
|
85
|
+
.filter((entry) => !entry.path.startsWith("$/responseBudget") &&
|
|
86
|
+
entry.value.length > 0 &&
|
|
87
|
+
isTruncatableDetail(entry))
|
|
88
|
+
.sort((a, b) => b.value.length - a.value.length)[0];
|
|
89
|
+
if (!candidate)
|
|
90
|
+
break;
|
|
91
|
+
const marker = "\n… [truncated]";
|
|
92
|
+
if (candidate.value.length <= marker.length + 1) {
|
|
93
|
+
if (Array.isArray(candidate.parent))
|
|
94
|
+
candidate.parent.splice(candidate.key, 1);
|
|
95
|
+
else
|
|
96
|
+
delete candidate.parent[candidate.key];
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
const keep = Math.max(0, Math.floor((candidate.value.length - marker.length) / 2));
|
|
100
|
+
candidate.parent[candidate.key] =
|
|
101
|
+
`${candidate.value.slice(0, keep)}${marker}`;
|
|
102
|
+
}
|
|
103
|
+
truncated = true;
|
|
104
|
+
}
|
|
105
|
+
while (bytes(root) > byteLimit) {
|
|
106
|
+
const candidate = collectArrays(root)
|
|
107
|
+
.filter((entry) => !entry.path.startsWith("$/responseBudget") && entry.value.length > 0)
|
|
108
|
+
.sort((a, b) => bytes(b.value) - bytes(a.value))[0];
|
|
109
|
+
if (!candidate)
|
|
110
|
+
break;
|
|
111
|
+
candidate.value.pop();
|
|
112
|
+
truncated = true;
|
|
113
|
+
}
|
|
114
|
+
return truncated;
|
|
115
|
+
}
|
|
51
116
|
/**
|
|
52
117
|
* Applies limits to the value that is actually JSON-serialized. Token accounting
|
|
53
118
|
* intentionally uses the deterministic local estimate of four UTF-8 bytes/token;
|
|
@@ -98,38 +163,7 @@ export function applyResponseBudget(value, operation, request, defaults) {
|
|
|
98
163
|
root.responseBudget = metadata;
|
|
99
164
|
// Preserve collection contracts and identifiers where possible: large source,
|
|
100
165
|
// artifact and diagnostic strings are the first expendable detail.
|
|
101
|
-
|
|
102
|
-
const candidate = collectStrings(root)
|
|
103
|
-
.filter((entry) => !entry.path.startsWith("$/responseBudget") &&
|
|
104
|
-
entry.value.length > 0 &&
|
|
105
|
-
isTruncatableDetail(entry))
|
|
106
|
-
.sort((a, b) => b.value.length - a.value.length)[0];
|
|
107
|
-
if (!candidate)
|
|
108
|
-
break;
|
|
109
|
-
const marker = "\n… [truncated]";
|
|
110
|
-
if (candidate.value.length <= marker.length + 1) {
|
|
111
|
-
if (Array.isArray(candidate.parent))
|
|
112
|
-
candidate.parent.splice(candidate.key, 1);
|
|
113
|
-
else
|
|
114
|
-
delete candidate.parent[candidate.key];
|
|
115
|
-
truncated = true;
|
|
116
|
-
continue;
|
|
117
|
-
}
|
|
118
|
-
const keep = Math.max(0, Math.floor((candidate.value.length - marker.length) / 2));
|
|
119
|
-
candidate.parent[candidate.key] =
|
|
120
|
-
`${candidate.value.slice(0, keep)}${marker}`;
|
|
121
|
-
truncated = true;
|
|
122
|
-
}
|
|
123
|
-
// Only drop tail items after scalar detail has been exhausted.
|
|
124
|
-
while (bytes(root) > byteLimit) {
|
|
125
|
-
const candidate = collectArrays(root)
|
|
126
|
-
.filter((entry) => !entry.path.startsWith("$/responseBudget") && entry.value.length > 0)
|
|
127
|
-
.sort((a, b) => bytes(b.value) - bytes(a.value))[0];
|
|
128
|
-
if (!candidate)
|
|
129
|
-
break;
|
|
130
|
-
candidate.value.pop();
|
|
131
|
-
truncated = true;
|
|
132
|
-
}
|
|
166
|
+
truncated = truncatePayloadToBytes(root, byteLimit) || truncated;
|
|
133
167
|
metadata.truncated = truncated;
|
|
134
168
|
if (truncated) {
|
|
135
169
|
metadata.continuation = {
|
|
@@ -138,6 +172,7 @@ export function applyResponseBudget(value, operation, request, defaults) {
|
|
|
138
172
|
instruction: `Repeat ${operation} with a narrower selector, larger budget, or query drill-down.`,
|
|
139
173
|
};
|
|
140
174
|
}
|
|
175
|
+
synchronizeNestedCapabilityBudget(root, metadata, operation);
|
|
141
176
|
// Metadata changes the byte count, so converge after setting it. The reserve
|
|
142
177
|
// above is normally enough; this final pass handles unusually long paths.
|
|
143
178
|
metadata.serializedBytes = bytes(root);
|
|
@@ -147,42 +182,11 @@ export function applyResponseBudget(value, operation, request, defaults) {
|
|
|
147
182
|
metadata.serializedBytes = bytes(root);
|
|
148
183
|
metadata.estimatedTokens = Math.ceil(metadata.serializedBytes / 4);
|
|
149
184
|
}
|
|
150
|
-
|
|
151
|
-
const candidate = collectStrings(root)
|
|
152
|
-
.filter((entry) => !entry.path.startsWith("$/responseBudget") &&
|
|
153
|
-
entry.value.length > 0 &&
|
|
154
|
-
isTruncatableDetail(entry))
|
|
155
|
-
.sort((a, b) => b.value.length - a.value.length)[0];
|
|
156
|
-
if (!candidate)
|
|
157
|
-
break;
|
|
158
|
-
const marker = "\n… [truncated]";
|
|
159
|
-
if (candidate.value.length <= marker.length + 1) {
|
|
160
|
-
if (Array.isArray(candidate.parent))
|
|
161
|
-
candidate.parent.splice(candidate.key, 1);
|
|
162
|
-
else
|
|
163
|
-
delete candidate.parent[candidate.key];
|
|
164
|
-
}
|
|
165
|
-
else {
|
|
166
|
-
const keep = Math.max(0, Math.floor((candidate.value.length - marker.length) / 2));
|
|
167
|
-
candidate.parent[candidate.key] =
|
|
168
|
-
`${candidate.value.slice(0, keep)}${marker}`;
|
|
169
|
-
}
|
|
170
|
-
metadata.truncated = true;
|
|
171
|
-
}
|
|
185
|
+
metadata.truncated = truncatePayloadToBytes(root, byteLimit) || metadata.truncated;
|
|
172
186
|
metadata.serializedBytes = bytes(root);
|
|
173
187
|
metadata.estimatedTokens = Math.ceil(metadata.serializedBytes / 4);
|
|
174
|
-
while (bytes(root) > byteLimit) {
|
|
175
|
-
const candidate = collectArrays(root)
|
|
176
|
-
.filter((entry) => !entry.path.startsWith("$/responseBudget") && entry.value.length > 0)
|
|
177
|
-
.sort((a, b) => bytes(b.value) - bytes(a.value))[0];
|
|
178
|
-
if (!candidate)
|
|
179
|
-
break;
|
|
180
|
-
candidate.value.pop();
|
|
181
|
-
metadata.truncated = true;
|
|
182
|
-
metadata.serializedBytes = bytes(root);
|
|
183
|
-
metadata.estimatedTokens = Math.ceil(metadata.serializedBytes / 4);
|
|
184
|
-
}
|
|
185
188
|
for (let iteration = 0; iteration < 8; iteration++) {
|
|
189
|
+
synchronizeNestedCapabilityBudget(root, metadata, operation);
|
|
186
190
|
const actual = bytes(root);
|
|
187
191
|
const tokens = Math.ceil(actual / 4);
|
|
188
192
|
if (metadata.serializedBytes === actual && metadata.estimatedTokens === tokens)
|
|
@@ -116,6 +116,7 @@ const QUERY_PATTERNS = [
|
|
|
116
116
|
"batch_outline",
|
|
117
117
|
"project_overview",
|
|
118
118
|
"shortest_path",
|
|
119
|
+
"cross_substrate_path",
|
|
119
120
|
"impact",
|
|
120
121
|
"dead_code",
|
|
121
122
|
"large_functions",
|
|
@@ -127,6 +128,7 @@ const QUERY_PATTERNS = [
|
|
|
127
128
|
"traverse",
|
|
128
129
|
"feature_path",
|
|
129
130
|
"flow_analysis",
|
|
131
|
+
"resource_reachability",
|
|
130
132
|
"knowledge_gaps",
|
|
131
133
|
"surprising_connections",
|
|
132
134
|
"suggested_questions",
|
|
@@ -227,15 +229,15 @@ function buildDocumentedKnodinTools() {
|
|
|
227
229
|
},
|
|
228
230
|
toIdentity: {
|
|
229
231
|
type: "string",
|
|
230
|
-
description: "shortest_path destination identity selector.",
|
|
232
|
+
description: "shortest_path/cross_substrate_path destination identity selector.",
|
|
231
233
|
},
|
|
232
234
|
toFile: {
|
|
233
235
|
type: "string",
|
|
234
|
-
description: "shortest_path destination file selector.",
|
|
236
|
+
description: "shortest_path/cross_substrate_path destination file selector.",
|
|
235
237
|
},
|
|
236
238
|
toKind: {
|
|
237
239
|
type: "string",
|
|
238
|
-
description: "shortest_path destination kind selector.",
|
|
240
|
+
description: "shortest_path/cross_substrate_path destination kind selector.",
|
|
239
241
|
},
|
|
240
242
|
pattern: {
|
|
241
243
|
type: "string",
|
|
@@ -243,7 +245,7 @@ function buildDocumentedKnodinTools() {
|
|
|
243
245
|
description: "feature_path — deterministic downstream DFS over resolved source references. It is bounded by depth and item limits, source-evidenced per hop, cycle-guarded, and never claims runtime execution; dynamic dispatch and unresolved calls are omitted. " +
|
|
244
246
|
"lsp_diagnostics accepts a repo-relative TypeScript/JavaScript file; lsp_definitions, lsp_declarations, and lsp_implementations accept file:line:column. These use an optional local TypeScript language-service adapter, never start a daemon or write files, and return an explicit unavailable result when no local adapter supports the file type. " +
|
|
245
247
|
"api_contract_mismatches — bounded, source-evidenced static mismatch findings for literal Express/Fastify routes and literal fetch/Axios clients. Matching requires method and normalized path, and requires exact origin equality when a client uses an absolute origin; dynamic routes remain explicitly unresolved. mcp_tools — list indexed TypeScript MCP SDK tool registrations, or pass symbol to look up one exact tool name; returns description/schema/handler/file and exact versus heuristic confidence. import_cycles — repo-wide canonical directed file-import cycles; no symbol required, type-only imports included, non-import lineage/ORM edges excluded, and limit/truncated bounds output. " +
|
|
246
|
-
"query: the graph pattern to run (callers_of, callees_of, imports_of, importers_of, inheritors_of, structural_implementations_of, tests_for, file_summary, shortest_path, impact, dead_code, large_functions, large_files, rename_preview, flows, flow_of, stats, traverse, knowledge_gaps, community, federated_repos). structural_implementations_of returns TypeScript structurally typed object implementations separately from nominal extends/implements results. federated_repos — discover and list all registered/configured repository paths that this engine federates queries across. community — fetch a single community's full detail (name, size, cohesion, files, and symbols) by name or substring filter; empty `symbol` = all communities. large_files — whole-file line counts (min 200), sorted descending — the file-level counterpart to large_functions, for spotting god files rather than god functions; same optional path-substring filter, empty `symbol` = all files. stats — repo-level index size + health in one call (per-repo symbol/reference/dependency/embedding/file counts, per-kind and per-language breakdowns, orphaned-embedding count, schema version, last-indexed HEAD, and cached community/hub/bridge/flow totals); federated, empty `symbol`. traverse — typed BFS from `symbol` within `depth` hops (default 3, 1–6), selectable upstream/downstream/both and explicit edge kinds; every discovered edge includes direction, kind, provenance, confidence, files, and source line, with optional Tree-sitter-grounded argument expressions honestly marked heuristic. Sets `truncated` when the `limit` cap binds; single-repo. knowledge_gaps — repo-health weaknesses in one call: thin communities (<3 symbols), single-file communities, isolated (zero-degree) symbols, and untested hub/bridge hotspots; sourced from the cached map(), federated, empty `symbol`, one row carrying a `knowledgeGaps` block. surprising_connections — resolved edges scored by a composite surprise formula (cross-community, cross-language, peripheral-to-hub, cross-test-boundary, unusual edge kind) to surface unexpected coupling; sorted highest-first, top 15 by default, federated, empty `symbol`, each row carrying a `surprise` block. suggested_questions — prioritized, human-readable review prompts synthesized from knowledge_gaps + surprising_connections (untested hotspots first, then surprising edges, then thin/single-file communities); federated, empty `symbol`, each row a `question` string citing the real symbol/file, top 10 by default. architecture_overview — a federated architecture view with scoped community coupling and independently selectable packages, layers, boundaries, hotspots, entry points, and language facets; `path` is segment-safe and applies consistently.
|
|
248
|
+
"query: the graph pattern to run (callers_of, callees_of, imports_of, importers_of, inheritors_of, structural_implementations_of, tests_for, file_summary, shortest_path, cross_substrate_path, impact, dead_code, large_functions, large_files, rename_preview, flows, flow_of, flow_analysis, resource_reachability, stats, traverse, knowledge_gaps, community, federated_repos). cross_substrate_path proves only one static Salesforce Flow action to one uniquely resolved Apex @InvocableMethod and returns exact endpoint identities/evidence, freshness, budgets, and explicit unsupported crossings; it does not resolve Terraform, dbt, or arbitrary substrate paths. resource_reachability is a repo-wide, bounded, cached, on-demand TS/JS static heuristic for literal process.env/fs.readFileSync sources reaching console.log/fetch/db.query sinks; it reports evidence, coverage, omissions, freshness, truncation, and continuation and is never runtime reachability or exploitability proof. structural_implementations_of returns TypeScript structurally typed object implementations separately from nominal extends/implements results. federated_repos — discover and list all registered/configured repository paths that this engine federates queries across. community — fetch a single community's full detail (name, size, cohesion, files, and symbols) by name or substring filter; empty `symbol` = all communities. large_files — whole-file line counts (min 200), sorted descending — the file-level counterpart to large_functions, for spotting god files rather than god functions; same optional path-substring filter, empty `symbol` = all files. stats — repo-level index size + health in one call (per-repo symbol/reference/dependency/embedding/file counts, per-kind and per-language breakdowns, orphaned-embedding count, schema version, last-indexed HEAD, and cached community/hub/bridge/flow totals); federated, empty `symbol`. traverse — typed BFS from `symbol` within `depth` hops (default 3, 1–6), selectable upstream/downstream/both and explicit edge kinds; every discovered edge includes direction, kind, provenance, confidence, files, and source line, with optional Tree-sitter-grounded argument expressions honestly marked heuristic. Sets `truncated` when the `limit` cap binds; single-repo. knowledge_gaps — repo-health weaknesses in one call: thin communities (<3 symbols), single-file communities, isolated (zero-degree) symbols, and untested hub/bridge hotspots; sourced from the cached map(), federated, empty `symbol`, one row carrying a `knowledgeGaps` block. surprising_connections — resolved edges scored by a composite surprise formula (cross-community, cross-language, peripheral-to-hub, cross-test-boundary, unusual edge kind) to surface unexpected coupling; sorted highest-first, top 15 by default, federated, empty `symbol`, each row carrying a `surprise` block. suggested_questions — prioritized, human-readable review prompts synthesized from knowledge_gaps + surprising_connections (untested hotspots first, then surprising edges, then thin/single-file communities); federated, empty `symbol`, each row a `question` string citing the real symbol/file, top 10 by default. architecture_overview — a federated architecture view with scoped community coupling and independently selectable packages, layers, boundaries, hotspots, entry points, and language facets; `path` is segment-safe and applies consistently. Spring/event patterns (Java): triggers_of — the schedule edge between a @Scheduled method and its synthetic scheduler (pass the method to get its scheduler, or the scheduler to list scheduled methods). publishers_of — methods that publish a given event type (ApplicationEventPublisher.publishEvent). listeners_of — @EventListener methods that listen for a given event type. handlers_of — methods that handle a given HTTP endpoint path (Spring @*Mapping + the existing JS/Python endpoints). endpoints_for — the inverse: endpoint path(s) a given method handles. consumers_of — classes/methods consuming a given @Value config property. children_of — symbols contained in a file path (same as file_summary) or, for a class name, its member symbols by line-range containment. All seven require `symbol` (the target); single-repo, not federated.",
|
|
247
249
|
},
|
|
248
250
|
depth: {
|
|
249
251
|
type: "number",
|
|
@@ -292,7 +294,7 @@ function buildDocumentedKnodinTools() {
|
|
|
292
294
|
},
|
|
293
295
|
to: {
|
|
294
296
|
type: "string",
|
|
295
|
-
description: "query shortest_path: destination symbol (start symbol goes in `symbol`). query rename_preview: the new name (old name goes in `symbol`). Read-only by default (returns edit sites + a unified diff); pass `apply: true` to write the rename to disk.",
|
|
297
|
+
description: "query shortest_path/cross_substrate_path: destination symbol (start symbol goes in `symbol`). query rename_preview: the new name (old name goes in `symbol`). Read-only by default (returns edit sites + a unified diff); pass `apply: true` to write the rename to disk.",
|
|
296
298
|
},
|
|
297
299
|
apply: {
|
|
298
300
|
type: "boolean",
|
|
@@ -1569,8 +1571,8 @@ async function dispatchKnodinTool(args) {
|
|
|
1569
1571
|
const repoWide = REPO_WIDE_QUERY_PATTERNS.includes(pattern);
|
|
1570
1572
|
if (!symbol && !repoWide)
|
|
1571
1573
|
throw new Error(`knodin query ${pattern} requires \`symbol\``);
|
|
1572
|
-
if (pattern === "shortest_path" && !to)
|
|
1573
|
-
throw new Error(
|
|
1574
|
+
if ((pattern === "shortest_path" || pattern === "cross_substrate_path") && !to)
|
|
1575
|
+
throw new Error(`knodin query ${pattern} requires \`to\``);
|
|
1574
1576
|
if (pattern === "rename_preview" && !to)
|
|
1575
1577
|
throw new Error("knodin query rename_preview requires `symbol` and `to`");
|
|
1576
1578
|
const queryHealth = GRAPH_INDEPENDENT_QUERY_PATTERNS.has(pattern)
|
|
@@ -1602,6 +1604,9 @@ async function dispatchKnodinTool(args) {
|
|
|
1602
1604
|
direction: pattern === "traverse" ? direction : undefined,
|
|
1603
1605
|
includeDataFlow: pattern === "traverse" ? includeDataFlow : undefined,
|
|
1604
1606
|
flowVariable: pattern === "flow_analysis" ? flowVariable : undefined,
|
|
1607
|
+
resourceOffset: pattern === "resource_reachability" ? offset : undefined,
|
|
1608
|
+
resourceMaxBytes: pattern === "resource_reachability" ? byteBudget : undefined,
|
|
1609
|
+
resourceMaxTokens: pattern === "resource_reachability" ? tokenBudget : undefined,
|
|
1605
1610
|
architectureFacets,
|
|
1606
1611
|
topN,
|
|
1607
1612
|
sort,
|
|
@@ -16,10 +16,11 @@ action-specific response semantics fail closed when a required signal is absent.
|
|
|
16
16
|
- **Value:** less manual context assembly and fewer missed dependencies. The
|
|
17
17
|
paired task method and its bounded results are checked in under
|
|
18
18
|
[`benchmarks/evaluations/c93-engineering-outcomes/`](../benchmarks/evaluations/c93-engineering-outcomes/).
|
|
19
|
-
- **ROI:** fewer corrective agent round trips without
|
|
20
|
-
authentication, or source-egress overhead. C93
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
- **ROI:** the intended mechanism is fewer corrective agent round trips without
|
|
20
|
+
hosted-service, account, authentication, or source-egress overhead. C93's
|
|
21
|
+
accepted two-task replay measured no round-trip benefit; both arms needed one
|
|
22
|
+
correction. It therefore authorizes no productivity claim and leaves billed
|
|
23
|
+
cost and unobserved token counts unavailable.
|
|
23
24
|
- **Tomorrow:** run `knodin init`, inspect `knodin status`, then use the existing
|
|
24
25
|
checkout through the CLI or the single `knodin.knodin` MCP gateway. The
|
|
25
26
|
installation and client readiness evidence remains bounded by C91 below.
|
|
@@ -35,6 +36,13 @@ preserving its stable identity and evidence provenance. Stale, unavailable, or
|
|
|
35
36
|
ambiguous graph evidence must remain explicit and cannot be promoted to a
|
|
36
37
|
confident failure diagnosis, impact claim, or runtime-causality proof.
|
|
37
38
|
|
|
39
|
+
`ExplainResult.callers[].kind` and `ExplainResult.omissions[]` are governed by
|
|
40
|
+
the existing explain mapping: relationship kinds require source provenance and
|
|
41
|
+
stable resolved endpoints, while omissions require an exact source location and
|
|
42
|
+
must never be promoted into a graph edge. C99 exercises these added fields
|
|
43
|
+
without adding a gateway operation or discriminator, so the C95 applicability
|
|
44
|
+
matrix is unchanged.
|
|
45
|
+
|
|
38
46
|
The C95 fixtures run in a linked non-default worktree. A child harness installs
|
|
39
47
|
guards before importing the production dispatcher and observes global `fetch`,
|
|
40
48
|
HTTP/HTTPS request and get, TCP/TLS connection, callback and promise DNS
|
|
@@ -46,6 +54,39 @@ credential forwarding, source bytes at network/subprocess boundaries, and
|
|
|
46
54
|
native-addon loads must remain zero. Local subprocess execution is counted and
|
|
47
55
|
permitted only when those observed payload checks remain clean.
|
|
48
56
|
|
|
57
|
+
## C101 composition closure
|
|
58
|
+
|
|
59
|
+
C101 composes four independently bounded decisions without adding an MCP tool
|
|
60
|
+
or operation:
|
|
61
|
+
|
|
62
|
+
- C97 retained lazy semantic residency in one local process. It does **not**
|
|
63
|
+
authorize an idle-RSS-reclamation claim.
|
|
64
|
+
- C98 reports literal TS/JS source-to-sink paths as static heuristics with
|
|
65
|
+
coverage, omissions, freshness, budgets, and continuation. Truncation cannot
|
|
66
|
+
become a complete-result claim.
|
|
67
|
+
- C99 persists only uniquely source-resolved Inversify/tsyringe relationships;
|
|
68
|
+
ambiguous, dynamic, factory, alias, conditional, and reflective wiring stays
|
|
69
|
+
omission evidence rather than an edge.
|
|
70
|
+
- C100 proves one Salesforce Flow action to one uniquely resolved Apex
|
|
71
|
+
`@InvocableMethod`. It does not prove Terraform, dbt, arbitrary Salesforce
|
|
72
|
+
metadata, or general cross-substrate traversal.
|
|
73
|
+
|
|
74
|
+
`npm run verify:c101` source-binds those decisions, checks the CLI and one-tool
|
|
75
|
+
MCP query declarations, and rejects eight adversarial mutations of actual
|
|
76
|
+
production responses. Stale resource/path evidence and heuristic-to-exact
|
|
77
|
+
promotion fail; a truncated result cannot be presented as complete; and a DI
|
|
78
|
+
ambiguity, missing source witness, or path omission cannot become a supported
|
|
79
|
+
edge.
|
|
80
|
+
|
|
81
|
+
## Repository stewardship
|
|
82
|
+
|
|
83
|
+
An authoritative pull request starts the full test matrix and Sonar analysis,
|
|
84
|
+
so it is a long, resource-intensive operation. Assistants must not automatically
|
|
85
|
+
open one PR per item. Dependency-compatible, coherently scoped commits should
|
|
86
|
+
normally be stacked into one reasonably sized shared PR; unrelated work must
|
|
87
|
+
not be bundled merely to make the PR larger. The user or approved batch decides
|
|
88
|
+
when that review unit is ready.
|
|
89
|
+
|
|
49
90
|
## Known bounds
|
|
50
91
|
|
|
51
92
|
This replay proves the checked operation/action fixtures, not all repositories,
|
|
@@ -53,7 +94,8 @@ languages, frameworks, dynamic runtime behavior, clients, or deployment
|
|
|
53
94
|
environments. Static relationships and failure correlations are candidates,
|
|
54
95
|
not runtime-causality proof. Budgets can truncate results; indexes can be stale
|
|
55
96
|
or unavailable; names can be ambiguous; generated code, dynamic dispatch,
|
|
56
|
-
framework wiring
|
|
97
|
+
framework wiring outside C99's declared Inversify/tsyringe patterns, and
|
|
98
|
+
language coverage can leave relationships unresolved.
|
|
57
99
|
|
|
58
100
|
C91 remains parked pending native client, runtime-manager, Homebrew, and
|
|
59
101
|
Artifactory certification evidence. C94 remains blocked on C91 and therefore
|
package/docs/CLI.md
CHANGED
|
@@ -32,6 +32,16 @@ example repository existence, mutually exclusive configuration modes, and
|
|
|
32
32
|
graph-query target rules), but syntax cannot reach a handler unless the shared
|
|
33
33
|
declarative model accepts it first.
|
|
34
34
|
|
|
35
|
+
`knodin query resource_reachability --limit 100` runs cached, on-demand static
|
|
36
|
+
TS/JS source-to-sink analysis. It covers literal `process.env` and
|
|
37
|
+
`fs.readFileSync` reads reaching `console.log`, `fetch`, or `db.query` through
|
|
38
|
+
bounded assignment, argument, and return handoff. Results include ordered source
|
|
39
|
+
evidence, stable path identities, registry coverage, omissions, freshness, and
|
|
40
|
+
hard truncation/continuation metadata. Depth is fixed at 6 and paths at 100;
|
|
41
|
+
dynamic names, reflection, computed aliases, and unsupported languages are
|
|
42
|
+
reported rather than guessed. This is a static heuristic, not runtime reachability
|
|
43
|
+
or an exploitability verdict.
|
|
44
|
+
|
|
35
45
|
For support evidence, `knodin diagnostics enable|status|preview|archive|inspect|clear|disable`
|
|
36
46
|
manages an explicit local failure journal and redacted gzip JSON bundles.
|
|
37
47
|
Collection does not upload data. See `docs/DIAGNOSTICS.md` for retention,
|
package/docs/COMPARISON.md
CHANGED
|
@@ -51,6 +51,16 @@ the evaluation's competitor limitations. The active
|
|
|
51
51
|
[competitive roadmap](../roadmap/competitive-roadmap.md) links each claim to
|
|
52
52
|
its acceptance criteria and replay state.
|
|
53
53
|
|
|
54
|
+
The current positioning lead is the checked behavioral contract, not the raw
|
|
55
|
+
capability count. C98 adds a bounded TS/JS resource-reachability heuristic; C99
|
|
56
|
+
adds only uniquely source-resolved Inversify/tsyringe relationships; C100 proves
|
|
57
|
+
one Salesforce Flow action to one Apex `@InvocableMethod`; and C97 retains the
|
|
58
|
+
one-process semantic design without claiming idle RSS reclamation. C101 binds
|
|
59
|
+
those decisions and rejects stale, truncated, ambiguous, or omission-only
|
|
60
|
+
results when promoted into complete or exact claims. None of these fixtures
|
|
61
|
+
supports general runtime causality, arbitrary cross-substrate paths, broad DI
|
|
62
|
+
framework coverage, or universal competitor superiority.
|
|
63
|
+
|
|
54
64
|
## The quartet: knodin vs its three direct progenitors
|
|
55
65
|
|
|
56
66
|
knodin exists to fuse three tools this project already used side by side
|
package/docs/DEMO.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Bounded product walkthrough
|
|
2
|
+
|
|
3
|
+
This is the maintained positioning walkthrough, not C94's pending certified
|
|
4
|
+
five-minute client demonstration. C94 remains parked behind native installation
|
|
5
|
+
and client evidence; this document must not be cited as completing it.
|
|
6
|
+
|
|
7
|
+
## Value
|
|
8
|
+
|
|
9
|
+
On an existing checkout, initialize and orient before assembling context by
|
|
10
|
+
hand:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
knodin init
|
|
14
|
+
knodin status --deep
|
|
15
|
+
knodin context "change the review submission path"
|
|
16
|
+
knodin query impact submit --direction upstream
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The intended value is less manual context assembly and fewer missed
|
|
20
|
+
dependencies. C100 demonstrates one narrow improvement: a Salesforce Flow
|
|
21
|
+
action can resolve to the exact local Apex `@InvocableMethod`, rather than only
|
|
22
|
+
its class file. It does not demonstrate arbitrary cross-substrate analysis.
|
|
23
|
+
|
|
24
|
+
## ROI
|
|
25
|
+
|
|
26
|
+
Use the same local CLI or one MCP gateway against the checkout already on disk;
|
|
27
|
+
no hosted index, account, authentication, or source-code egress is required.
|
|
28
|
+
Fewer corrective round trips are an intended mechanism, not a measured product
|
|
29
|
+
claim: C93's accepted two-task replay found no round-trip difference and both
|
|
30
|
+
arms required one correction.
|
|
31
|
+
|
|
32
|
+
## Tomorrow
|
|
33
|
+
|
|
34
|
+
After `knodin init`, use `context`, `explain`, structured `query`, and `review`
|
|
35
|
+
through the CLI or the single operation-routed MCP tool. If status reports stale
|
|
36
|
+
or damaged state, repair it before relying on graph evidence.
|
|
37
|
+
|
|
38
|
+
## Secret sauce and bounds
|
|
39
|
+
|
|
40
|
+
Stable identity, exact source evidence, explicit freshness, and truthful
|
|
41
|
+
budgets compose behind the compact local surface. C101 mutates actual production
|
|
42
|
+
responses for resource reachability, TypeScript DI, and one Flow-to-Apex path;
|
|
43
|
+
stale, truncated, ambiguous, or evidence-free variants must fail the contract
|
|
44
|
+
oracle. C97 separately retains one-process semantic residency and authorizes no
|
|
45
|
+
idle-RSS-reclamation claim.
|
|
46
|
+
|
|
47
|
+
These checked fixtures do not prove runtime causality, broad DI framework
|
|
48
|
+
coverage, arbitrary Salesforce/Terraform/dbt paths, every client or platform,
|
|
49
|
+
or superiority over competitors.
|
package/docs/MCP.md
CHANGED
|
@@ -4,6 +4,11 @@ knodin exposes exactly one MCP tool named `knodin`. Capabilities such as
|
|
|
4
4
|
context, explain, review, search, docs, doctor, repositories, and systems are
|
|
5
5
|
operations of that gateway, not separate top-level tools.
|
|
6
6
|
|
|
7
|
+
Use `operation: "query", pattern: "resource_reachability"` for the same bounded,
|
|
8
|
+
cached, repo-wide TS/JS analysis as the CLI. It requires no symbol and retains
|
|
9
|
+
the gateway's freshness refusal and response budgets; returned paths remain
|
|
10
|
+
source-evidenced static heuristics with explicit coverage and omissions.
|
|
11
|
+
|
|
7
12
|
Use `operation: "evidence"` for deterministic `locate`, `outline`, `evidence`,
|
|
8
13
|
and `expand` source delivery with a verified complete-file hash handshake and
|
|
9
14
|
recoverable hard-budget continuations. See `docs/PROGRESSIVE-EVIDENCE.md`.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# knodin 0.8.3
|
|
2
|
+
|
|
3
|
+
This release strengthens Knodin's source-evidenced graph across repository
|
|
4
|
+
lifecycle, cross-substrate analysis, and bounded organization-scale workflows.
|
|
5
|
+
|
|
6
|
+
- Adds bounded repository-wide resource reachability for source-proven
|
|
7
|
+
environment, file, fetch, console, and database paths. Results retain stable
|
|
8
|
+
identities, exact evidence, explicit unsupported cases, freshness, response
|
|
9
|
+
budgets, and deterministic continuation.
|
|
10
|
+
- Resolves source-proven TypeScript dependency-injection wiring for supported
|
|
11
|
+
Inversify and tsyringe forms. Framework and registry scoping, ambiguity,
|
|
12
|
+
conditional wiring, incremental refresh, and removal are represented without
|
|
13
|
+
guessing across containers or frameworks.
|
|
14
|
+
- Proves exact Salesforce Flow-to-Apex paths from Flow action metadata to unique
|
|
15
|
+
`@InvocableMethod` targets, including targeted Apex refresh, source evidence,
|
|
16
|
+
omissions, freshness, and bounded responses.
|
|
17
|
+
- Makes repair converge truthfully across schema migration, empty repositories,
|
|
18
|
+
final verification failure, and future-schema refusal. Scoped repairs avoid
|
|
19
|
+
unrelated TypeScript DI reads while still rebuilding affected DI evidence.
|
|
20
|
+
- Strengthens the public behavioral contract and positioning with replayed
|
|
21
|
+
production CLI, MCP, and engine responses. C97-C101 evidence is independently
|
|
22
|
+
replayable and source-bound; failed performance experiments remain recorded
|
|
23
|
+
as limitations rather than superiority claims.
|
|
24
|
+
- Prevents stale package and barrel-resolution caches, avoids caching transient
|
|
25
|
+
filesystem failures, and keeps independent engine instances from closing
|
|
26
|
+
resources still owned by another instance.
|
|
27
|
+
- Reuses a bounded, generation-scoped resource corpus so warm reachability
|
|
28
|
+
queries do not reread every indexed source file while still failing closed on
|
|
29
|
+
disk drift.
|
|
30
|
+
- Bounds cross-substrate evidence consistently with the outer response budget,
|
|
31
|
+
fixes member-call reachability false positives, and makes evidence verifiers
|
|
32
|
+
recompute their claim-bearing gates instead of trusting stored booleans.
|
|
33
|
+
- Removes duplicated progress-worker and response-budget machinery, updates the
|
|
34
|
+
audited development dependency set, and fixes lifecycle evaluation owners so
|
|
35
|
+
the complete test process terminates.
|
|
36
|
+
- Records that pull requests are intentionally expensive because Sonar and the
|
|
37
|
+
complete repository gates run on each review stream; compatible work should
|
|
38
|
+
be stacked into one coherent PR rather than opened automatically as many small
|
|
39
|
+
PRs.
|
|
40
|
+
|
|
41
|
+
The one-process semantic-residency evaluation remains a retained no-go: neither
|
|
42
|
+
in-process ONNX disposal, worker threads, quantized weights, nor vector/cache
|
|
43
|
+
eviction met the repeatable memory gate without violating the local one-process
|
|
44
|
+
product boundary. Knodin retains lazy loading and bounded caches rather than
|
|
45
|
+
claiming unsupported reclamation.
|
|
46
|
+
|
|
47
|
+
This remains an ordinary 0.x release, not a dogfood-only build and not GA.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "knodin",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.3",
|
|
4
4
|
"description": "knodin — source-evidenced local code intelligence with known bounds. Stable identity, fresh evidence, truthful budgets, and recoverable bounded views.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"docs/DOCTOR-AND-UPDATES.md",
|
|
26
26
|
"docs/DIAGNOSTICS.md",
|
|
27
27
|
"docs/BEHAVIORAL-CONTRACT.md",
|
|
28
|
+
"docs/DEMO.md",
|
|
28
29
|
"docs/COMPARISON.md",
|
|
29
30
|
"docs/COMPETITIVE-LANDSCAPE-2026-08.md",
|
|
30
31
|
"docs/INDEXING-POLICY-AND-PROVENANCE.md",
|
|
@@ -57,6 +58,7 @@
|
|
|
57
58
|
"docs/releases/0.7.5.md",
|
|
58
59
|
"docs/releases/0.8.0.md",
|
|
59
60
|
"docs/releases/0.8.2.md",
|
|
61
|
+
"docs/releases/0.8.3.md",
|
|
60
62
|
"docs/assets/knodin-favicon.svg",
|
|
61
63
|
"docs/SYSTEMS-AND-RELATIONSHIPS.md",
|
|
62
64
|
"docs/TELEMETRY.md",
|
|
@@ -114,6 +116,16 @@
|
|
|
114
116
|
"bench:c93": "tsx benchmarks/evaluations/c93-engineering-outcomes/runner.ts",
|
|
115
117
|
"verify:c93": "tsx scripts/verify-c93.ts",
|
|
116
118
|
"verify:c95": "tsx scripts/verify-c95.ts && vitest run src/__tests__/unit/behavior-contract.spec.ts src/__tests__/unit/failure-diagnosis.spec.ts src/__tests__/unit/impact.spec.ts src/__tests__/unit/freshness.spec.ts",
|
|
119
|
+
"bench:c97": "tsx benchmarks/evaluations/c97-one-process-semantic-residency/runner.ts",
|
|
120
|
+
"verify:c97": "tsx scripts/verify-c97.ts",
|
|
121
|
+
"bench:c98": "tsx benchmarks/evaluations/c98-resource-reachability/runner.ts",
|
|
122
|
+
"verify:c98": "tsx scripts/verify-c98.ts && vitest run src/__tests__/unit/resource-reachability.spec.ts",
|
|
123
|
+
"bench:c99": "tsx benchmarks/evaluations/c99-typescript-di/runner.ts",
|
|
124
|
+
"verify:c99": "tsx scripts/verify-c99.ts && vitest run src/__tests__/unit/typescript-di.spec.ts",
|
|
125
|
+
"bench:c100": "tsx benchmarks/evaluations/c100-flow-apex-path/runner.ts",
|
|
126
|
+
"verify:c100": "tsx scripts/verify-c100.ts && vitest run src/__tests__/unit/salesforce-metadata.spec.ts",
|
|
127
|
+
"bench:c101": "tsx benchmarks/evaluations/c101-contract-positioning/runner.ts",
|
|
128
|
+
"verify:c101": "tsx scripts/verify-c101.ts",
|
|
117
129
|
"bench:ann": "bun scripts/ann-bench.ts",
|
|
118
130
|
"bench:perf": "tsx scripts/perf-bench.ts",
|
|
119
131
|
"bench:competitive": "tsx scripts/competitive-bakeoff.ts",
|
|
@@ -132,6 +132,65 @@ new items or strengthen existing ones; they do not reopen the archived roadmap.
|
|
|
132
132
|
| C94 | P1 | parked-external-evidence — 2026-08-06 (previous: blocked) | Make first use self-explanatory and demonstrable | C89, C90, C91 |
|
|
133
133
|
| C95 | P1 | implemented | Codify and replay the defensible behavioral contract | C3, C24, C83 |
|
|
134
134
|
| C96 | P2 | evaluated — deferred | Gate every new capability on a narrow outcome replay | C24, C93, C95 |
|
|
135
|
+
| C97 | P1 | evaluated — retained existing design | Reclaim idle semantic memory without changing one-process architecture | C46, C51, C80, C87 |
|
|
136
|
+
| C98 | P1 | implemented | Add bounded source-to-sink resource reachability | C2, C3, C8, C24, C78, C95 |
|
|
137
|
+
| C99 | P1 | implemented | Resolve bounded TypeScript dependency-injection wiring | C2, C3, C24, C95 |
|
|
138
|
+
| C100 | P1 | implemented | Prove bounded Salesforce Flow-to-Apex paths | C2, C3, C20, C23, C95, C96 |
|
|
139
|
+
| C101 | P1 | implemented | Strengthen contract-led positioning | C95, C97, C98, C99, C100 |
|
|
140
|
+
|
|
141
|
+
### C98 — Bounded source-to-sink resource reachability
|
|
142
|
+
|
|
143
|
+
- Status: implemented
|
|
144
|
+
- Evidence: `benchmarks/evaluations/c98-resource-reachability/` freezes the strengthened eight-path C78 oracle and records 100% precision, 100% recall, deterministic ordering, and historical cold/warm/RSS measurements across three local repositories. The verifier independently replays correctness and its current sub-1-GB memory gate; portfolio timings remain descriptive rather than acceptance gates.
|
|
145
|
+
- Implementation: `query resource_reachability` performs cached, on-demand TS/JS analysis without persisted resource-flow tables. It recognizes literal `process.env` and `fs.readFileSync` sources, `console.log`, `fetch`, and `db.query` sinks, plus assignment, argument, return, and bounded recursive handoff.
|
|
146
|
+
- Bounds: maximum depth 6 and 100 paths. Results are static heuristics, never runtime reachability or exploitability proof; dynamic names, reflection, computed aliases, unsupported languages, cycles, truncation, continuation, coverage, and freshness remain explicit.
|
|
147
|
+
- Locality: no hosted service, authentication, credentials, source egress, network access, or production model is required.
|
|
148
|
+
|
|
149
|
+
### C99 — Bounded TypeScript dependency-injection wiring
|
|
150
|
+
|
|
151
|
+
- Status: implemented
|
|
152
|
+
- Evidence: `benchmarks/evaluations/c99-typescript-di/` records 100% precision and recall on its declared Inversify/tsyringe oracle, including an explicit ambiguous-token omission; `npm run verify:c99` rejects stale evidence or any missed/extra edge.
|
|
153
|
+
- Implementation: exact source-only `di_binding` and `di_resolution` references cover `bind().to`, `toSelf`, `register(useClass)`, `registerSingleton`, `@inject`, `get`, and `resolve`. Existing explain, impact, traversal, shortest-path, review, and architecture consumers reuse the persisted relationships.
|
|
154
|
+
- Known bounds: only source-proven framework imports, receivers, token declarations, and uniquely resolved implementations qualify. Multiple bindings, computed tokens, aliases, factories, runtime container modules, conditionals, and reflection remain explicit omissions rather than inferred edges.
|
|
155
|
+
|
|
156
|
+
### C100 — Bounded Salesforce Flow-to-Apex paths
|
|
157
|
+
|
|
158
|
+
- Status: implemented
|
|
159
|
+
- Evidence: `benchmarks/evaluations/c100-flow-apex-path/` records 100% precision and recall for one preregistered Salesforce DX Flow `actionCalls` to uniquely declared Apex `@InvocableMethod` boundary, including unannotated, missing, and overloaded negative cases. The paired missed-dependency replay improves from an imprecise file answer to a stable method identity with exact XML and Apex evidence.
|
|
160
|
+
- Implementation: Flow indexing persists an exact `flow_apex_action` method reference in addition to its compatible file topology. `query cross_substrate_path <from> <to>` requires both endpoints and returns only that supported substrate transition with stable identities, per-step substrates, extracted provenance, confidence, freshness, exact source evidence, truthful truncation/continuation, and explicit omissions.
|
|
161
|
+
- Known bounds: this is not a general path engine and does not support Terraform, dbt, arbitrary Salesforce metadata, runtime dispatch, namespaced packages, factories, aliases, or ambiguous/multiple Apex methods. One passing boundary and paired task do not establish broad cross-substrate or competitor superiority.
|
|
162
|
+
- Locality: the replay requires no Salesforce org, hosted service, authentication, credentials, network access, or source egress.
|
|
163
|
+
|
|
164
|
+
### C101 — Contract-led positioning closure
|
|
165
|
+
|
|
166
|
+
- Status: implemented
|
|
167
|
+
- Evidence: `benchmarks/evaluations/c101-contract-positioning/` and
|
|
168
|
+
`scripts/verify-c101.ts` source-bind the C97–C100 decisions, the behavioral
|
|
169
|
+
contract, public CLI/MCP declarations, positioning documents, and repository
|
|
170
|
+
stewardship instructions.
|
|
171
|
+
- Contract: eight adversarial mutations of actual production responses reject
|
|
172
|
+
resource/path stale evidence, continuation-free truncation, a truncated
|
|
173
|
+
response presented as complete, heuristic-to-exact promotion, DI source
|
|
174
|
+
removal, DI ambiguity, and a path omission retained beside a supported step.
|
|
175
|
+
Fixture-backed CLI and one-tool MCP calls return the same bounded resource and
|
|
176
|
+
Flow-to-Apex envelopes; DI reuses
|
|
177
|
+
existing explain/query/review/map surfaces rather than adding a discriminator.
|
|
178
|
+
- Positioning: value is less manual context assembly and fewer missed
|
|
179
|
+
dependencies; ROI's intended mechanism is fewer corrective round trips
|
|
180
|
+
without hosted-service, authentication, or source-egress overhead, while
|
|
181
|
+
C93's null two-task result authorizes no measured productivity claim;
|
|
182
|
+
tomorrow is `knodin init` plus the local CLI or single gateway; the secret
|
|
183
|
+
sauce is stable identity, source evidence, freshness, and truthful budgets
|
|
184
|
+
composed under one contract.
|
|
185
|
+
- Known bounds: C98 is a static TS/JS heuristic, C99 covers only its declared
|
|
186
|
+
Inversify/tsyringe patterns, C100 proves one Flow-to-Apex boundary, and C97
|
|
187
|
+
does not reclaim idle semantic RSS. The closure proves checked fixtures, not
|
|
188
|
+
runtime causality, arbitrary cross-substrate paths, broad framework coverage,
|
|
189
|
+
client/platform certification, or competitor superiority.
|
|
190
|
+
- Stewardship: pull requests invoke the full test matrix and Sonar analysis and
|
|
191
|
+
are therefore long and resource intensive. Related dependency-compatible
|
|
192
|
+
commits normally form one reasonably sized shared PR; assistants do not
|
|
193
|
+
auto-open per-item PRs, and unrelated changes are not bundled for size.
|
|
135
194
|
|
|
136
195
|
## Roadmap completion contract
|
|
137
196
|
|
|
@@ -3709,6 +3768,42 @@ Evidence: `benchmarks/evaluations/c93-engineering-outcomes/verification.json`,
|
|
|
3709
3768
|
`contracts/behavior-contract-v1.json`, and
|
|
3710
3769
|
`benchmarks/evaluations/c95-behavior-contract/runner.ts`.
|
|
3711
3770
|
|
|
3771
|
+
### C97 — One-process semantic residency reclamation
|
|
3772
|
+
|
|
3773
|
+
- Status: evaluated — retained existing design
|
|
3774
|
+
- Priority: P1
|
|
3775
|
+
- Disposition: Evaluate
|
|
3776
|
+
- DependsOn: C46, C51, C80, C87
|
|
3777
|
+
- Touches: evaluation and decision evidence only; no runtime, status, API, or
|
|
3778
|
+
storage change.
|
|
3779
|
+
- What: test whether idle model/vector/HNSW eviction can make a repeatable OS-RSS
|
|
3780
|
+
guarantee while preserving Knodin's one-local-process architecture.
|
|
3781
|
+
- Evidence: `benchmarks/evaluations/c97-one-process-semantic-residency/` and
|
|
3782
|
+
`scripts/verify-c97.ts` bind 10-trial fresh-process measurements to the runner,
|
|
3783
|
+
engine, package, and embedding-test sources.
|
|
3784
|
+
|
|
3785
|
+
Decision: retain the current lazy local model and bounded generation-scoped
|
|
3786
|
+
caches. No in-process candidate repeatedly reclaimed both 32 MiB and 15% of its
|
|
3787
|
+
attributable semantic increment across two corpus tiers. ONNX disposal and
|
|
3788
|
+
allocator behavior were nondeterministic; `worker_threads` retained the shared
|
|
3789
|
+
native address space; q8 lacks the required C28 retrieval-equivalence replay;
|
|
3790
|
+
fp16 failed to initialize. Child-process isolation is explicitly rejected
|
|
3791
|
+
because it would violate the one-local-process product contract. Do not claim
|
|
3792
|
+
idle RSS reclamation from model disposal or cache clearing on this evidence.
|
|
3793
|
+
|
|
3794
|
+
Known limitations: resident semantic search retains a measurable one-process
|
|
3795
|
+
RSS cost after first use. Structural-first routing still avoids loading the model
|
|
3796
|
+
when evidence is sufficient, and decoded-vector/HNSW caches remain bounded and
|
|
3797
|
+
generation-invalidated. Reopen only with a portable allocator/runtime mechanism
|
|
3798
|
+
that passes the unchanged absolute, percentage, p95, retrieval, and 20-cycle
|
|
3799
|
+
gates.
|
|
3800
|
+
|
|
3801
|
+
Final-stack refresh: C101 reran the full C97 measurement after C98–C100 changed
|
|
3802
|
+
the shared engine. Some individual cache/ONNX trials crossed the memory
|
|
3803
|
+
threshold, but no production candidate passed all 10 trials; the retained
|
|
3804
|
+
one-process decision therefore remains unchanged. The refreshed raw artifact
|
|
3805
|
+
replaces the mutable C97 measurement file and `verify:c97` recomputes this gate.
|
|
3806
|
+
|
|
3712
3807
|
## Explicit non-goals from the GitNexus comparison
|
|
3713
3808
|
|
|
3714
3809
|
- Do not split knodin's gateway into one MCP schema per capability; the one-tool
|