knodin 0.13.0 → 0.14.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/dist/bin/cli.js +120 -9
- package/dist/src/backup-retention.js +345 -12
- package/dist/src/class-consumer-cursor.js +2 -0
- package/dist/src/cli-model.js +12 -0
- package/dist/src/compact-structural.js +7 -2
- package/dist/src/engine/apex-class-uses.js +54 -8
- package/dist/src/engine/apex-dead-chains.js +368 -0
- package/dist/src/engine/apex-entry-points.js +44 -8
- package/dist/src/engine/candidate-database.js +624 -66
- package/dist/src/engine/index.js +1768 -258
- package/dist/src/engine/seal.js +28 -4
- package/dist/src/engine/state-paths.js +192 -31
- package/dist/src/init.js +14 -2
- package/dist/src/manager-update.js +9 -10
- package/dist/src/mirror.js +2 -0
- package/dist/src/response-budget.js +14 -2
- package/dist/src/shared-index/restore.js +16 -6
- package/dist/src/storage-budget.js +146 -0
- package/dist/src/storage-inventory.js +263 -0
- package/dist/src/storage-management.js +204 -0
- package/dist/src/storage-policy-contract.js +121 -0
- package/dist/src/tools/knodin-tools.js +1 -0
- package/dist/src/worktree-seed.js +35 -2
- package/docs/BACKUP-RETENTION.md +46 -2
- package/docs/CLI.md +12 -5
- package/docs/DEAD-CODE-AND-IMPACT.md +41 -0
- package/docs/MCP.md +15 -3
- package/docs/SALESFORCE-BINDINGS.md +26 -8
- package/docs/releases/0.13.1.md +216 -0
- package/docs/releases/0.14.0.md +78 -0
- package/package.json +4 -1
package/docs/BACKUP-RETENTION.md
CHANGED
|
@@ -5,7 +5,8 @@ Knodin graph promotions leave completed snapshots named
|
|
|
5
5
|
They are promotion snapshots, not a supported restore interface. Malformed and
|
|
6
6
|
legacy names are inventory-only and are never pruning candidates.
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
One-shot pruning is preview-only unless `--apply` is supplied. Inspect one
|
|
9
|
+
checkout or bounded portfolio roots:
|
|
9
10
|
|
|
10
11
|
```bash
|
|
11
12
|
knodin backups list
|
|
@@ -25,6 +26,48 @@ trees. It unions explicit roots with valid absolute checkout paths in
|
|
|
25
26
|
|
|
26
27
|
## Opt-in ongoing retention
|
|
27
28
|
|
|
29
|
+
### Managed storage and legacy consent
|
|
30
|
+
|
|
31
|
+
New successfully indexed stores automatically receive `.knodin/storage-policy.json`
|
|
32
|
+
unless a healthy, applicable bounded global policy already manages that store.
|
|
33
|
+
In that case no local policy file is materialized; `backups policy status` reports
|
|
34
|
+
the effective policy. The local defaults provide:
|
|
35
|
+
one protected recoverable backup, a 1 GiB allocated-backup budget, and a 512 MiB
|
|
36
|
+
free-space reserve. Post-promotion maintenance runs after releasing the operation
|
|
37
|
+
lease. Count/byte quotas override the age window, but never recovery protection.
|
|
38
|
+
If protected data exceeds the quota, Knodin reports it and refuses unsafe further
|
|
39
|
+
candidate allocation; increase the budget or resolve the storage condition.
|
|
40
|
+
|
|
41
|
+
Existing unmanaged graphs require explicit consent:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
knodin backups policy status /path/to/repo --json
|
|
45
|
+
knodin backups policy preview /path/to/repo --json
|
|
46
|
+
knodin backups policy apply /path/to/repo --json
|
|
47
|
+
knodin backups policy apply /path/to/repo --max-count 2 --max-bytes 2147483648
|
|
48
|
+
knodin backups policy apply /path/to/repo --mode preview
|
|
49
|
+
knodin backups policy apply /path/to/repo --mode disabled
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Preview writes nothing and includes the pruning plan and bounded inventory.
|
|
53
|
+
Apply persists consent and runs policy-approved backup maintenance. Omitted
|
|
54
|
+
settings preserve an existing policy, including explicit dry-run. Use
|
|
55
|
+
`--mode enabled` to explicitly return to deleting eligible managed backups.
|
|
56
|
+
`--reserve-bytes` configures free space retained beyond a conservative scratch
|
|
57
|
+
estimate. Unknown capacity/allocated sizes refuse allocations instead of
|
|
58
|
+
guessing zero. The estimate is not a reservation against other writers.
|
|
59
|
+
|
|
60
|
+
Candidate maintenance removes only managed empty or audit-only directories with
|
|
61
|
+
a validated owner marker and confirmed exited owner. Owner-unknown legacy
|
|
62
|
+
directories, live owners, DB-bearing interrupted candidates, symlinks, leases
|
|
63
|
+
and promotion markers are protected. Permission/deletion failures and protected over-budget data are
|
|
64
|
+
visible, not claimed as reclaimed space. Allocated versus apparent totals differ;
|
|
65
|
+
APFS clones can share extents, so allocated-byte sums are not promised physical
|
|
66
|
+
recovery. Source mirrors and external development harness directories are
|
|
67
|
+
separate storage classes, not promotion backups.
|
|
68
|
+
|
|
69
|
+
### Native daily scheduler
|
|
70
|
+
|
|
28
71
|
Installation is the consent boundary:
|
|
29
72
|
|
|
30
73
|
```bash
|
|
@@ -34,7 +77,8 @@ knodin backups retention doctor
|
|
|
34
77
|
knodin backups retention remove
|
|
35
78
|
```
|
|
36
79
|
|
|
37
|
-
Options are `--retention-days` (3), `--keep-newest` (1), `--
|
|
80
|
+
Options are `--retention-days` (3), `--keep-newest` (1), `--max-count` (1),
|
|
81
|
+
`--max-bytes` (1073741824), `--depth` (5),
|
|
38
82
|
`--schedule` (`04:17` local), and `--dry-run`. Installation writes a versioned
|
|
39
83
|
policy to `$XDG_CONFIG_HOME/knodin/backup-retention.json` and owned receipt/run
|
|
40
84
|
state beneath `$XDG_STATE_HOME/knodin/backup-retention/`. Ordinary Knodin use
|
package/docs/CLI.md
CHANGED
|
@@ -37,8 +37,12 @@ knodin update --help
|
|
|
37
37
|
|
|
38
38
|
Backup discovery and pruning are native and cross-platform. `knodin backups
|
|
39
39
|
list` and the default `knodin backups prune` are read-only; deletion requires
|
|
40
|
-
`--apply
|
|
41
|
-
|
|
40
|
+
`--apply`. New successfully indexed stores get bounded post-promotion retention
|
|
41
|
+
(one rollback, 1 GiB allocated-backup budget, 512 MiB free-space reserve).
|
|
42
|
+
Existing stores require `knodin backups policy preview` followed by explicit
|
|
43
|
+
`policy apply`; status/preview expose bounded inventory and exact cleanup plans.
|
|
44
|
+
Native daily scheduling remains opt-in through `knodin backups retention install`.
|
|
45
|
+
See `docs/BACKUP-RETENTION.md` for safety,
|
|
42
46
|
scheduler, logging, and removal details.
|
|
43
47
|
|
|
44
48
|
`repos search` resolves configured system memberships independently for every
|
|
@@ -227,8 +231,8 @@ configuration `consumers_of`. `count` is total observed matching sites,
|
|
|
227
231
|
`files` contains aggregates only for files represented on this page.
|
|
228
232
|
`targetKind` identifies the resolved declaration as `class` or `interface` and is
|
|
229
233
|
preserved on every page. Interface consumers cover supported type-position roles,
|
|
230
|
-
not constructors, static-field reads, `implements`
|
|
231
|
-
runtime dispatch. Query implementation relationships separately.
|
|
234
|
+
not constructors, static-field reads, static-method receivers, `implements`
|
|
235
|
+
relationships, or inferred runtime dispatch. Query implementation relationships separately.
|
|
232
236
|
|
|
233
237
|
Use `--test-scope test|production|all` (default `all`), a canonical repository-relative
|
|
234
238
|
`--path` prefix, and stable `--identity`/`--file` target selectors when needed.
|
|
@@ -240,10 +244,13 @@ A minimum complete site plus qualifications must fit; source fields are never sh
|
|
|
240
244
|
|
|
241
245
|
Sites retain exact spelling, role, source-owner identity when known, and exclusive
|
|
242
246
|
end positions: one-based lines/UTF-16 columns and zero-based UTF-8 byte offsets.
|
|
243
|
-
The target's own file is excluded.
|
|
247
|
+
The target's own file is excluded. Supported syntax roles include `instanceof`
|
|
248
|
+
types and explicit static-method receivers, but do not cover every
|
|
244
249
|
Apex use, metadata relationship, or runtime path. Read `classConsumerAnalysis` and
|
|
245
250
|
`indexCoverage` before interpreting a negative; missing/invalid descriptors and
|
|
246
251
|
unresolved uses remain qualified, not proof that a class is unused.
|
|
252
|
+
Legacy descriptors without receiver or `instanceof` capability require
|
|
253
|
+
`knodin repair` to re-extract affected files within the declared index scope.
|
|
247
254
|
An indexed retained interface declaration without a safely matching interface
|
|
248
255
|
symbol returns `CLASS_CONSUMER_TARGET_CAPABILITY_MISSING`, `targetResolution: capability-missing`,
|
|
249
256
|
and a nonzero exit—not a successful zero or a fabricated identity. Follow the
|
|
@@ -6,6 +6,47 @@ reference. It does not prove that reflection, runtime dependency injection,
|
|
|
6
6
|
framework configuration, metadata, deployed infrastructure, or external
|
|
7
7
|
consumers cannot invoke the code.
|
|
8
8
|
|
|
9
|
+
For Apex, `dead_code` can also report connected methods with
|
|
10
|
+
`candidateReason: "unrooted-chain"`: no modeled root reaches that chain in
|
|
11
|
+
the indexed inventory, even though its methods reference one another.
|
|
12
|
+
`deadCodeAnalysis.rootReachability` records the model, counts, limitations,
|
|
13
|
+
stable chain identities, method membership, structural owners and call edges.
|
|
14
|
+
Owner membership is not a finding that the entire class is unused.
|
|
15
|
+
|
|
16
|
+
Completeness has two separate scopes. `deadCodeAnalysis.partial`, labeled
|
|
17
|
+
`partialScope: "apex-platform-declarations"`, reports unsupported or missing
|
|
18
|
+
Apex declaration capabilities. It does not certify complete call resolution.
|
|
19
|
+
`deadCodeAnalysis.rootReachability.partial` independently reports uncertainty
|
|
20
|
+
in the indexed root/call analysis. Complete declaration coverage can therefore
|
|
21
|
+
coexist with partial root reachability; inspect both before interpreting results.
|
|
22
|
+
|
|
23
|
+
`deadCodeAnalysis.platformEntries` separately describes matching indexed
|
|
24
|
+
org-invokable declarations. It does not add them to candidate `results` or
|
|
25
|
+
change the candidate `count`. Returned entries include identity, location and
|
|
26
|
+
source-verified `platformEntry` evidence, or an explicit unavailable reason.
|
|
27
|
+
The classification total is not a verified-proof count or evidence of runtime use.
|
|
28
|
+
|
|
29
|
+
This collection is a bounded preview: at most 25 entries, further limited by
|
|
30
|
+
the query limit, with at most eight source-file verification attempts and a
|
|
31
|
+
1 MiB bound per file. Each selected file is verified once per request. Counts
|
|
32
|
+
separate verified, unavailable and omitted entries; `truncated`/`partial` and
|
|
33
|
+
omission reasons disclose incomplete delivery. There is no collection cursor:
|
|
34
|
+
narrow the path or use identity-qualified `explain` for a specific declaration.
|
|
35
|
+
Response budgets preserve the returned collection or fail explicitly.
|
|
36
|
+
|
|
37
|
+
An org-invokable declaration may also have static callers, including Flow
|
|
38
|
+
metadata. These tags do not assert no static callers and do not replace
|
|
39
|
+
`callers_of` evidence. `runtimeInvocation: "not-established"` remains explicit.
|
|
40
|
+
|
|
41
|
+
The analysis considers platform declarations, triggers, test declarations and
|
|
42
|
+
supported metadata boundaries before filtering the requested output paths.
|
|
43
|
+
Possible local calls conservatively protect reachable targets; unresolved
|
|
44
|
+
reflection, missing provenance and bounded-inventory omissions remain qualified.
|
|
45
|
+
An omitted candidate is not proof of runtime use. Root reachability is scoped
|
|
46
|
+
to indexed source, with `runtimeInvocation: "not-established"` and
|
|
47
|
+
`safeToDelete: false`. Response budgets preserve the root-analysis contract or
|
|
48
|
+
fail explicitly when it cannot fit; narrow the request or increase its budget.
|
|
49
|
+
|
|
9
50
|
Impact follows source-evidenced resolved relationships. High-confidence
|
|
10
51
|
incoming cross-repository relationships can make a dependency visible to
|
|
11
52
|
impact and dead-code analysis. Heuristic or unresolved relationships lower
|
package/docs/MCP.md
CHANGED
|
@@ -4,6 +4,14 @@ 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
|
+
Indexing and repair use the same storage-capacity and managed-retention guards
|
|
8
|
+
as the CLI. Low or unknown capacity refuses scratch allocation without replacing
|
|
9
|
+
the active graph. Maintenance warnings go to stderr, not the stdio JSON protocol.
|
|
10
|
+
Repository storage-policy consent and inventory are CLI administrative commands:
|
|
11
|
+
`knodin backups policy status|preview|apply /path/to/repo --json`.
|
|
12
|
+
Existing unmanaged stores do not gain destructive cleanup through an MCP read.
|
|
13
|
+
See `docs/BACKUP-RETENTION.md` for limits, migration and recovery protection.
|
|
14
|
+
|
|
7
15
|
Shared-index support also stays inside that one gateway. Status, context,
|
|
8
16
|
query, explain, review, map, and search responses include a bounded
|
|
9
17
|
`sharedIndex` provenance object. `source: "shared-snapshot"` identifies origin;
|
|
@@ -229,8 +237,9 @@ and `limit` (1–1000 sites). This is separate from method calls and Java config
|
|
|
229
237
|
and `returnedCount` counts delivered sites; page-local `files` aggregates do not
|
|
230
238
|
enumerate every matching file until paging is complete.
|
|
231
239
|
The protected `targetKind` is `class` or `interface`. Interface targets admit
|
|
232
|
-
supported type-position roles, not constructor/static-field
|
|
233
|
-
relationships and concrete runtime
|
|
240
|
+
supported type-position roles, including `instanceof`, not constructor/static-field
|
|
241
|
+
or static-method-receiver uses. `implements` relationships and concrete runtime
|
|
242
|
+
dispatch are not typed consumer sites.
|
|
234
243
|
|
|
235
244
|
Use the returned `continuation` with the same target and filters. Byte/token/item
|
|
236
245
|
budgets may vary. The signed token is interchangeable with CLI `--continuation`
|
|
@@ -239,10 +248,13 @@ qualifications fit before the cursor is signed; no generic truncation follows.
|
|
|
239
248
|
An extra limit-one backend read currently revalidates the snapshot before delivery;
|
|
240
249
|
this correctness guard is not a claim of optimized paging cost.
|
|
241
250
|
|
|
242
|
-
|
|
251
|
+
Supported Apex roles include explicit static-method receivers and `instanceof`
|
|
252
|
+
types, exclude target-self-file sites and do not establish
|
|
243
253
|
complete class-use or runtime reachability. `classConsumerAnalysis` reports partial
|
|
244
254
|
extraction and indexed-inventory counters, separately from `indexCoverage`. Unknown
|
|
245
255
|
targets and ambiguity are unavailable, never successful zero-site answers.
|
|
256
|
+
Legacy descriptors without receiver or `instanceof` capability remain partial;
|
|
257
|
+
follow the scope-preserving `knodin repair` guidance to re-extract them.
|
|
246
258
|
`CLASS_CONSUMER_TARGET_CAPABILITY_MISSING` with `targetResolution: "capability-missing"`
|
|
247
259
|
means retained indexed interface evidence exists but its symbol capability is
|
|
248
260
|
missing. It is unavailable without a fabricated target identity or zero count;
|
|
@@ -106,16 +106,34 @@ and [dynamic picklist configuration guide](https://developer.salesforce.com/docs
|
|
|
106
106
|
|
|
107
107
|
## Apex class-use sites are a separate query
|
|
108
108
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
109
|
+
For a selected Apex platform entry declaration, `explain` also exposes
|
|
110
|
+
`platformEntry`: the declared contract, reason, source hash and exact declaration
|
|
111
|
+
and owner spans. `runtimeInvocation: "not-established"` is intentional: a
|
|
112
|
+
Batchable, Queueable or other platform-facing declaration does not prove that
|
|
113
|
+
an org invokes it. Missing or mismatched declaration evidence is explicitly
|
|
114
|
+
unavailable, not a positive entry classification. Ordinary helper declarations
|
|
115
|
+
do not gain a platform-entry label merely from global visibility.
|
|
116
|
+
|
|
117
|
+
This evidence is separate from class-use sites and dead-code candidate filtering.
|
|
118
|
+
CLI/MCP source and compact modes retain the qualification; a budget too small
|
|
119
|
+
for the complete platform-entry field fails explicitly rather than dropping it.
|
|
120
|
+
|
|
121
|
+
`query class_consumers` exposes static-field reads, static-method receivers,
|
|
122
|
+
constructors, variable types, casts, `instanceof` types, class literals,
|
|
123
|
+
parameter types, generic parameter types, loop-variable types, and generic type
|
|
124
|
+
arguments. It does not widen metadata bindings or method
|
|
112
125
|
call edges. Case-insensitive type resolution requires unique declarations and
|
|
113
|
-
validated owner chains
|
|
114
|
-
catalog entries cannot become confident class matches.
|
|
126
|
+
validated owner chains. Relevant lexical shadows, malformed source and ambiguous
|
|
127
|
+
catalog entries cannot become confident class matches. A value-name shadow does
|
|
128
|
+
not hide an explicit `instanceof` RHS type.
|
|
115
129
|
|
|
116
130
|
Results exclude the target's own source file and include test files by default.
|
|
117
131
|
Missing descriptors, unresolved uses and unsupported forms qualify the observed
|
|
118
|
-
counts.
|
|
119
|
-
|
|
120
|
-
|
|
132
|
+
counts. Method receivers require a unique same-owner method name and arity
|
|
133
|
+
before the static modifier is accepted; same-arity overloads remain ambiguous.
|
|
134
|
+
Return types, inheritance and writes are not promoted into these roles.
|
|
135
|
+
Legacy descriptors without receiver or `instanceof` capability remain partial;
|
|
136
|
+
run `knodin repair` to re-extract affected files within the declared index scope.
|
|
137
|
+
These source-evidenced sites are not complete Apex usage enumeration or runtime
|
|
138
|
+
reachability proof. See the CLI/MCP paging
|
|
121
139
|
sections for signed continuations and exact site-position conventions.
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# knodin 0.13.1
|
|
2
|
+
|
|
3
|
+
Compatible patch release for KNODIN-47 and KNODIN-48: correct false stale
|
|
4
|
+
evidence after repair and bound managed graph storage.
|
|
5
|
+
|
|
6
|
+
## Fixed
|
|
7
|
+
|
|
8
|
+
- Align freshness probes with source-indexing eligibility. Non-source files and
|
|
9
|
+
collapsed untracked directories no longer make an unchanged, repaired graph
|
|
10
|
+
appear stale.
|
|
11
|
+
- Preserve exact Git paths, including renames and names containing whitespace,
|
|
12
|
+
and exclude canonical pruned trees before expanding untracked files.
|
|
13
|
+
- Track relevant `.gitignore` rules, including tracked policy files omitted by
|
|
14
|
+
Git's stat cache, Git's local exclude file, and its
|
|
15
|
+
effective global exclude file with bounded reads. Retain previously indexed
|
|
16
|
+
paths for deletion detection and respect scoped-index path safety.
|
|
17
|
+
- Encode dirty path sets without newline collisions. Failed Git or ignore-policy
|
|
18
|
+
checks remain unknown, including Git checkouts without their first commit.
|
|
19
|
+
- Reindex relevant dirty or committed-diff source before accepting a repaired
|
|
20
|
+
baseline, so restored file sizes and timestamps cannot hide source changes.
|
|
21
|
+
Repair's initial audit also checks change times against the completed source snapshot,
|
|
22
|
+
covering source edits omitted by Git's stat-cache shortcuts.
|
|
23
|
+
Verify source and Git stability before publishing the baseline; unresolved
|
|
24
|
+
historical evidence requires explicit recovery rather than a false success.
|
|
25
|
+
- Preserve first-time repair of an empty graph while refusing to guess missing
|
|
26
|
+
history or refresh timestamps for an existing graph.
|
|
27
|
+
- Preserve completed-file resume behavior in direct-engine repairs with content
|
|
28
|
+
proofs that are invalidated by later index writes. Public repair retains its
|
|
29
|
+
atomic candidate cancellation behavior.
|
|
30
|
+
- Separate repair's content-proof epoch from ordinary reconciliation timestamps.
|
|
31
|
+
Existing non-empty Git graphs need a one-time `knodin index --clean` before
|
|
32
|
+
this versioned proof is established. Status, query freshness, and repair
|
|
33
|
+
refuse to certify missing, malformed, or future-dated provenance rather than
|
|
34
|
+
trusting a legacy timestamp.
|
|
35
|
+
- Force-reindex paths that Git reports changed, even when size and timestamp
|
|
36
|
+
match the indexed tuple, so ordinary reconciliation cannot retain old symbols.
|
|
37
|
+
- Establish Knodin's existing repository-local state exclusion before candidate
|
|
38
|
+
indexing and repair record their policy baseline.
|
|
39
|
+
- Accept the platform null device as an empty global Git exclude policy, and
|
|
40
|
+
retain the documented bounded stat fallback for verified nested Git paths.
|
|
41
|
+
- Bound new manifest eligibility reads together with ignore-policy reads. When
|
|
42
|
+
the freshness budget is exceeded, report unknown; explicitly index a large
|
|
43
|
+
new manifest before relying on automatic freshness for it.
|
|
44
|
+
- Revalidate already-dirty source content with a bounded proof (at most 256
|
|
45
|
+
paths and 1 MiB per probe). Over-budget content or unreliable Git stat settings
|
|
46
|
+
remain unknown on the cheap freshness path. A complete deep audit can verify
|
|
47
|
+
the retained source snapshot; unknown is not evidence that nothing changed.
|
|
48
|
+
- Validate clean-build resume provenance strictly, preserve the original HEAD,
|
|
49
|
+
recheck equal-stat source edits, and remove deleted paths before promotion.
|
|
50
|
+
Source/Git changes during clean indexing or final promotion refuse publication
|
|
51
|
+
of the candidate rather than minting a proof over a mixed snapshot.
|
|
52
|
+
- Preserve verified parsed-source proofs when seeding an unchanged linked
|
|
53
|
+
worktree. Missing, malformed, or mismatched copied proofs require extraction;
|
|
54
|
+
omitted equal-stat source edits cannot retain stale sibling symbols.
|
|
55
|
+
- Reuse scoped, canonically pruned Git enumeration for cold reconciliation,
|
|
56
|
+
including unborn repositories. Failed or over-budget working-tree/commit-diff
|
|
57
|
+
enumeration cannot advance the stored HEAD or freshness baseline. Missing
|
|
58
|
+
shallow/foreign commit history requires explicit clean-index recovery rather
|
|
59
|
+
than a stat-only fallback that misses equal-stat source edits.
|
|
60
|
+
- Withhold a first scoped content-proof epoch after unhealthy verification or
|
|
61
|
+
an exception, including failures after the deep audit completes. Existing
|
|
62
|
+
verified epochs are not deleted by failed scope widening.
|
|
63
|
+
- Preserve structural revisions and Apex consumer paging snapshots across
|
|
64
|
+
unchanged cold opens, including unborn Git repositories. Canonical discovery
|
|
65
|
+
and relationship/semantic maintenance always run; only unchanged file
|
|
66
|
+
extraction is skipped using an exact retained parsed-source proof. Missing,
|
|
67
|
+
malformed, or changed per-file evidence forces extraction. The extraction
|
|
68
|
+
fence also retains proof before a repository epoch exists, using bounded-memory
|
|
69
|
+
streaming reads before and after parsing (additional source I/O, not a measured
|
|
70
|
+
performance gain). Failed extraction cannot publish a new per-file proof;
|
|
71
|
+
aggregate completion still requires healthy verification.
|
|
72
|
+
Worker-queued inputs also retain pre/post-parse source fences; per-queued-file
|
|
73
|
+
metadata scales with the source inventory, while streaming uses a 64 KiB read
|
|
74
|
+
buffer. Successful batched writes retain their parsed proofs; rolled-back
|
|
75
|
+
file writes cannot regain a proof at the batch boundary.
|
|
76
|
+
Stable unparsed/skipped source reads also retain their consumed-source proof
|
|
77
|
+
after pre/post-read verification; extraction and database-write errors do not.
|
|
78
|
+
Batch write failures retain successful per-file work but refuse aggregate
|
|
79
|
+
completion before publishing an epoch or baseline; resolve the write error
|
|
80
|
+
and retry indexing. A failed candidate is not promoted over the active graph.
|
|
81
|
+
|
|
82
|
+
## Storage stewardship (KNODIN-48)
|
|
83
|
+
|
|
84
|
+
New successfully indexed stores receive a repository-local storage policy:
|
|
85
|
+
one recoverable promotion backup, a 1 GiB allocated-backup budget, and a
|
|
86
|
+
512 MiB free-space reserve. Count/byte budgets override the age grace period.
|
|
87
|
+
Cleanup runs after durable promotion and operation-lease release; cleanup
|
|
88
|
+
failures are reported without rolling back the committed graph. The newest
|
|
89
|
+
snapshot and an integrity-checked rollback remain protected, even when that
|
|
90
|
+
requires reporting an over-budget condition instead of deleting recovery data.
|
|
91
|
+
|
|
92
|
+
Existing unmanaged stores are not silently migrated. Run
|
|
93
|
+
`knodin backups policy preview /path/to/repo --json`, inspect exact candidates,
|
|
94
|
+
then `knodin backups policy apply /path/to/repo --json` to consent. Existing
|
|
95
|
+
explicit dry-run/disabled policies remain respected. Configure limits with
|
|
96
|
+
`--max-count`, `--max-bytes`, and `--reserve-bytes`; `--mode preview` or
|
|
97
|
+
`--mode disabled` records the corresponding maintenance choice.
|
|
98
|
+
|
|
99
|
+
Automatic cleanup rechecks effective policy under its lease before deletion.
|
|
100
|
+
New-store initialization eligibility is durably recorded in the graph before
|
|
101
|
+
publication and survives later clean replacement if policy publication fails;
|
|
102
|
+
successful initialization clears it, so deliberate policy removal stays unmanaged.
|
|
103
|
+
Clearing this internal marker preserves an already validated graph audit and its
|
|
104
|
+
original timestamp across clean close/reopen; concurrent database changes refuse
|
|
105
|
+
audit carry-forward rather than being labeled as previously verified.
|
|
106
|
+
Policy reads use the shared external-state resolver for registered mirrors;
|
|
107
|
+
policy initialization, apply, and automatic cleanup refuse mirror source writes,
|
|
108
|
+
including source aliases. Unsupported Windows directory syncing does not turn
|
|
109
|
+
an already file-synced policy publication into failure; other I/O errors remain visible.
|
|
110
|
+
|
|
111
|
+
Candidate creation and repair's VACUUM preflight require conservatively
|
|
112
|
+
estimated scratch space plus the reserve. Unknown capacity or allocated-size
|
|
113
|
+
measurements fail closed before allocating scratch. This is an estimate, not
|
|
114
|
+
a disk reservation; ENOSPC and concurrent writers can still cause refusal.
|
|
115
|
+
Bounded candidate sweeping removes only managed empty/audit-only residue with
|
|
116
|
+
a validated marker and confirmed exited owner. Unknown legacy owners and
|
|
117
|
+
DB-bearing resumable candidates are preserved. Inventory distinguishes apparent from
|
|
118
|
+
allocated bytes; APFS shared extents mean allocated totals are not guaranteed
|
|
119
|
+
physical reclamation. External source mirrors and development acceptance
|
|
120
|
+
directories are not graph backups and are not blanket-deleted by this policy.
|
|
121
|
+
Candidate allocation revalidates the managed root and new directory before any
|
|
122
|
+
owner or database write. JSON-manifest eligibility uses a no-follow descriptor
|
|
123
|
+
with final pathname identity checks. Shared-index restore always releases its
|
|
124
|
+
lifecycle lease and invokes post-promotion storage finalization even when cache
|
|
125
|
+
lease release or candidate cleanup fails.
|
|
126
|
+
|
|
127
|
+
The release auto-merge dispatch retains exact-SHA, unresolved-conversation,
|
|
128
|
+
local final-gate, approval, and atomic-merge protections when Copilot review is
|
|
129
|
+
unavailable because its AI-credit budget is exhausted. The explicit fallback
|
|
130
|
+
reason is opt-in; ordinary dispatches still require a clean exact-head review.
|
|
131
|
+
The exhausted-credit path also covers a new PR for which Copilot cannot create
|
|
132
|
+
any review object; an exact-head review containing findings still blocks merge.
|
|
133
|
+
The dispatch runs on the organization's approved self-hosted Linux pool so IP
|
|
134
|
+
allow-list enforcement does not prevent it from reading or merging its own PR.
|
|
135
|
+
The tagged release verifier allows 45 minutes for the same full-suite workload,
|
|
136
|
+
preventing a successful test run from being cancelled by the former 30-minute cap.
|
|
137
|
+
|
|
138
|
+
## Release verification
|
|
139
|
+
|
|
140
|
+
Release-candidate pushes run full coverage without repeatedly scanning Sonar. After the current
|
|
141
|
+
PR head has completed review, maintainers run `npm run release:verify` locally; it runs full
|
|
142
|
+
coverage and the local Sonar quality gate, refuses a dirty tracked tree or remote-head mismatch,
|
|
143
|
+
and records the exact verified SHA in Git-local metadata. Any later commit invalidates that result.
|
|
144
|
+
The gate also refuses branch changes and ambiguous remote references. Isolated
|
|
145
|
+
subprocess regressions cover preflight refusals, verification failures, SHA drift,
|
|
146
|
+
and the evidence payload without invoking real scans.
|
|
147
|
+
|
|
148
|
+
Ordinary PR pushes no longer enable auto-merge. Maintainers explicitly dispatch
|
|
149
|
+
the auto-merge workflow with the PR number and exact SHA only after independently
|
|
150
|
+
verifying clean current-head review and successful local final-gate evidence.
|
|
151
|
+
The dispatch checks the live open PR head; it does not authenticate local evidence
|
|
152
|
+
or replace protected-branch checks.
|
|
153
|
+
|
|
154
|
+
Regression coverage includes repeated cold status checks after repair, genuine
|
|
155
|
+
source edits, ignore-policy changes, scoped paths, symlinks, JSON eligibility,
|
|
156
|
+
and unusual filenames. A freshness-only development build was also verified
|
|
157
|
+
against SalesforceCI's approximately 903,000-file graph: repair completed, then
|
|
158
|
+
two separate-process status checks reported healthy and fresh without changing
|
|
159
|
+
repository source files or existing working-tree edits.
|
|
160
|
+
|
|
161
|
+
That acceptance establishes the reported repair/status defect, not a complete
|
|
162
|
+
cross-repository init/repair/status certification or a general performance gain.
|
|
163
|
+
Real source changes still require graph refresh. After upgrading an affected
|
|
164
|
+
checkout, run `knodin repair`. If it reports that content provenance is missing,
|
|
165
|
+
run the requested one-time `knodin index --clean`; then run `knodin status`.
|
|
166
|
+
|
|
167
|
+
## Additional review safety fixes
|
|
168
|
+
|
|
169
|
+
Already-dirty source proofs reject symlinked paths and recheck held-file identity
|
|
170
|
+
and change time; an unverifiable path reports unknown rather than false freshness.
|
|
171
|
+
Candidate reads and promotion fences retain no-follow descriptor evidence.
|
|
172
|
+
Interrupted candidates with unknown/live owners or nonselected databases are
|
|
173
|
+
preserved rather than recursively discarded. Failed promotion rollback preserves
|
|
174
|
+
uncertain files and a repair-needed marker for manual inspection instead of
|
|
175
|
+
automatically accepting a substituted graph. These are boundary checks, not an
|
|
176
|
+
atomic filesystem reservation against concurrent pathname changes.
|
|
177
|
+
|
|
178
|
+
Mirror identities use the generated `repo_<20 hexadecimal characters>` format.
|
|
179
|
+
Malformed/unreadable registries fail closed; registry writes reject unsafe targets
|
|
180
|
+
and publish through an exclusive temporary file. Managed staging/source guards
|
|
181
|
+
refuse symlink escapes and reject an unrelated clone path before it can be cached
|
|
182
|
+
as that mirror. Canonical aliases remain supported, and a missing clone remains
|
|
183
|
+
registered only at its deterministic managed path. Mirror indexing keeps graph
|
|
184
|
+
state out of source but does not opt read-only mirrors into managed backup-policy
|
|
185
|
+
initialization or report that intentional omission as failed maintenance.
|
|
186
|
+
Duplicate mirror identities or canonical clone paths are rejected before routing.
|
|
187
|
+
Owner-proven audit-only
|
|
188
|
+
quarantines remain discoverable and retryable after cleanup failure; unknown or
|
|
189
|
+
database-bearing quarantines remain preserved.
|
|
190
|
+
|
|
191
|
+
The local final gate uses the existing npm coverage command without requiring Bun.
|
|
192
|
+
The privileged merge action is pinned to an immutable upstream commit.
|
|
193
|
+
|
|
194
|
+
Repair snapshot proofs now use component-wise no-follow source checks and bind
|
|
195
|
+
the opened descriptor to the final pathname across the complete read. Storage
|
|
196
|
+
policy reads similarly reject atomic pathname replacement, and applied policy
|
|
197
|
+
changes share the cleanup lifecycle lease so deletion cannot continue under
|
|
198
|
+
superseded consent.
|
|
199
|
+
|
|
200
|
+
Opportunistic global retention respects configured roots and depth and revalidates
|
|
201
|
+
installed consent under its deletion lease. Direct candidate cleanup refuses
|
|
202
|
+
read-only mirrors. Seeded worktree promotions run the same post-audit storage
|
|
203
|
+
finalizer, with durable retry after policy publication failure. Read-only mirror
|
|
204
|
+
inventory measures exact backups in resolved external state, not source decoys.
|
|
205
|
+
|
|
206
|
+
Global policy resolution and opportunistic retention share the same bounded scope
|
|
207
|
+
check; scheduled and opportunistic deletion share lease-time consent validation.
|
|
208
|
+
Mirror aliases resolve through one canonical identity seam. Mirror allocation
|
|
209
|
+
previews external backup quotas, while deletion remains refused. Any skipped or
|
|
210
|
+
unverified rollback inventory blocks managed allocation. Failed policy writes
|
|
211
|
+
clean their unpublished temporary files. A healthy applicable bounded global
|
|
212
|
+
policy can manage a new store without materializing a local policy file.
|
|
213
|
+
Shared-index restores and committed worktree seeds now finalize pending storage
|
|
214
|
+
policy and maintenance after promotion, including a failed post-promotion status
|
|
215
|
+
check. Release dispatch uses GitHub's exact-SHA merge precondition rather than
|
|
216
|
+
arming unbound auto-merge; a changed head requires fresh review and verification.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# knodin 0.14.0
|
|
2
|
+
|
|
3
|
+
Minor release for KNODIN-47, KNODIN-49, and KNODIN-50: Salesforce evidence for
|
|
4
|
+
static-method receivers, `instanceof` checks, platform entry points, and
|
|
5
|
+
unrooted Apex chains; and a corrected upgrade path for graphs indexed before
|
|
6
|
+
0.13.1, whose lifecycle hooks reported success while the graph fell behind.
|
|
7
|
+
|
|
8
|
+
Pre-1.0 minor: the `class_consumers` binding version advances and the lifecycle
|
|
9
|
+
hook now exits non-zero on a graph the audit refuses to certify. No stored graph
|
|
10
|
+
is rewritten without an explicit `init` or `index --clean`.
|
|
11
|
+
|
|
12
|
+
## Upgrade note for graphs built before 0.13.1
|
|
13
|
+
|
|
14
|
+
0.13.1 introduced a versioned content-proof epoch and required a one-time
|
|
15
|
+
`knodin index --clean` for existing non-empty graphs, but nothing performed or
|
|
16
|
+
enforced it. On such a graph the background hook indexed the changed paths,
|
|
17
|
+
saw the audit refuse to certify the result, and still logged the paths and
|
|
18
|
+
exited 0. `status` reported lifecycle healthy with no last error while the
|
|
19
|
+
indexed HEAD sat dozens of commits behind. Observed on a real checkout: 33
|
|
20
|
+
commits behind, two days after the upgrade.
|
|
21
|
+
|
|
22
|
+
In 0.14.0:
|
|
23
|
+
|
|
24
|
+
- `knodin init` detects the missing epoch and runs the clean index itself, then
|
|
25
|
+
verifies health. Run it once per affected checkout; no other step is needed.
|
|
26
|
+
- The lifecycle hook does not migrate on its own. It fails with the audit's
|
|
27
|
+
first finding and remedy, records the cause in
|
|
28
|
+
`.knodin/hooks/last-refresh-failure`, and `knodin status` reports lifecycle
|
|
29
|
+
degraded with that error until `init` or `index --clean` runs. A hook on a
|
|
30
|
+
healthy graph is unchanged and its JSON result now includes `verification`.
|
|
31
|
+
- `status`, `repair`, `index`, and `init` print the audit's own first repair
|
|
32
|
+
step. Previously all three hardcoded `Run knodin repair`, which cannot fix
|
|
33
|
+
this condition; on the observed checkout the user was bounced
|
|
34
|
+
`status → repair → status` with an unchanged graph before finding
|
|
35
|
+
`index --clean` at the bottom of an unrelated error dump.
|
|
36
|
+
- `repair` says "Repair made no changes" when it repaired nothing and the
|
|
37
|
+
before/after audit counts are equal, instead of reading as progress.
|
|
38
|
+
- Each `.knodin/indexer.log` record carries `at` (UTC) and `event` (kind,
|
|
39
|
+
before/after commits, queued `sequence`), so a refresh can be tied to the Git
|
|
40
|
+
event that queued it. Lines remain one JSON object each.
|
|
41
|
+
- `IndexResult.verification` carries `repairSteps` for `--json` and MCP
|
|
42
|
+
consumers.
|
|
43
|
+
|
|
44
|
+
## Salesforce evidence (KNODIN-47)
|
|
45
|
+
|
|
46
|
+
- `class_consumers` adds two roles: `static_method_receiver`, bound to the
|
|
47
|
+
receiving class with method arity, and `instanceof_type`. The binding
|
|
48
|
+
version advances from `2-interface-types` to `4-instanceof-types`. Graphs
|
|
49
|
+
materialized under the older binding report these roles as a repair
|
|
50
|
+
limitation instead of silently under-reporting them.
|
|
51
|
+
- The class-consumer catalog memo is deflate-packed, removing the 8 MiB cache
|
|
52
|
+
cliff that evicted large orgs, and the materialization digest seeks by bare
|
|
53
|
+
tuple.
|
|
54
|
+
- `explain` carries source-verified `platformEntry` evidence for Apex REST,
|
|
55
|
+
Flow, and platform contracts, and `dead_code` carries a bounded
|
|
56
|
+
`deadCodeAnalysis.platformEntries` collection (capped at 25 previews
|
|
57
|
+
independently of candidate pagination). Sealed artifacts read source through
|
|
58
|
+
a bounded, integrity-checked path; compact `explain` refuses a budget that
|
|
59
|
+
cannot hold the entry rather than dropping it.
|
|
60
|
+
- `dead_code` reports Apex method chains with no reachable root as candidates
|
|
61
|
+
with `candidateReason: "unrooted-chain"`, `chainIdentity`, and
|
|
62
|
+
`deadCodeAnalysis.rootReachability`. Response budgets protect these fields.
|
|
63
|
+
- Known gap: C2 REST acceptance is not green on the vendored Apex grammar
|
|
64
|
+
(lowercase `boolean.` parse-partial). Recorded in
|
|
65
|
+
`benchmarks/evaluations/knodin-41-outcomes/C2-ENTRY-EXPLANATION-ACCEPTANCE.md`.
|
|
66
|
+
|
|
67
|
+
## Release verification
|
|
68
|
+
|
|
69
|
+
Both branches passed the full 16-shard suite locally before merge. New
|
|
70
|
+
regressions in `legacy-epoch-migration.spec.ts` fabricate a 0.13.0-shaped graph
|
|
71
|
+
(non-empty `index_state`, no `contentProofEpochV1`) and exercise the real CLI:
|
|
72
|
+
scoped indexing refuses and explains, `hook-refresh` exits non-zero with the
|
|
73
|
+
remedy, the healthy hook path still advances HEAD, `init` migrates, and
|
|
74
|
+
`status`/`repair` agree on the issue count for the unchanged graph.
|
|
75
|
+
|
|
76
|
+
After upgrading an affected checkout, run `knodin init`; then `knodin status`
|
|
77
|
+
should report healthy and fresh. `knodin index --clean` remains available as the
|
|
78
|
+
explicit equivalent.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "knodin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"knodin": {
|
|
5
5
|
"compatibility": "breaking"
|
|
6
6
|
},
|
|
@@ -73,6 +73,8 @@
|
|
|
73
73
|
"docs/releases/0.12.1.md",
|
|
74
74
|
"docs/releases/0.12.2.md",
|
|
75
75
|
"docs/releases/0.13.0.md",
|
|
76
|
+
"docs/releases/0.13.1.md",
|
|
77
|
+
"docs/releases/0.14.0.md",
|
|
76
78
|
"docs/releases/0.3.0.md",
|
|
77
79
|
"docs/releases/0.4.0.md",
|
|
78
80
|
"docs/releases/0.4.1.md",
|
|
@@ -121,6 +123,7 @@
|
|
|
121
123
|
"test:watch": "vitest --watch",
|
|
122
124
|
"test:coverage": "tsx scripts/run-vitest-shards.ts --coverage",
|
|
123
125
|
"scan:sonar": "npm run test:coverage && sh scripts/run-sonar-scan.sh",
|
|
126
|
+
"release:verify": "tsx scripts/release-final-gate.ts",
|
|
124
127
|
"mirror:sync": "sh tools/hooks/sync-ghes-mirror.sh",
|
|
125
128
|
"test:pack-install": "tsx scripts/pack-install-smoke.ts",
|
|
126
129
|
"test:package-managers": "tsx scripts/package-manager-smoke.ts",
|