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.
- package/README.md +16 -1
- package/dist/bin/cli.js +173 -14
- package/dist/src/agent-events.js +25 -7
- package/dist/src/authenticated-cursor.js +81 -0
- package/dist/src/class-consumer-contract.js +18 -0
- package/dist/src/class-consumer-cursor.js +91 -0
- package/dist/src/class-consumer-delivery.js +22 -0
- package/dist/src/class-consumer-page.js +148 -0
- package/dist/src/cli-model.js +9 -3
- package/dist/src/docs-sections.js +1 -0
- package/dist/src/engine/apex-class-uses.js +430 -0
- package/dist/src/engine/apex-entry-points.js +98 -0
- package/dist/src/engine/apex-receiver.js +301 -0
- package/dist/src/engine/embedding-reuse.js +57 -0
- package/dist/src/engine/embeddings.js +22 -0
- package/dist/src/engine/index-coverage.js +215 -0
- package/dist/src/engine/index.js +2495 -252
- package/dist/src/engine/salesforce-components.js +460 -0
- package/dist/src/engine/seal.js +3 -0
- package/dist/src/engine/sqlite.js +44 -0
- package/dist/src/evidence-bundle.js +283 -0
- package/dist/src/evidence-graph.js +163 -0
- package/dist/src/failure-diagnosis.js +80 -5
- package/dist/src/file-dependency.js +35 -0
- package/dist/src/graph-query-health.js +47 -1
- package/dist/src/implementation-search.js +69 -0
- package/dist/src/index-coverage-read.js +33 -0
- package/dist/src/investigation.js +195 -0
- package/dist/src/mcp-reliability.js +4 -0
- package/dist/src/mcp-worker-supervisor.js +122 -6
- package/dist/src/progressive-evidence.js +4 -4
- package/dist/src/response-budget.js +129 -3
- package/dist/src/server.js +18 -5
- package/dist/src/shared-index/publisher.js +41 -1
- package/dist/src/tools/knodin-tools.js +224 -41
- package/docs/CLI.md +92 -0
- package/docs/MCP.md +67 -0
- package/docs/PROGRESSIVE-EVIDENCE.md +62 -0
- package/docs/SALESFORCE-BINDINGS.md +121 -0
- package/docs/SALESFORCE-DEAD-CODE.md +45 -0
- package/docs/SCOPED-INDEXING.md +76 -0
- package/docs/apex-receiver-resolution.md +41 -0
- package/docs/releases/0.13.0.md +62 -0
- package/docs/structural-only-indexing.md +20 -0
- 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.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"knodin": {
|
|
5
|
-
"compatibility": "
|
|
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.
|
|
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.
|
|
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.
|
|
207
|
+
"vitest": "^4.1.11"
|
|
202
208
|
}
|
|
203
209
|
}
|