knodin 0.12.2 → 0.13.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.
Files changed (45) hide show
  1. package/README.md +16 -1
  2. package/dist/bin/cli.js +173 -14
  3. package/dist/src/agent-events.js +25 -7
  4. package/dist/src/authenticated-cursor.js +81 -0
  5. package/dist/src/class-consumer-contract.js +18 -0
  6. package/dist/src/class-consumer-cursor.js +91 -0
  7. package/dist/src/class-consumer-delivery.js +22 -0
  8. package/dist/src/class-consumer-page.js +148 -0
  9. package/dist/src/cli-model.js +9 -3
  10. package/dist/src/docs-sections.js +1 -0
  11. package/dist/src/engine/apex-class-uses.js +430 -0
  12. package/dist/src/engine/apex-entry-points.js +98 -0
  13. package/dist/src/engine/apex-receiver.js +301 -0
  14. package/dist/src/engine/embedding-reuse.js +57 -0
  15. package/dist/src/engine/embeddings.js +22 -0
  16. package/dist/src/engine/index-coverage.js +215 -0
  17. package/dist/src/engine/index.js +2495 -252
  18. package/dist/src/engine/salesforce-components.js +460 -0
  19. package/dist/src/engine/seal.js +3 -0
  20. package/dist/src/engine/sqlite.js +44 -0
  21. package/dist/src/evidence-bundle.js +283 -0
  22. package/dist/src/evidence-graph.js +163 -0
  23. package/dist/src/failure-diagnosis.js +80 -5
  24. package/dist/src/file-dependency.js +35 -0
  25. package/dist/src/graph-query-health.js +47 -1
  26. package/dist/src/implementation-search.js +69 -0
  27. package/dist/src/index-coverage-read.js +33 -0
  28. package/dist/src/investigation.js +195 -0
  29. package/dist/src/mcp-reliability.js +4 -0
  30. package/dist/src/mcp-worker-supervisor.js +122 -6
  31. package/dist/src/progressive-evidence.js +4 -4
  32. package/dist/src/response-budget.js +129 -3
  33. package/dist/src/server.js +18 -5
  34. package/dist/src/shared-index/publisher.js +41 -1
  35. package/dist/src/tools/knodin-tools.js +224 -41
  36. package/docs/CLI.md +92 -0
  37. package/docs/MCP.md +67 -0
  38. package/docs/PROGRESSIVE-EVIDENCE.md +62 -0
  39. package/docs/SALESFORCE-BINDINGS.md +121 -0
  40. package/docs/SALESFORCE-DEAD-CODE.md +45 -0
  41. package/docs/SCOPED-INDEXING.md +76 -0
  42. package/docs/apex-receiver-resolution.md +41 -0
  43. package/docs/releases/0.13.0.md +62 -0
  44. package/docs/structural-only-indexing.md +20 -0
  45. package/package.json +11 -5
package/docs/MCP.md CHANGED
@@ -156,6 +156,21 @@ operation remains available in the gateway while a worker is being replaced.
156
156
  `KNODIN_MCP_DEADLINE_MS` may be set to a positive value up to 300000 for local
157
157
  testing of the cooperative repair path.
158
158
 
159
+ Multi-file evidence bundle byte/token accounting covers the compact JSON in the
160
+ MCP text content. It excludes the surrounding JSON-RPC/MCP transport envelope
161
+ and request/trace metadata. The gateway preserves that compact serialization so
162
+ pagination receipts and reported source budgets describe the delivered text.
163
+
164
+ The gateway retains at most four repository workers by default and retires each
165
+ after five minutes idle. Set `KNODIN_MCP_MAX_WORKERS` and
166
+ `KNODIN_MCP_IDLE_TIMEOUT_MS` to positive integers to tune these limits (maximum
167
+ 2147483647). At capacity the least recently used idle worker is retired; the
168
+ replacement waits for shutdown before starting. Active, starting, and queued
169
+ requests protect their worker from eviction. If every worker is busy, a new
170
+ repository receives `KNODIN_WORKER_CAPACITY` immediately and can retry after an
171
+ active request completes. These are process-count and idle-residency limits,
172
+ not a byte-level memory cap. Revisiting an evicted repository incurs cold startup.
173
+
159
174
  Checked-in process replays prove a real SQLite held lock, abrupt worker exit,
160
175
  disconnect/cancellation race against a stuck worker, hard kill, bounded restart,
161
176
  warm-worker reuse, worktree isolation, and the next independent success. The
@@ -181,3 +196,55 @@ centrality, and bounded Git-history facts separately. Churn, co-change, and
181
196
  coupling include contributing commits, bounds, omissions, confidence, and the
182
197
  response's graph freshness. See `docs/GIT-HISTORY-REVIEW.md`; co-change is
183
198
  correlation only and never an ownership, defect, or remediation assertion.
199
+
200
+ ### Local flow-analysis budgets
201
+
202
+ For `query` with `pattern: "flow_analysis"`, the effective response ceiling must
203
+ be at least 1536 serialized bytes (384 estimated tokens). It is the stricter of
204
+ `byteBudget` and `tokenBudget × 4`. Smaller ceilings are rejected, not silently
205
+ increased; larger required evidence or qualifications can still need more space.
206
+ Defaults and other patterns' budget policies are unchanged.
207
+
208
+ Flow response-budget metadata and drill-down continuation guidance identify
209
+ operation `query:flow_analysis` on both MCP and CLI. This is narrowing/retry
210
+ guidance, not a signed resumable cursor.
211
+
212
+ ### Paged Apex class-use evidence
213
+
214
+ `query` with `pattern: "inheritors_of"` and an unselected name aggregates nominal
215
+ inheritance across languages, not one globally resolved target. The fixed
216
+ `inheritanceQuery` qualification preserves mode, partial/truncation flags, and
217
+ Apex resolution status even when only non-Apex evidence is available. Apex rows
218
+ require verified typed endpoints; Apex `file`/`identity` selectors establish a
219
+ selected typed target. Non-Apex inheritance retains legacy name matching, not
220
+ an exact identity-resolution promise. An insufficient budget fails closed rather than dropping the
221
+ qualification. The restricted `query_batch` operation does not accept this pattern.
222
+ The tuple reports engine analysis bounds; `responseBudget.truncated` separately
223
+ reports wire-size trimming. Neither qualifier can substitute for the other.
224
+
225
+ Call `query` with `pattern: "class_consumers"`, an Apex class or interface `symbol`, and optional
226
+ `identity`/`file`, `testScope` (`all`, `test`, `production`), canonical `path` prefix,
227
+ and `limit` (1–1000 sites). This is separate from method calls and Java config
228
+ `consumers_of`. `count` counts observed sites, `consumerFileCount` counts files,
229
+ and `returnedCount` counts delivered sites; page-local `files` aggregates do not
230
+ enumerate every matching file until paging is complete.
231
+ The protected `targetKind` is `class` or `interface`. Interface targets admit
232
+ supported type-position roles, not constructor/static-field uses. `implements`
233
+ relationships and concrete runtime dispatch are not typed consumer sites.
234
+
235
+ Use the returned `continuation` with the same target and filters. Byte/token/item
236
+ budgets may vary. The signed token is interchangeable with CLI `--continuation`
237
+ in the same repository and unchanged graph snapshot. All evidence and scope
238
+ qualifications fit before the cursor is signed; no generic truncation follows.
239
+ An extra limit-one backend read currently revalidates the snapshot before delivery;
240
+ this correctness guard is not a claim of optimized paging cost.
241
+
242
+ The nine supported Apex roles exclude target-self-file sites and do not establish
243
+ complete class-use or runtime reachability. `classConsumerAnalysis` reports partial
244
+ extraction and indexed-inventory counters, separately from `indexCoverage`. Unknown
245
+ targets and ambiguity are unavailable, never successful zero-site answers.
246
+ `CLASS_CONSUMER_TARGET_CAPABILITY_MISSING` with `targetResolution: "capability-missing"`
247
+ means retained indexed interface evidence exists but its symbol capability is
248
+ missing. It is unavailable without a fabricated target identity or zero count;
249
+ follow the returned scope-preserving repair guidance. This differs from an unknown
250
+ target and does not expand indexed coverage.
@@ -35,3 +35,65 @@ absolute/traversal paths, and symlinks are refused.
35
35
 
36
36
  This protocol does not summarize source and does not support token-savings or
37
37
  task-success claims. See the C83 checked-in replay and limitations for bounds.
38
+
39
+ ## Graph-backed file bundles
40
+
41
+ The additive bundle protocol (`knodin-evidence-bundle-v1`) accepts an explicit
42
+ list of repository-relative `files`. At `evidence` level it returns those files;
43
+ at `expand` level an injected graph adapter can add related files with their
44
+ identity, relationship, confidence, and source-location provenance. It never
45
+ searches the repository for matching names. Stale or unknown graph relationships
46
+ are omitted explicitly; each selected file's source is read and hashed locally.
47
+ The original single-file API and its `pev1` handles remain compatible.
48
+
49
+ Each response includes a per-file hash/byte manifest. Its `evidenceHandle` is
50
+ `null` until the complete file has been delivered across the signed cursor
51
+ chain; only then is a signed `peb1` completion receipt issued. Pass completed
52
+ receipts as `alreadyPresent` to omit unchanged files you still hold. A changed
53
+ file invalidates only its own receipt and returns current source. Forged,
54
+ cross-repository, incomplete, and wrong-purpose handles are rejected. Reading
55
+ only the manifest or an initial source page does not authorize source omission.
56
+
57
+ Continue a truncated bundle with its `continuation`, preserving `files`, `level`,
58
+ and `alreadyPresent`. The cursor binds selected files, hashes, graph provenance,
59
+ and reuse assertions. Content or graph changes reject the cursor and require a
60
+ fresh request, preventing a stale cursor from skipping newly changed source.
61
+ Pages contain exact source line ranges, so line-aligned chunks can be joined
62
+ with a newline. Per-file handles and bundle continuations are not interchangeable.
63
+
64
+ The manifest and all response metadata count toward the hard UTF-8 byte/token
65
+ budget. The item cap counts returned source lines and reused-file records. If
66
+ the manifest cannot fit, narrow the file list or increase the budget. A source
67
+ line too large for the remaining budget is omitted with a continuation; increase
68
+ the byte/token budget to retrieve it. Requests are bounded to 32 selected files
69
+ and 8 MiB of source. These are local static associations, not runtime proof;
70
+ graph omissions remain visible even after every selected source file is returned.
71
+
72
+ CLI:
73
+
74
+ ```bash
75
+ knodin evidence expand --files src/widget.ts --items 100 --json
76
+ knodin evidence evidence --files src/widget.ts,src/caller.ts --items 20 --json
77
+ knodin evidence evidence --files src/widget.ts,src/caller.ts \
78
+ --continuation '<bundle-continuation>' --items 20 --json
79
+ knodin evidence evidence --files src/widget.ts,src/caller.ts \
80
+ --already-present '<completed-receipt>,<completed-receipt>' --json
81
+ ```
82
+
83
+ The MCP equivalents use `operation: "evidence"`, `evidenceLevel:
84
+ "evidence"|"expand"`, and `evidenceFiles: ["src/widget.ts", "src/caller.ts"]`.
85
+ Use `itemBudget`, `byteBudget`, and `tokenBudget` for limits; `continuation` and
86
+ `alreadyPresent` accept the same handles on either surface. Supply `file` for
87
+ the original single-file protocol or `evidenceFiles` for a bundle, never both.
88
+ The current graph adapter follows whitelisted file dependencies breadth-first through
89
+ `imports_of` and `importers_of`, including supported Salesforce Flow, QuickAction,
90
+ App Builder, controller, Apex method binding, and component relationships. It
91
+ does not treat those bindings as executed calls. These associations are labeled
92
+ heuristic; source text and its hashes remain exact.
93
+
94
+ Discovery stops at two dependency hops and 32 files including the requested seeds.
95
+ Cycles are visited once; query truncation, omitted files and uninspected depth
96
+ frontiers are reported explicitly. A generation or freshness change during any
97
+ hop withholds all graph-selected relationships. This bounded discovery is not
98
+ whole-repository reachability or proof of complete source delivery: use the
99
+ continuation and completion receipts for delivery verification.
@@ -0,0 +1,121 @@
1
+ # Salesforce metadata bindings
2
+
3
+ Knodin records a bounded set of literal, local Salesforce DX bindings as
4
+ file-to-file dependencies. These indicate source declarations, not successful
5
+ deployment, configured org availability, runtime reachability, or execution.
6
+
7
+ | Source | Literal declaration | Target | Dependency kind |
8
+ | --- | --- | --- | --- |
9
+ | `force-app/main/default/quickActions/[Object.]Name.quickAction-meta.xml` | `type=LightningComponent` and one `lightningComponent` value | Unique local Aura `aura/Name/Name.cmp` | `quickaction_lightning_component` |
10
+ | `force-app/main/default/lwc/Name/Name.js-meta.xml` | A `targetConfig` property with `datasource="apex://ClassName"` | Unique local `ClassName.cls` | `appbuilder_apex_datasource` |
11
+ | `force-app/main/default/aura/Name/Name.design` | A `design:attribute` with `datasource="apex://ClassName"` | Unique local `ClassName.cls` | `appbuilder_apex_datasource` |
12
+
13
+ Edges point from the declaring metadata file to the target source file and
14
+ retain the XML tag/attribute as source evidence. Query `importers_of` with the
15
+ target file to discover these consumers. They are not inserted as executed
16
+ method calls, so `callers_of ClassName` is not a substitute for this query.
17
+
18
+ QuickAction component values accept bare local names or the explicit `c:`
19
+ namespace. Other namespaces, computed values, missing targets, and duplicate
20
+ matching target files produce no resolved edge. The `lightningComponent` field
21
+ is the Aura bridge; the separate LWC QuickAction field is not implemented by
22
+ this extractor. App Builder extraction ignores comments, CDATA, static lists,
23
+ non-Apex URLs, description text, duplicate datasource attributes, and dynamic
24
+ or namespaced Apex values. Target filename matching preserves exact spelling;
25
+ case-normalized Apex resolution is a separate follow-up.
26
+
27
+ Target changes, additions, deletions, and newly introduced duplicates revisit
28
+ indexed binding sources, including declarations that previously had no edge.
29
+ Source-only edits replace old outgoing edges. A bounded repository/generation
30
+ catalog avoids a repository walk for every individual binding. On upgrading
31
+ an existing graph, unchanged metadata needs re-extraction before new bindings
32
+ can be claimed; a clean selected-source replay does not establish that an old
33
+ real-world graph has been migrated.
34
+
35
+ ## Component markup and Lightning pages
36
+
37
+ Within the same canonical `force-app/main/default/` layout, Knodin also records:
38
+
39
+ | Source declaration | Target file | Dependency kind |
40
+ | --- | --- | --- |
41
+ | Aura `.cmp`/`.app` literal `<c:Name>` | Unique Aura `Name.cmp` | `aura_component` |
42
+ | Aura `.cmp`/`.app` literal `<c:Name>` | Unique LWC `Name.js` | `aura_lwc_component` |
43
+ | LWC `.html` literal `<c-name>` | Unique LWC entrypoint `.js` | `lwc_template_component` |
44
+ | FlexiPage component-instance `componentName` | Unique Aura `.cmp` or LWC `.js` | `flexipage_component` |
45
+ | FlexiPage direct `template/name` | Unique Aura `.cmp` | `flexipage_template` |
46
+ | Flow direct `screens/fields/extensionName` with literal `c:Name` | Unique Aura `.cmp` or LWC `.js` | `flow_screen_component` |
47
+ | Aura application direct `aura:dependency resource="c:Name"` | Unique Aura `.cmp` or LWC `.js` | `aura_resource_component` |
48
+ | Visualforce page inline `$Lightning.use("c:Name", ...)` | Unique Aura `.app` | `visualforce_lightning_out` |
49
+ | WebLink direct `linkType=page` and singleton `page` | Unique Visualforce `.page` | `weblink_visualforce_page` |
50
+
51
+ FlexiPage identifiers may be bare or prefixed with `c:`. Modern
52
+ `flexiPageRegions/itemInstances/componentInstance` and legacy
53
+ `flexiPageRegions/componentInstances` containers are recognized; unrelated
54
+ `name`/`componentName` fields are not. Aura/LWC name collisions are withheld,
55
+ not resolved by preferring one framework. LWC HTML aliases are generated from
56
+ declared bundle names: camelCase becomes kebab-case while underscores remain
57
+ underscores. Case-preserving metadata matching does not inherit Apex's
58
+ case-insensitive receiver rules.
59
+
60
+ Flow screen bindings require exactly one literal `extensionName` in the direct
61
+ screen-field context. When `fieldType` is present, it must be exactly one literal
62
+ `ComponentInstance`; omission remains supported for existing LWC metadata. This
63
+ is bounded source extraction, not full Flow schema validation. Unrelated XML
64
+ contexts, duplicate declarations, comments, computed names, and ambiguous
65
+ Aura/LWC targets are withheld. These bindings receive the same target-only
66
+ refresh handling as component markup and Lightning pages.
67
+ Flow exports may declare the standard `xmlns:xsi` schema-instance namespace for
68
+ unrelated nullable metadata values. Other bindings or rebindings of that prefix
69
+ are unsupported; `xsi` annotations on screen/component identity elements are
70
+ withheld, not treated as literal component identities.
71
+
72
+ Lightning Out extraction recognizes literal JavaScript member calls in bounded
73
+ inline scripts within canonical Visualforce pages. Comments, strings, dynamic
74
+ names, malformed scripts, computed calls and ambiguous raw-script boundaries
75
+ do not supply bindings. A declaration or reassignment involving `$Lightning`
76
+ in any parsed script withholds all of the page's Lightning Out bindings,
77
+ including declarations in other scripts. External script behavior, runtime
78
+ global mutation and Visualforce merge-expression evaluation are not analyzed;
79
+ these edges identify static configuration, not guaranteed platform execution.
80
+ Application and Visualforce page names use separate exact target namespaces.
81
+ WebLink extraction requires the canonical object `webLinks` path and direct XML
82
+ fields; unrelated fields and duplicate page/link-type declarations are withheld.
83
+
84
+ The XML paths reuse the shipped parser and additionally reject unsupported
85
+ namespaces, DTDs, undeclared entities, malformed markup, and nonliteral identity
86
+ values. Comments, CDATA, and attribute strings cannot supply component tags.
87
+ LWC HTML uses a separate bounded literal subset. Raw-text contents such as
88
+ `script`, `style`, and `textarea`, and SVG/MathML subtrees are opaque while ordinary
89
+ component siblings remain eligible. Namespace re-entry through `foreignObject`
90
+ or other integration points is not modeled. Unclosed raw-text boundaries and
91
+ HTML `plaintext` remain unsupported. A document is also withheld when script
92
+ comments/nested script markers make its closing boundary ambiguous. Dynamic component
93
+ creation, foreign namespaces, and arbitrary directories named `lwc` or `aura`
94
+ do not become local component dependencies.
95
+
96
+ Target-only additions, deletions, and Aura/LWC collisions revisit indexed source
97
+ bindings, including previously unresolved ones. A newly recognized source in an
98
+ old index still needs re-extraction, for example an explicit structural refresh
99
+ with `knodin index --under force-app/main/default --force --skip-embeddings`.
100
+ These are direct file edges: a parent LWC consumer is its `.html` file, not an
101
+ invented JavaScript call site or a claim of complete bundle-level reachability.
102
+
103
+ The schemas are documented in Salesforce's [QuickAction metadata reference](https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_quickaction.htm),
104
+ [LWC XML configuration reference](https://developer.salesforce.com/docs/platform/lwc/guide/reference-configuration-tags.html),
105
+ and [dynamic picklist configuration guide](https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/components_config_for_app_builder_dynamic_picklists.htm).
106
+
107
+ ## Apex class-use sites are a separate query
108
+
109
+ `query class_consumers` exposes static-field reads, constructors, variable types,
110
+ casts, class literals, parameter types, generic parameter types, loop-variable
111
+ types, and generic type arguments. It does not widen metadata bindings or method
112
+ call edges. Case-insensitive type resolution requires unique declarations and
113
+ validated owner chains; value/type shadows, malformed source and ambiguous
114
+ catalog entries cannot become confident class matches.
115
+
116
+ Results exclude the target's own source file and include test files by default.
117
+ Missing descriptors, unresolved uses and unsupported forms qualify the observed
118
+ counts. Static method receivers, return types, inheritance and writes are not
119
+ promoted into these nine roles. These source-evidenced sites are not complete
120
+ Apex usage enumeration or runtime reachability proof. See the CLI/MCP paging
121
+ sections for signed continuations and exact site-position conventions.
@@ -0,0 +1,45 @@
1
+ # Salesforce dead-code candidates
2
+
3
+ `dead_code` returns static candidates, not permission to delete code. A symbol
4
+ without a locally resolved caller can still be reached through org configuration,
5
+ runtime dispatch, reflection, or an unsupported dependency kind.
6
+
7
+ Native Apex declaration evidence now excludes recognized org-facing boundaries:
8
+ REST resource classes and annotated static methods; Invocable, Lightning and
9
+ future static methods; SOAP methods; and supported Queueable, Batchable,
10
+ Schedulable and inbound-email contracts and callback signatures. The owner class
11
+ and its constructors are protected when an org-facing member is recognized.
12
+
13
+ This does **not** exempt every method in such a class. Ordinary helpers remain
14
+ candidates. Callback matching checks the declaring class, method name, public or
15
+ global instance visibility, arity and parameter types. For example,
16
+ `execute(String)` does not become a Queueable entry point merely because another
17
+ overload accepts `QueueableContext`. Nested classes and same-named declarations
18
+ in different files are not merged. `global` visibility alone is not an exemption.
19
+
20
+ The response's `deadCodeAnalysis` reports protected declaration counts, files
21
+ whose Apex declarations are unsupported, repository-wide missing Apex capability
22
+ counts, and whether the analysis is partial. Old/malformed declaration evidence
23
+ cannot support an unused-code verdict: affected Apex files are withheld and a
24
+ refresh instruction is returned. For old sealed artifacts, refresh the source
25
+ graph and produce a new sealed artifact; a read-only artifact cannot acquire
26
+ missing extraction evidence in place.
27
+
28
+ ## Limits
29
+
30
+ Recognition is source-declaration evidence, not a compiler validity check or proof
31
+ that an org actually invokes a class. Native parameter matching does not infer
32
+ arbitrary user-defined type aliases or runtime overload selection. Batchable
33
+ collection parameters are recognized as lists/arrays; generic-type compatibility
34
+ is not a Salesforce compiler judgment. Dead-chain/root reachability, complete
35
+ class/type consumer enumeration, and org-only configuration remain separate gaps.
36
+
37
+ For local pre-release verification without publishing or changing live indexes:
38
+
39
+ ```sh
40
+ node scripts/knodin-outcome-replay.mjs --manifest benchmarks/evaluations/knodin-41-outcomes/dead-code-manifest.json --out /tmp/knodin-dead-code-new-run
41
+ ```
42
+
43
+ Build the current checkout first. The runner copies the pinned actual sources
44
+ into a private temporary graph and refuses an existing output directory. Its
45
+ small selected-source corpus is not a whole-repository dead-code assessment.
@@ -0,0 +1,76 @@
1
+ # Scoped indexing
2
+
3
+ Use a scoped first index when a repository is too large to index before a bounded
4
+ investigation. Scope is durable graph state, not a temporary output filter:
5
+
6
+ ```sh
7
+ knodin index --under force-app/main/default/aura --skip-embeddings
8
+ knodin index --under force-app/main/default/quickActions --skip-embeddings
9
+ knodin query importers_of force-app/main/default/aura/MyComponent/MyComponent.cmp
10
+ ```
11
+
12
+ The second index adds its prefix to the first. Cold reopen, query reconciliation,
13
+ watcher updates, deep status audits, and repair retain that union; they do not
14
+ silently index the rest of the repository. Prefix matching respects directory
15
+ boundaries: `aura` does not include `aura-old`.
16
+
17
+ An explicit file list remains an exact file selection, including on cold reopen:
18
+
19
+ ```sh
20
+ knodin index src/one.ts src/two.ts --skip-embeddings
21
+ ```
22
+
23
+ Adding a containing prefix subsumes those exact selectors. Updating a subset of
24
+ an already full graph never shrinks its coverage. An explicit full index on a
25
+ scoped graph builds and verifies an isolated candidate; only successful atomic
26
+ promotion replaces the active scoped graph.
27
+
28
+ ## Inventory and safety
29
+
30
+ Git-backed prefix discovery uses literal, bounded Git pathspec batches before
31
+ enumerating source files. It includes tracked and unignored untracked files,
32
+ subject to the existing source eligibility rules. Git errors or output overflow
33
+ fail closed instead of falling back to an unfiltered filesystem walk. Non-Git
34
+ repositories walk only the selected prefixes or exact files. Selectors must stay
35
+ inside the repository; scoped discovery does not follow symbolic links.
36
+
37
+ Use tracked or unignored paths for explicit file selections. The policy for an
38
+ explicitly requested Git-ignored file is not yet part of this scoped-indexing
39
+ contract; it must not be used as an implicit ignore override.
40
+
41
+ The complete intent is stored locally, with version and revision. Graph-backed
42
+ query and health summaries contain only bounded counts and selector previews, plus a digest
43
+ binding the intent. Git argument batches are limited to 256 literal selectors
44
+ and approximately 32 KiB each. Persisted intent is limited to 100,000 selectors
45
+ and 16 MB; oversized or malformed intent is rejected rather than broadened.
46
+
47
+ ## Completion and negative answers
48
+
49
+ `indexCoverage` reports `mode`, `origin`, `revision`, `digest`, `intentState`,
50
+ `repositoryComplete`, and `negativeScope`, with bounded selector counts/previews.
51
+
52
+ - A complete scoped intent has `repositoryComplete: false` and
53
+ `negativeScope: "declared-scope"`. A missing result is not a repository-wide
54
+ absence claim.
55
+ - A pending or unknown intent has `negativeScope: "unknown"`; interrupted work
56
+ must not be described as a completed inventory.
57
+ - Older graphs without explicit intent retain legacy full-mode compatibility,
58
+ but do not gain measured completeness merely from their age or full intent.
59
+ - Malformed intent fails closed. Restore valid metadata or explicitly rebuild a
60
+ full candidate; ordinary queries and repair must not guess the missing scope.
61
+
62
+ These fields describe inventory extent, not completeness of the language parser,
63
+ call graph, type/configuration references, dynamic dispatch, or runtime behavior.
64
+ Existing target ambiguity, extraction capability, freshness, and response-budget
65
+ limitations still apply. A completed index can subsequently become stale; check
66
+ the result's freshness as well as its coverage summary.
67
+
68
+ Intent and a pending marker are persisted before scoped work. A failed or empty
69
+ prefix selection therefore remains visible as pending instead of reverting to
70
+ an accidental full index. Repair or subsequent reconciliation can complete the
71
+ declared inventory. Structure-only intent also preserves embedding deferral
72
+ through recovery; reading a graph does not request inference.
73
+
74
+ Source-only operations such as text search, file metrics, and language-server
75
+ queries have their own traversal/coverage contracts. Scoped graph intent does
76
+ not imply that every nongraph command is restricted to those selectors.
@@ -0,0 +1,41 @@
1
+ # Static Apex receiver evidence
2
+
3
+ The native generic parser preserves versioned Apex declaration and call
4
+ provenance. Worker threads transport the same plain extraction result as the
5
+ serial parser. SQLite stores raw `apexDeclaration` and `apexCall` payloads; file
6
+ capability epochs distinguish refreshed files from older graphs.
7
+
8
+ After identities are persisted, a repository-scoped indexed catalog binds a
9
+ literal class receiver to one declared static method with the same owner and
10
+ argument count. Identifier comparison is case-insensitive. Declaration spelling
11
+ is used for the resolved endpoint without overwriting raw receiver/member text.
12
+ An explicit construction binds to the class symbol only when its constructor
13
+ arity is unique; a class with no explicit constructors permits the implicit
14
+ zero-argument construction. This is constructor evidence, not proof that a
15
+ particular handler method executes.
16
+
17
+ Same-arity overloads, duplicate class identities, dynamic receivers, value
18
+ shadowing, inherited-scope uncertainty, and unqualified nested-owner ambiguity
19
+ remain unresolved. The conservative shadow check can also reject a receiver
20
+ when a same-named binding exists elsewhere in its containing class. Qualified
21
+ nested owners are supported when uniquely declared. Runtime instance/interface
22
+ dispatch, overload selection by inferred argument type, inherited method lookup,
23
+ and general class-consumer enumeration are not supplied by these edges.
24
+
25
+ Changed Apex batches re-resolve persisted raw calls, including previously
26
+ unresolved ones, against the current indexed catalog. Thus target-only rename,
27
+ deletion, creation, and duplicate/overload introduction do not require reparsing
28
+ every caller. This currently scans indexed Apex declarations and raw calls once
29
+ per resolver invocation; it is not a constant-time incremental dependency index.
30
+ The resolver does not traverse or open repository source files per call.
31
+
32
+ Older indexes are not silently upgraded by name-only matching. Caller/callee
33
+ responses expose `apexReceiverCapability`, including missing-file counts,
34
+ bounded missing paths, and malformed/unknown payload counts. Refresh selected
35
+ Apex paths with `knodin index <files> --force --skip-embeddings`, or use a scoped
36
+ `--under` rebuild. Capability checks also work on older read-only artifacts
37
+ without adding tables or columns. Payload validation is a keyset-paged indexed
38
+ data scan, not source-file traversal; it adds work to these queries.
39
+
40
+ These additions do not require a full graph rebuild or change existing stored
41
+ embedding inputs. Explicit semantic deferral remains available during refresh.
@@ -0,0 +1,62 @@
1
+ # knodin 0.13.0
2
+
3
+ This release adds task-oriented investigation and Salesforce evidence queries,
4
+ with explicit indexing coverage and bounded, recoverable results. It also
5
+ improves repeated graph reads and embedding reuse. Work is tracked under
6
+ KNODIN-41 through KNODIN-47.
7
+
8
+ This is a pre-1.0 breaking minor release: callers requesting flow-analysis
9
+ budgets below the new minimum must increase their requested limit.
10
+
11
+ ## Source-evidenced investigations
12
+
13
+ - Task-oriented investigation, implementation search, and evidence bundles
14
+ assemble related source evidence for CLI and MCP consumers.
15
+ - File dependency evidence includes re-exports; coverage travels with results
16
+ so a scoped or partially parsed graph is not presented as whole-repository
17
+ proof.
18
+ - Scoped and structural-only indexing provide explicit alternatives to a full
19
+ semantic index. Unchanged embedding inputs can reuse existing vectors.
20
+
21
+ ## Salesforce analysis
22
+
23
+ - Apex class-use queries and entry-point-aware dead-code analysis distinguish
24
+ supported source uses from inheritance and implementation relationships.
25
+ - Receiver resolution and Salesforce component bindings add evidence for
26
+ supported Apex and Lightning relationships without claiming runtime coverage.
27
+ - Class-consumer paging uses authenticated cursors, scope-bound evidence, and
28
+ delivery-time validation to reject stale or mismatched results.
29
+
30
+ ## Reliability and response budgets
31
+
32
+ - Evidence bundles reject malformed UTF-8 instead of issuing receipts for lossy
33
+ decoded text. Graph-expanded bundles pin selected source bytes and recheck the
34
+ graph before delivery, refusing results that change across that boundary.
35
+ - Repeated class-consumer reads reuse validated native evidence where safe.
36
+ Their post-query health check defers optional WAL checkpoint maintenance;
37
+ correctness checks remain in place. A later eligible audit or close can
38
+ checkpoint the WAL; no separate checkpoint job is scheduled.
39
+ - Flow analysis now requires at least **1,536 serialized bytes**, or **384
40
+ estimated tokens**. When both limits are supplied, the stricter limit applies.
41
+ Smaller requests fail explicitly; the tool does not silently enlarge them.
42
+ This is a minimum request size, not a guarantee every result will fit.
43
+ - Flow truncation guidance describes how to retry; it is not an authenticated
44
+ continuation cursor. Other operations retain their existing minimum budgets.
45
+
46
+ ## Dependency maintenance
47
+
48
+ - Update Sharp to 0.35.4, Hono to 4.13.7, and Vitest with its aligned tooling
49
+ to 4.1.11 to address newly reported dependency advisories. This does not
50
+ claim that every outstanding dependency advisory is resolved.
51
+
52
+ ## Evidence and known bounds
53
+
54
+ The checked-in KNODIN-41 evaluation reports distinguish private copies of actual
55
+ SalesforceCI and minions sources from synthetic fixtures. Selected-source
56
+ success does not certify either entire repository. Unsupported cases, partial
57
+ parses, and historical source blockers remain visible in those reports.
58
+
59
+ Measured performance has been mixed across cold, warm, indexing, and public
60
+ command paths. This release makes no overall speedup or superiority claim.
61
+ See `roadmap/competitive-roadmap.md` for the remaining product and distribution
62
+ certification boundaries.
@@ -0,0 +1,20 @@
1
+ # Structural-only indexing
2
+
3
+ Use `knodin index --skip-embeddings` to build native structure without running
4
+ semantic inference. It also works with `--clean`/`--force`, explicit file paths,
5
+ and `--under <directory>`. Scoped indexing still discovers the repository file
6
+ inventory before filtering; it is not a constant-time directory operation.
7
+
8
+ Intentional deferral is persisted in the local graph. Reopening the graph for a
9
+ structural query, read-side reconciliation, or watcher updates does not silently
10
+ complete the semantic backlog. Semantic readiness remains `absent` or `partial`
11
+ until the missing vectors are built; semantic retrieval may under-return.
12
+
13
+ Run an explicit `knodin index` without `--skip-embeddings` to resume inference.
14
+ An explicit-file index without the flag also completes the missing-vector pass,
15
+ including deferred symbols outside those files. Existing vectors are retained.
16
+
17
+ A deferred clean candidate must still pass SQLite, source coverage, source
18
+ snapshot, and orphan checks before promotion. Only the requirement for complete
19
+ semantic coverage is waived for an intentionally deferred graph. An interrupted
20
+ ordinary semantic build does not gain that exemption.
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "knodin",
3
- "version": "0.12.2",
3
+ "version": "0.13.0",
4
4
  "knodin": {
5
- "compatibility": "compatible"
5
+ "compatibility": "breaking"
6
6
  },
7
7
  "description": "knodin — source-evidenced local code intelligence with known bounds. Stable identity, fresh evidence, truthful budgets, and recoverable bounded views.",
8
8
  "license": "MIT",
@@ -46,12 +46,17 @@
46
46
  "docs/PT-ACCESS-RECOMMENDATION.md",
47
47
  "docs/RELEASE-0.3-EVIDENCE.md",
48
48
  "docs/REPOSITORIES-AND-WORKTREES.md",
49
+ "docs/SALESFORCE-BINDINGS.md",
50
+ "docs/SALESFORCE-DEAD-CODE.md",
51
+ "docs/SCOPED-INDEXING.md",
49
52
  "docs/SCIP-IMPORT.md",
50
53
  "docs/SHARED-INDEX-CONTRACT.md",
51
54
  "docs/SIGNED-UPDATES.md",
52
55
  "docs/SYSTEMS-AND-RELATIONSHIPS.md",
53
56
  "docs/TELEMETRY.md",
54
57
  "docs/TOKEN-OPTIMIZER-SCORECARD.md",
58
+ "docs/apex-receiver-resolution.md",
59
+ "docs/structural-only-indexing.md",
55
60
  "docs/assets/knodin-favicon.svg",
56
61
  "docs/prompts/declare-multi-repository-system.md",
57
62
  "docs/releases/0.10.0.md",
@@ -67,6 +72,7 @@
67
72
  "docs/releases/0.12.0.md",
68
73
  "docs/releases/0.12.1.md",
69
74
  "docs/releases/0.12.2.md",
75
+ "docs/releases/0.13.0.md",
70
76
  "docs/releases/0.3.0.md",
71
77
  "docs/releases/0.4.0.md",
72
78
  "docs/releases/0.4.1.md",
@@ -187,17 +193,17 @@
187
193
  "@hono/node-server": "^2.0.5",
188
194
  "adm-zip": "^0.6.0",
189
195
  "fast-uri": "^4.1.1",
190
- "sharp": "^0.35.3"
196
+ "sharp": "^0.35.4"
191
197
  },
192
198
  "devDependencies": {
193
199
  "@biomejs/biome": "2.4.6",
194
200
  "@types/bun": "^1.3.14",
195
201
  "@types/node": "^24.10.0",
196
- "@vitest/coverage-v8": "^4.1.10",
202
+ "@vitest/coverage-v8": "^4.1.11",
197
203
  "ajv": "8.20.0",
198
204
  "lefthook": "^2.1.5",
199
205
  "tsx": "^4.21.0",
200
206
  "typescript": "^5.9.3",
201
- "vitest": "^4.1.3"
207
+ "vitest": "^4.1.11"
202
208
  }
203
209
  }