@descryy/core 0.4.0 → 0.5.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/budget/reply.d.ts +11 -46
- package/dist/budget/reply.d.ts.map +1 -1
- package/dist/budget/reply.js +10 -39
- package/dist/budget/reply.js.map +1 -1
- package/dist/budget/size.d.ts +2 -21
- package/dist/budget/size.d.ts.map +1 -1
- package/dist/budget/size.js +3 -24
- package/dist/budget/size.js.map +1 -1
- package/dist/capabilities/preconditions.d.ts +7 -68
- package/dist/capabilities/preconditions.d.ts.map +1 -1
- package/dist/capabilities/preconditions.js +6 -57
- package/dist/capabilities/preconditions.js.map +1 -1
- package/dist/contracts/engine.d.ts +23 -11
- package/dist/contracts/engine.d.ts.map +1 -1
- package/dist/contracts/engine.js +23 -11
- package/dist/contracts/engine.js.map +1 -1
- package/dist/contracts/orphans.d.ts +18 -122
- package/dist/contracts/orphans.d.ts.map +1 -1
- package/dist/contracts/orphans.js +36 -134
- package/dist/contracts/orphans.js.map +1 -1
- package/dist/contracts/paths.d.ts +4 -114
- package/dist/contracts/paths.d.ts.map +1 -1
- package/dist/contracts/paths.js +7 -140
- package/dist/contracts/paths.js.map +1 -1
- package/dist/contracts/shapes.d.ts +13 -66
- package/dist/contracts/shapes.d.ts.map +1 -1
- package/dist/contracts/shapes.js +20 -91
- package/dist/contracts/shapes.js.map +1 -1
- package/dist/governance/budget.d.ts +12 -48
- package/dist/governance/budget.d.ts.map +1 -1
- package/dist/governance/budget.js +12 -48
- package/dist/governance/budget.js.map +1 -1
- package/dist/governance/candidate-boundary.d.ts +4 -32
- package/dist/governance/candidate-boundary.d.ts.map +1 -1
- package/dist/governance/candidate-boundary.js +4 -32
- package/dist/governance/candidate-boundary.js.map +1 -1
- package/dist/governance/escalation.d.ts +7 -45
- package/dist/governance/escalation.d.ts.map +1 -1
- package/dist/governance/escalation.js +7 -45
- package/dist/governance/escalation.js.map +1 -1
- package/dist/governance/fact-boundary.d.ts +7 -49
- package/dist/governance/fact-boundary.d.ts.map +1 -1
- package/dist/governance/fact-boundary.js +5 -43
- package/dist/governance/fact-boundary.js.map +1 -1
- package/dist/governance/finding-funnel.d.ts +11 -72
- package/dist/governance/finding-funnel.d.ts.map +1 -1
- package/dist/governance/finding-funnel.js +9 -68
- package/dist/governance/finding-funnel.js.map +1 -1
- package/dist/graph/build.d.ts +9 -90
- package/dist/graph/build.d.ts.map +1 -1
- package/dist/graph/build.js +15 -62
- package/dist/graph/build.js.map +1 -1
- package/dist/graph/cross-language.d.ts +4 -43
- package/dist/graph/cross-language.d.ts.map +1 -1
- package/dist/graph/cross-language.js +9 -77
- package/dist/graph/cross-language.js.map +1 -1
- package/dist/graph/merge.d.ts +8 -88
- package/dist/graph/merge.d.ts.map +1 -1
- package/dist/graph/merge.js +9 -93
- package/dist/graph/merge.js.map +1 -1
- package/dist/graph/observed-tests.d.ts +7 -68
- package/dist/graph/observed-tests.d.ts.map +1 -1
- package/dist/graph/observed-tests.js +5 -60
- package/dist/graph/observed-tests.js.map +1 -1
- package/dist/graph/persist.d.ts +2 -25
- package/dist/graph/persist.d.ts.map +1 -1
- package/dist/graph/persist.js +2 -25
- package/dist/graph/persist.js.map +1 -1
- package/dist/graph/runtime-confirmation.d.ts +14 -91
- package/dist/graph/runtime-confirmation.d.ts.map +1 -1
- package/dist/graph/runtime-confirmation.js +19 -103
- package/dist/graph/runtime-confirmation.js.map +1 -1
- package/dist/ledger/mint.d.ts +9 -43
- package/dist/ledger/mint.d.ts.map +1 -1
- package/dist/ledger/mint.js +15 -65
- package/dist/ledger/mint.js.map +1 -1
- package/dist/ledger/resolve.d.ts +13 -81
- package/dist/ledger/resolve.d.ts.map +1 -1
- package/dist/ledger/resolve.js +13 -76
- package/dist/ledger/resolve.js.map +1 -1
- package/dist/multipr/fingerprint.d.ts +5 -46
- package/dist/multipr/fingerprint.d.ts.map +1 -1
- package/dist/multipr/fingerprint.js +22 -74
- package/dist/multipr/fingerprint.js.map +1 -1
- package/dist/multipr/hidden-dependency.d.ts +13 -73
- package/dist/multipr/hidden-dependency.d.ts.map +1 -1
- package/dist/multipr/hidden-dependency.js +12 -63
- package/dist/multipr/hidden-dependency.js.map +1 -1
- package/dist/multipr/mechanical.d.ts +25 -160
- package/dist/multipr/mechanical.d.ts.map +1 -1
- package/dist/multipr/mechanical.js +21 -137
- package/dist/multipr/mechanical.js.map +1 -1
- package/dist/multipr/migration-heads.d.ts +18 -105
- package/dist/multipr/migration-heads.d.ts.map +1 -1
- package/dist/multipr/migration-heads.js +15 -84
- package/dist/multipr/migration-heads.js.map +1 -1
- package/dist/multipr/overlap.d.ts +16 -94
- package/dist/multipr/overlap.d.ts.map +1 -1
- package/dist/multipr/overlap.js +25 -105
- package/dist/multipr/overlap.js.map +1 -1
- package/dist/multipr/scope-store.d.ts +15 -80
- package/dist/multipr/scope-store.d.ts.map +1 -1
- package/dist/multipr/scope-store.js +17 -87
- package/dist/multipr/scope-store.js.map +1 -1
- package/dist/multipr/superseded.d.ts +10 -95
- package/dist/multipr/superseded.d.ts.map +1 -1
- package/dist/multipr/superseded.js +7 -60
- package/dist/multipr/superseded.js.map +1 -1
- package/dist/query/confirmed-facts.d.ts +12 -58
- package/dist/query/confirmed-facts.d.ts.map +1 -1
- package/dist/query/confirmed-facts.js +8 -47
- package/dist/query/confirmed-facts.js.map +1 -1
- package/dist/query/declared-value-closure.d.ts +13 -104
- package/dist/query/declared-value-closure.d.ts.map +1 -1
- package/dist/query/declared-value-closure.js +15 -104
- package/dist/query/declared-value-closure.js.map +1 -1
- package/dist/query/memory.d.ts +4 -16
- package/dist/query/memory.d.ts.map +1 -1
- package/dist/query/memory.js +9 -22
- package/dist/query/memory.js.map +1 -1
- package/dist/query/prominence.d.ts +6 -55
- package/dist/query/prominence.d.ts.map +1 -1
- package/dist/query/prominence.js +6 -55
- package/dist/query/prominence.js.map +1 -1
- package/dist/query/provider.d.ts +27 -93
- package/dist/query/provider.d.ts.map +1 -1
- package/dist/query/provider.js +8 -29
- package/dist/query/provider.js.map +1 -1
- package/dist/query/queries.d.ts +15 -65
- package/dist/query/queries.d.ts.map +1 -1
- package/dist/query/queries.js +30 -104
- package/dist/query/queries.js.map +1 -1
- package/dist/query/refusal-fetch.d.ts +8 -85
- package/dist/query/refusal-fetch.d.ts.map +1 -1
- package/dist/query/refusal-fetch.js +11 -93
- package/dist/query/refusal-fetch.js.map +1 -1
- package/dist/query/refusal-questions.d.ts +17 -92
- package/dist/query/refusal-questions.d.ts.map +1 -1
- package/dist/query/refusal-questions.js +14 -78
- package/dist/query/refusal-questions.js.map +1 -1
- package/dist/query/resolution-floor.d.ts +3 -23
- package/dist/query/resolution-floor.d.ts.map +1 -1
- package/dist/query/resolution-floor.js +3 -23
- package/dist/query/resolution-floor.js.map +1 -1
- package/dist/query/root-cause-score.d.ts +11 -161
- package/dist/query/root-cause-score.d.ts.map +1 -1
- package/dist/query/root-cause-score.js +6 -137
- package/dist/query/root-cause-score.js.map +1 -1
- package/dist/query/row-closure-picture.d.ts +5 -67
- package/dist/query/row-closure-picture.d.ts.map +1 -1
- package/dist/query/row-closure-picture.js +6 -67
- package/dist/query/row-closure-picture.js.map +1 -1
- package/dist/query/similar-incidents.d.ts +6 -41
- package/dist/query/similar-incidents.d.ts.map +1 -1
- package/dist/query/similar-incidents.js +15 -69
- package/dist/query/similar-incidents.js.map +1 -1
- package/dist/query/sqlite.d.ts +3 -7
- package/dist/query/sqlite.d.ts.map +1 -1
- package/dist/query/sqlite.js +9 -19
- package/dist/query/sqlite.js.map +1 -1
- package/dist/query/test-coverage.d.ts +5 -45
- package/dist/query/test-coverage.d.ts.map +1 -1
- package/dist/query/test-coverage.js +10 -53
- package/dist/query/test-coverage.js.map +1 -1
- package/dist/query/traverse.d.ts +22 -126
- package/dist/query/traverse.d.ts.map +1 -1
- package/dist/query/traverse.js +25 -126
- package/dist/query/traverse.js.map +1 -1
- package/dist/query/unresolved.d.ts +19 -164
- package/dist/query/unresolved.d.ts.map +1 -1
- package/dist/query/unresolved.js +11 -138
- package/dist/query/unresolved.js.map +1 -1
- package/dist/query/verification-status.d.ts +12 -109
- package/dist/query/verification-status.d.ts.map +1 -1
- package/dist/query/verification-status.js +9 -99
- package/dist/query/verification-status.js.map +1 -1
- package/dist/recording/migrate.d.ts +4 -10
- package/dist/recording/migrate.d.ts.map +1 -1
- package/dist/recording/migrate.js +4 -10
- package/dist/recording/migrate.js.map +1 -1
- package/dist/recording/reader.d.ts +2 -7
- package/dist/recording/reader.d.ts.map +1 -1
- package/dist/recording/reader.js +2 -7
- package/dist/recording/reader.js.map +1 -1
- package/dist/recording/redact.d.ts +6 -57
- package/dist/recording/redact.d.ts.map +1 -1
- package/dist/recording/redact.js +8 -64
- package/dist/recording/redact.js.map +1 -1
- package/dist/recording/schema.d.ts +3 -38
- package/dist/recording/schema.d.ts.map +1 -1
- package/dist/recording/schema.js +3 -38
- package/dist/recording/schema.js.map +1 -1
- package/dist/recording/writer.d.ts +11 -74
- package/dist/recording/writer.d.ts.map +1 -1
- package/dist/recording/writer.js +3 -43
- package/dist/recording/writer.js.map +1 -1
- package/dist/scoping/fanout.d.ts +6 -68
- package/dist/scoping/fanout.d.ts.map +1 -1
- package/dist/scoping/fanout.js +6 -68
- package/dist/scoping/fanout.js.map +1 -1
- package/dist/scoping/score.d.ts +20 -70
- package/dist/scoping/score.d.ts.map +1 -1
- package/dist/scoping/score.js +20 -70
- package/dist/scoping/score.js.map +1 -1
- package/dist/scoping/tiers.d.ts +4 -16
- package/dist/scoping/tiers.d.ts.map +1 -1
- package/dist/scoping/tiers.js +4 -16
- package/dist/scoping/tiers.js.map +1 -1
- package/dist/scoping/traverse.d.ts +3 -25
- package/dist/scoping/traverse.d.ts.map +1 -1
- package/dist/scoping/traverse.js +14 -49
- package/dist/scoping/traverse.js.map +1 -1
- package/dist/scoping/weights.d.ts +10 -74
- package/dist/scoping/weights.d.ts.map +1 -1
- package/dist/scoping/weights.js +14 -86
- package/dist/scoping/weights.js.map +1 -1
- package/dist/sources/confirmed/incidents.d.ts +5 -35
- package/dist/sources/confirmed/incidents.d.ts.map +1 -1
- package/dist/sources/confirmed/incidents.js +14 -48
- package/dist/sources/confirmed/incidents.js.map +1 -1
- package/dist/sources/git/diff.d.ts +71 -65
- package/dist/sources/git/diff.d.ts.map +1 -1
- package/dist/sources/git/diff.js +136 -83
- package/dist/sources/git/diff.js.map +1 -1
- package/dist/sources/git/env.d.ts +7 -0
- package/dist/sources/git/env.d.ts.map +1 -1
- package/dist/sources/git/env.js +10 -11
- package/dist/sources/git/env.js.map +1 -1
- package/dist/sources/git/history.d.ts +64 -84
- package/dist/sources/git/history.d.ts.map +1 -1
- package/dist/sources/git/history.js +141 -112
- package/dist/sources/git/history.js.map +1 -1
- package/dist/sources/git/incidents.d.ts +13 -75
- package/dist/sources/git/incidents.d.ts.map +1 -1
- package/dist/sources/git/incidents.js +21 -91
- package/dist/sources/git/incidents.js.map +1 -1
- package/dist/sources/git/index.d.ts +5 -3
- package/dist/sources/git/index.d.ts.map +1 -1
- package/dist/sources/git/index.js +3 -2
- package/dist/sources/git/index.js.map +1 -1
- package/dist/sources/git/source.d.ts +9 -79
- package/dist/sources/git/source.d.ts.map +1 -1
- package/dist/sources/git/source.js +33 -133
- package/dist/sources/git/source.js.map +1 -1
- package/dist/sources/migrations/across-change.d.ts +94 -0
- package/dist/sources/migrations/across-change.d.ts.map +1 -0
- package/dist/sources/migrations/across-change.js +278 -0
- package/dist/sources/migrations/across-change.js.map +1 -0
- package/dist/sources/migrations/dialects.d.ts +20 -36
- package/dist/sources/migrations/dialects.d.ts.map +1 -1
- package/dist/sources/migrations/dialects.js +11 -36
- package/dist/sources/migrations/dialects.js.map +1 -1
- package/dist/sources/migrations/index.d.ts +3 -1
- package/dist/sources/migrations/index.d.ts.map +1 -1
- package/dist/sources/migrations/index.js +2 -1
- package/dist/sources/migrations/index.js.map +1 -1
- package/dist/sources/migrations/read.d.ts +14 -79
- package/dist/sources/migrations/read.d.ts.map +1 -1
- package/dist/sources/migrations/read.js +14 -89
- package/dist/sources/migrations/read.js.map +1 -1
- package/dist/sources/workspace/workspace.d.ts +6 -42
- package/dist/sources/workspace/workspace.d.ts.map +1 -1
- package/dist/sources/workspace/workspace.js +10 -53
- package/dist/sources/workspace/workspace.js.map +1 -1
- package/dist/store/driver/driver.d.ts +9 -38
- package/dist/store/driver/driver.d.ts.map +1 -1
- package/dist/store/driver/driver.js +4 -22
- package/dist/store/driver/driver.js.map +1 -1
- package/dist/store/driver/node-sqlite.d.ts +3 -12
- package/dist/store/driver/node-sqlite.d.ts.map +1 -1
- package/dist/store/driver/node-sqlite.js +4 -18
- package/dist/store/driver/node-sqlite.js.map +1 -1
- package/dist/store/index.d.ts +2 -7
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +4 -10
- package/dist/store/index.js.map +1 -1
- package/dist/store/migrate.d.ts +14 -50
- package/dist/store/migrate.d.ts.map +1 -1
- package/dist/store/migrate.js +15 -52
- package/dist/store/migrate.js.map +1 -1
- package/dist/store/reader.d.ts +19 -84
- package/dist/store/reader.d.ts.map +1 -1
- package/dist/store/reader.js +25 -92
- package/dist/store/reader.js.map +1 -1
- package/dist/store/schema.d.ts +14 -76
- package/dist/store/schema.d.ts.map +1 -1
- package/dist/store/schema.js +14 -76
- package/dist/store/schema.js.map +1 -1
- package/dist/store/writer.d.ts +14 -88
- package/dist/store/writer.d.ts.map +1 -1
- package/dist/store/writer.js +29 -123
- package/dist/store/writer.js.map +1 -1
- package/dist/tiers/certify.d.ts +46 -281
- package/dist/tiers/certify.d.ts.map +1 -1
- package/dist/tiers/certify.js +46 -226
- package/dist/tiers/certify.js.map +1 -1
- package/dist/tiers/ladder.d.ts +7 -51
- package/dist/tiers/ladder.d.ts.map +1 -1
- package/dist/tiers/ladder.js +13 -89
- package/dist/tiers/ladder.js.map +1 -1
- package/dist/validation/attributes.d.ts +6 -55
- package/dist/validation/attributes.d.ts.map +1 -1
- package/dist/validation/attributes.js +6 -55
- package/dist/validation/attributes.js.map +1 -1
- package/dist/validation/config-graph.d.ts +7 -56
- package/dist/validation/config-graph.d.ts.map +1 -1
- package/dist/validation/config-graph.js +15 -61
- package/dist/validation/config-graph.js.map +1 -1
- package/dist/validation/env.d.ts +7 -1
- package/dist/validation/env.d.ts.map +1 -1
- package/dist/validation/env.js +3 -1
- package/dist/validation/env.js.map +1 -1
- package/dist/validation/join-substitution.d.ts +22 -120
- package/dist/validation/join-substitution.d.ts.map +1 -1
- package/dist/validation/join-substitution.js +13 -90
- package/dist/validation/join-substitution.js.map +1 -1
- package/dist/validation/migration-integrity.d.ts +11 -72
- package/dist/validation/migration-integrity.d.ts.map +1 -1
- package/dist/validation/migration-integrity.js +16 -79
- package/dist/validation/migration-integrity.js.map +1 -1
- package/dist/validation/migrations.d.ts +22 -101
- package/dist/validation/migrations.d.ts.map +1 -1
- package/dist/validation/migrations.js +19 -83
- package/dist/validation/migrations.js.map +1 -1
- package/dist/validation/nodes.d.ts +3 -1
- package/dist/validation/nodes.d.ts.map +1 -1
- package/dist/validation/nodes.js +3 -1
- package/dist/validation/nodes.js.map +1 -1
- package/dist/validation/rollback.d.ts +10 -73
- package/dist/validation/rollback.d.ts.map +1 -1
- package/dist/validation/rollback.js +15 -82
- package/dist/validation/rollback.js.map +1 -1
- package/dist/validation/route-drift.d.ts +9 -62
- package/dist/validation/route-drift.d.ts.map +1 -1
- package/dist/validation/route-drift.js +7 -52
- package/dist/validation/route-drift.js.map +1 -1
- package/dist/validation/sources.d.ts +16 -94
- package/dist/validation/sources.d.ts.map +1 -1
- package/dist/validation/sources.js +51 -147
- package/dist/validation/sources.js.map +1 -1
- package/dist/worker/pool.d.ts +6 -45
- package/dist/worker/pool.d.ts.map +1 -1
- package/dist/worker/pool.js +5 -42
- package/dist/worker/pool.js.map +1 -1
- package/dist/worker/protocol.d.ts +7 -20
- package/dist/worker/protocol.d.ts.map +1 -1
- package/dist/worker/protocol.js +3 -10
- package/dist/worker/protocol.js.map +1 -1
- package/dist/worker/traversal.worker.d.ts +2 -21
- package/dist/worker/traversal.worker.d.ts.map +1 -1
- package/dist/worker/traversal.worker.js +4 -23
- package/dist/worker/traversal.worker.js.map +1 -1
- package/package.json +11 -2
|
@@ -1,59 +1,9 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* > *"Without this layer, a run that surfaces 200 findings gets read by
|
|
5
|
-
* > nobody. Volume without governance is functionally the same as no output at
|
|
6
|
-
* > all."*
|
|
7
|
-
*
|
|
8
|
-
* §20.1 draws a five-filter funnel ending in a hard cap. Two of its boxes had
|
|
9
|
-
* no implementation anywhere: **F2, "known false positives from the feedback
|
|
10
|
-
* store,"** and **the HARD CAP itself**, whose value architecture §32 item 6
|
|
11
|
-
* has carried as a blank since the document was written (*"Hard cap value —
|
|
12
|
-
* how many findings is 'a few'"*, Tuning, *"set from early runs"*).
|
|
13
|
-
*
|
|
14
|
-
* `CLAUDE.md` rule 5 — *"a few high-confidence findings, never an exhaustive
|
|
15
|
-
* maybe-list"* — is the rule aimed most directly at what this whole category
|
|
16
|
-
* of tool gets wrong, and it was the one rule with no number behind it. Three
|
|
17
|
-
* per-check caps of 25 existed (`contracts/orphans.ts`, `validation/rollback.ts`,
|
|
18
|
-
* `validation/env.ts`), which is not the same thing: three checks at 25 present
|
|
19
|
-
* 75 items and nothing objects.
|
|
20
|
-
*
|
|
21
|
-
* ## The cap values, and where they come from
|
|
22
|
-
*
|
|
23
|
-
* §20.1 states its own worked example in prose: *"Twenty-seven possible issues
|
|
24
|
-
* get ignored. Three confirmed issues plus two worth checking get acted on
|
|
25
|
-
* immediately."* **Three plus two is five**, and that is `pr`'s cap — read off
|
|
26
|
-
* the architecture rather than invented.
|
|
27
|
-
*
|
|
28
|
-
* The other three are scaled to their trigger the same way `NODE_BUDGETS`
|
|
29
|
-
* already is, and for the same reason: an IDE hover and a nightly sweep are
|
|
30
|
-
* not the same reading surface. **Starting values, not measurements** —
|
|
31
|
-
* `CLAUDE.md`'s standing convention for every number in this project.
|
|
32
|
-
*
|
|
33
|
-
* ## What this module deliberately does not own
|
|
34
|
-
*
|
|
35
|
-
* - **It does not assign a category.** Only G4 does (`ai-governance-spec.md`
|
|
36
|
-
* §11). This runs strictly after, on already-categorised findings, and
|
|
37
|
-
* reorders and truncates them without touching a single field.
|
|
38
|
-
* - **It does not store dismissals.** `isDismissed` is a caller-supplied
|
|
39
|
-
* predicate. The ledger is `descry-desktop`'s (§21.3 puts the feedback store
|
|
40
|
-
* next to the runs it belongs to); the *filter* is governance and belongs
|
|
41
|
-
* here, next to G1–G4.
|
|
42
|
-
* - **It never silently drops anything.** Every finding that entered leaves in
|
|
43
|
-
* exactly one of `reported` / `unconfirmed` / `suppressed`, and the count it
|
|
44
|
-
* truncated is a structured field with a rendered sentence — the same rule
|
|
45
|
-
* `ai-tool-contract.md` §4 technique 5 applies one layer down (*"a capped
|
|
46
|
-
* result that looks complete is the same defect as a zero that looks like a
|
|
47
|
-
* finding"*).
|
|
48
|
-
*/
|
|
1
|
+
/** §20.1 governance funnel — five filters ending in a hard cap; F2 (feedback-store false
|
|
2
|
+
* positives) and the cap itself were unimplemented until now. Caps are starting values (pr=5,
|
|
3
|
+
* §20.1's own 3+2 example). Never silently drops: every finding lands in reported/unconfirmed/suppressed. */
|
|
49
4
|
import { findingFingerprint } from "@descryy/ir";
|
|
50
|
-
/**
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* `pr` is architecture §20.1's own arithmetic (3 confirmed + 2 worth
|
|
54
|
-
* checking). The rest are scaled to the reading surface, the same shape
|
|
55
|
-
* `NODE_BUDGETS` uses, and are starting values pending real runs to tune from.
|
|
56
|
-
*/
|
|
5
|
+
/** Findings one run may report, per trigger. `pr`=5 is §20.1's own arithmetic (3+2). The rest
|
|
6
|
+
* scale to the reading surface (same shape as NODE_BUDGETS) — starting values, not measurements. */
|
|
57
7
|
export const FINDING_CAPS = {
|
|
58
8
|
/** A hover is one line of screen. More than one finding there is a list nobody reads. */
|
|
59
9
|
"ide-hover": 1,
|
|
@@ -74,14 +24,8 @@ const CATEGORY_RANK = {
|
|
|
74
24
|
};
|
|
75
25
|
/** Categories that belong in §20.1's separate unconfirmed list rather than the capped one. */
|
|
76
26
|
const NOT_CONFIDENT = new Set(["unconfirmed", "not analysable", "unsupported"]);
|
|
77
|
-
/**
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
* Pure and total: same input, same output, and every input finding appears in
|
|
81
|
-
* exactly one output list. Deterministic ordering — required by
|
|
82
|
-
* `ai-layer-plan.md` §9 layer 6's replay guarantee, so ties break on the
|
|
83
|
-
* finding's own fingerprint rather than on input order.
|
|
84
|
-
*/
|
|
27
|
+
/** §20.1's funnel. Pure and total — every input finding appears in exactly one output list.
|
|
28
|
+
* Deterministic ordering (replay guarantee, §9 layer 6): ties break on fingerprint, not input order. */
|
|
85
29
|
export function runFindingFunnel(findings, options) {
|
|
86
30
|
const isDismissed = options.isDismissed ?? (() => false);
|
|
87
31
|
const suppressed = [];
|
|
@@ -128,10 +72,7 @@ function compareFindings(a, b) {
|
|
|
128
72
|
// A stable, content-derived tiebreak, so replay reproduces the order.
|
|
129
73
|
return findingFingerprint(a) < findingFingerprint(b) ? -1 : 1;
|
|
130
74
|
}
|
|
131
|
-
/**
|
|
132
|
-
*
|
|
133
|
-
* The implementation lives in `@descryy/ir`'s identity module — see
|
|
134
|
-
* `DEC-NEXT-edge-id-prefix-split` for why an identity gets exactly one home.
|
|
135
|
-
*/
|
|
75
|
+
/** Re-exported so a caller wiring the funnel and ledger imports one module — implementation
|
|
76
|
+
* lives in @descryy/ir's identity module (DEC-NEXT-edge-id-prefix-split). */
|
|
136
77
|
export { findingFingerprint } from "@descryy/ir";
|
|
137
78
|
//# sourceMappingURL=finding-funnel.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"finding-funnel.js","sourceRoot":"","sources":["../../src/governance/finding-funnel.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"finding-funnel.js","sourceRoot":"","sources":["../../src/governance/finding-funnel.ts"],"names":[],"mappings":"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"}
|
package/dist/graph/build.d.ts
CHANGED
|
@@ -1,48 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Everything before it works on one adapter's output at a time; this folds
|
|
6
|
-
* several adapters' IR into one graph, and either the cross-language join
|
|
7
|
-
* happens here or it never happens at all.
|
|
8
|
-
*
|
|
9
|
-
* Its acceptance test is XL-1 — *exactly one* `API_ENDPOINT` node after merging
|
|
10
|
-
* both adapters — and XL-2, that the node carries no language. Step 7 showed the
|
|
11
|
-
* two fakes reach the same endpoint id independently; this has to preserve that
|
|
12
|
-
* through the merge rather than produce two nodes or one wrong one.
|
|
13
|
-
*
|
|
14
|
-
* ## Four rules, in order of how much damage they prevent
|
|
15
|
-
*
|
|
16
|
-
* **1. Never invent a node.** An edge whose target cannot be resolved is
|
|
17
|
-
* dropped. It never becomes a stub node, however convenient that would be for
|
|
18
|
-
* traversal. On the prior-art graphs measured for this build, 52-60% of edges
|
|
19
|
-
* pointed at a non-existent target — `append` with in-degree 1,036, `get` with
|
|
20
|
-
* 973. Materialising those as nodes is how a graph acquires a thousand-way hub
|
|
21
|
-
* that every impact score then routes through.
|
|
22
|
-
*
|
|
23
|
-
* **2. Merge is order-independent.** DEC-012's third tie-break exists only for
|
|
24
|
-
* this. Without it, "which adapter ran first" leaks into every impact score, and
|
|
25
|
-
* the symptom is an unreproducible difference nobody can bisect.
|
|
26
|
-
*
|
|
27
|
-
* **3. Collisions are reported, not merged.** Two nodes sharing an id but
|
|
28
|
-
* disagreeing on type or language are not the same thing, and merging them pools
|
|
29
|
-
* the edges of two unrelated symbols. See DEC-024 — this is a live hazard in a
|
|
30
|
-
* polyglot monorepo, not a hypothetical one.
|
|
31
|
-
*
|
|
32
|
-
* **4. Nothing enters without passing the Normaliser.** The builder calls it
|
|
33
|
-
* rather than trusting its caller, because the batch-spanning `nodeExists` it
|
|
34
|
-
* needs — an edge may legitimately point into a sibling batch in the same build
|
|
35
|
-
* — can only be computed here.
|
|
2
|
+
* Folds multiple adapters' IR into one graph — XL-1: one `API_ENDPOINT` node after merging; XL-2: no
|
|
3
|
+
* language on it. Never invents a node for an unresolved edge (52-60% of edges were dangling in
|
|
4
|
+
* prior-art graphs measured here); merge order-independent (DEC-012); collisions reported, never merged (DEC-024).
|
|
36
5
|
*/
|
|
37
6
|
import { type IRBatch, type IREdge, type IRNode, type NodeType, type NormaliseOptions, type Rejection, type UnresolvedRef } from "@descryy/ir";
|
|
38
|
-
/**
|
|
39
|
-
* Two nodes claimed the same id but are not the same thing.
|
|
40
|
-
*
|
|
41
|
-
* Reported rather than resolved. There is no correct merge — the ids are equal,
|
|
42
|
-
* so the graph has no way to represent them separately — and picking one
|
|
43
|
-
* silently is the corruption DEC-024 describes. Surfacing it puts the failure in
|
|
44
|
-
* §20.2's "not analysable" category, where a user can see it.
|
|
45
|
-
*/
|
|
7
|
+
/** Two nodes claimed the same id but are not the same thing. Reported, never silently resolved (DEC-024). */
|
|
46
8
|
export interface IdentityCollision {
|
|
47
9
|
readonly nodeId: string;
|
|
48
10
|
readonly kept: {
|
|
@@ -56,54 +18,21 @@ export interface IdentityCollision {
|
|
|
56
18
|
readonly producedBy: string;
|
|
57
19
|
};
|
|
58
20
|
}
|
|
59
|
-
/**
|
|
60
|
-
* How much of a workspace-scoped node type actually crossed a repository
|
|
61
|
-
* boundary, and how much only ever existed in one.
|
|
62
|
-
*
|
|
63
|
-
* Counted per *repository*, not per producer: two adapters in one repo agreeing
|
|
64
|
-
* on a node is a within-repo merge and is not what DEC-054's scope table exists
|
|
65
|
-
* to achieve.
|
|
66
|
-
*
|
|
67
|
-
* **Legibility note (UAT round 3, second-look item).** On a single-repository
|
|
68
|
-
* build this metric's own name invited a wrong reading: `{ total: 48, joined:
|
|
69
|
-
* 0 }` next to a disclosure about 55 unrelated within-repo `USES_API` edges
|
|
70
|
-
* read as "0 of 48 endpoints joined" — a failure of the thing the disclosure
|
|
71
|
-
* had just said succeeded — when `joined: 0` was in fact the *only possible
|
|
72
|
-
* value* with one repository in scope, and both statements were true. Nothing
|
|
73
|
-
* here was wrong; the name did not say what it counts. `suppliedByTwoOrMoreRepos`
|
|
74
|
-
* replaces `joined`, and `crossRepoJoinPossible` states outright whether this
|
|
75
|
-
* entry could ever be nonzero in this build, so a reader is not left to infer
|
|
76
|
-
* "one repository" from `repos.length` themselves.
|
|
77
|
-
*/
|
|
21
|
+
/** How much of a workspace-scoped type crossed a repo boundary, counted per repo not producer (DEC-054). */
|
|
78
22
|
export interface JoinMetric {
|
|
79
23
|
readonly type: NodeType;
|
|
80
24
|
/** Distinct nodes of this type in the built graph. */
|
|
81
25
|
readonly total: number;
|
|
82
26
|
/** Of those, how many were supplied by more than one repository — the join itself. */
|
|
83
27
|
readonly suppliedByTwoOrMoreRepos: number;
|
|
84
|
-
/**
|
|
85
|
-
* False when fewer than two repositories emitted this type in this build,
|
|
86
|
-
* which makes `suppliedByTwoOrMoreRepos` structurally zero — a fact about
|
|
87
|
-
* the input, not a measurement of anything. True does not promise a join
|
|
88
|
-
* happened, only that one was possible; `NO_CROSS_REPO_JOIN` below is the
|
|
89
|
-
* warning for "possible and did not happen."
|
|
90
|
-
*/
|
|
28
|
+
/** False when fewer than two repos emitted this type (join is structurally zero). True only means possible — see `NO_CROSS_REPO_JOIN`. */
|
|
91
29
|
readonly crossRepoJoinPossible: boolean;
|
|
92
30
|
/** Repositories in this build that emitted the type at all. */
|
|
93
31
|
readonly repos: readonly string[];
|
|
94
32
|
/** The identity scope each of those repositories resolved to, deduplicated. */
|
|
95
33
|
readonly scopes: readonly string[];
|
|
96
34
|
}
|
|
97
|
-
/**
|
|
98
|
-
* Something the build cannot call an error but must not pass over in silence.
|
|
99
|
-
*
|
|
100
|
-
* `NO_CROSS_REPO_JOIN` is the one that matters and the reason this list exists.
|
|
101
|
-
* A workspace id has to be byte-identical in every repository that shares it,
|
|
102
|
-
* and when it is not, nothing fails: every batch normalises, every node is
|
|
103
|
-
* well-formed, every edge resolves, and the two sides simply never meet. Zero
|
|
104
|
-
* joins, zero errors, zero warnings — which is why the zero itself has to be the
|
|
105
|
-
* warning.
|
|
106
|
-
*/
|
|
35
|
+
/** Not an error, but not silent. `NO_CROSS_REPO_JOIN`: a workspace id must be byte-identical across repos, or nothing else fails but the zero-join is the warning. */
|
|
107
36
|
export interface BuildWarning {
|
|
108
37
|
readonly code: "NO_CROSS_REPO_JOIN";
|
|
109
38
|
readonly type: NodeType;
|
|
@@ -127,20 +56,10 @@ export interface BuildResult {
|
|
|
127
56
|
readonly warnings: readonly BuildWarning[];
|
|
128
57
|
}
|
|
129
58
|
export interface BuildOptions {
|
|
130
|
-
/**
|
|
131
|
-
* Does a node with this id already exist in the store? An incremental build
|
|
132
|
-
* over one changed file legitimately points at nodes no batch in this build
|
|
133
|
-
* supplied.
|
|
134
|
-
*/
|
|
59
|
+
/** Does a node with this id already exist in the store? Needed for incremental builds over one changed file. */
|
|
135
60
|
readonly nodeExists?: (id: string) => boolean;
|
|
136
61
|
readonly confidenceCeilings?: NormaliseOptions["confidenceCeilings"];
|
|
137
62
|
}
|
|
138
|
-
/**
|
|
139
|
-
* Fold normalised batches into one graph.
|
|
140
|
-
*
|
|
141
|
-
* Pure: no store, no IO. The store is one consumer of the result, the
|
|
142
|
-
* conformance harness is another, and a builder that wrote as it went could be
|
|
143
|
-
* tested by neither without a database.
|
|
144
|
-
*/
|
|
63
|
+
/** Fold normalised batches into one graph. Pure: no store, no IO — testable without a database. */
|
|
145
64
|
export declare function buildGraph(batches: readonly IRBatch[], options?: BuildOptions): BuildResult;
|
|
146
65
|
//# sourceMappingURL=build.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/graph/build.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/graph/build.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAIL,KAAK,OAAO,EACZ,KAAK,MAAM,EACX,KAAK,MAAM,EACX,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,SAAS,EACd,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AAMrB,6GAA6G;AAC7G,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IACxG,QAAQ,CAAC,SAAS,EAAE;QAClB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;KAC7B,CAAC;CACH;AAED,4GAA4G;AAC5G,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,sFAAsF;IACtF,QAAQ,CAAC,wBAAwB,EAAE,MAAM,CAAC;IAC1C,0IAA0I;IAC1I,QAAQ,CAAC,qBAAqB,EAAE,OAAO,CAAC;IACxC,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,+EAA+E;IAC/E,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,sKAAsK;AACtK,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,UAAU,EAAE,SAAS,aAAa,EAAE,CAAC;IAC9C,+EAA+E;IAC/E,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IAC1C,qFAAqF;IACrF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,oEAAoE;IACpE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAClD,4EAA4E;IAC5E,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,mFAAmF;IACnF,QAAQ,CAAC,cAAc,EAAE,SAAS,UAAU,EAAE,CAAC;IAC/C,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAC;CAC5C;AAED,MAAM,WAAW,YAAY;IAC3B,gHAAgH;IAChH,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;IAC9C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,gBAAgB,CAAC,oBAAoB,CAAC,CAAC;CACtE;AAED,mGAAmG;AACnG,wBAAgB,UAAU,CAAC,OAAO,EAAE,SAAS,OAAO,EAAE,EAAE,OAAO,GAAE,YAAiB,GAAG,WAAW,CA2L/F"}
|
package/dist/graph/build.js
CHANGED
|
@@ -1,55 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Everything before it works on one adapter's output at a time; this folds
|
|
6
|
-
* several adapters' IR into one graph, and either the cross-language join
|
|
7
|
-
* happens here or it never happens at all.
|
|
8
|
-
*
|
|
9
|
-
* Its acceptance test is XL-1 — *exactly one* `API_ENDPOINT` node after merging
|
|
10
|
-
* both adapters — and XL-2, that the node carries no language. Step 7 showed the
|
|
11
|
-
* two fakes reach the same endpoint id independently; this has to preserve that
|
|
12
|
-
* through the merge rather than produce two nodes or one wrong one.
|
|
13
|
-
*
|
|
14
|
-
* ## Four rules, in order of how much damage they prevent
|
|
15
|
-
*
|
|
16
|
-
* **1. Never invent a node.** An edge whose target cannot be resolved is
|
|
17
|
-
* dropped. It never becomes a stub node, however convenient that would be for
|
|
18
|
-
* traversal. On the prior-art graphs measured for this build, 52-60% of edges
|
|
19
|
-
* pointed at a non-existent target — `append` with in-degree 1,036, `get` with
|
|
20
|
-
* 973. Materialising those as nodes is how a graph acquires a thousand-way hub
|
|
21
|
-
* that every impact score then routes through.
|
|
22
|
-
*
|
|
23
|
-
* **2. Merge is order-independent.** DEC-012's third tie-break exists only for
|
|
24
|
-
* this. Without it, "which adapter ran first" leaks into every impact score, and
|
|
25
|
-
* the symptom is an unreproducible difference nobody can bisect.
|
|
26
|
-
*
|
|
27
|
-
* **3. Collisions are reported, not merged.** Two nodes sharing an id but
|
|
28
|
-
* disagreeing on type or language are not the same thing, and merging them pools
|
|
29
|
-
* the edges of two unrelated symbols. See DEC-024 — this is a live hazard in a
|
|
30
|
-
* polyglot monorepo, not a hypothetical one.
|
|
31
|
-
*
|
|
32
|
-
* **4. Nothing enters without passing the Normaliser.** The builder calls it
|
|
33
|
-
* rather than trusting its caller, because the batch-spanning `nodeExists` it
|
|
34
|
-
* needs — an edge may legitimately point into a sibling batch in the same build
|
|
35
|
-
* — can only be computed here.
|
|
2
|
+
* Folds multiple adapters' IR into one graph — XL-1: one `API_ENDPOINT` node after merging; XL-2: no
|
|
3
|
+
* language on it. Never invents a node for an unresolved edge (52-60% of edges were dangling in
|
|
4
|
+
* prior-art graphs measured here); merge order-independent (DEC-012); collisions reported, never merged (DEC-024).
|
|
36
5
|
*/
|
|
37
6
|
import { normaliseBatch, scopeOf, WORKSPACE_SCOPED_NODE_TYPES, } from "@descryy/ir";
|
|
38
7
|
import { identityFingerprint, mergeEdge, mergeNode } from "./merge.js";
|
|
39
8
|
const WORKSPACE_SCOPED = new Set(WORKSPACE_SCOPED_NODE_TYPES);
|
|
40
|
-
/**
|
|
41
|
-
* Fold normalised batches into one graph.
|
|
42
|
-
*
|
|
43
|
-
* Pure: no store, no IO. The store is one consumer of the result, the
|
|
44
|
-
* conformance harness is another, and a builder that wrote as it went could be
|
|
45
|
-
* tested by neither without a database.
|
|
46
|
-
*/
|
|
9
|
+
/** Fold normalised batches into one graph. Pure: no store, no IO — testable without a database. */
|
|
47
10
|
export function buildGraph(batches, options = {}) {
|
|
48
11
|
const rejections = [];
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
|
-
// against the store alone would reject every cross-batch edge in the build.
|
|
12
|
+
// pass 1: node ids that will exist. Computed first — an edge in batch A may
|
|
13
|
+
// legitimately point at a node in batch B; normalising one batch at a time
|
|
14
|
+
// would reject every cross-batch edge.
|
|
53
15
|
const suppliedIds = new Set();
|
|
54
16
|
for (const batch of batches) {
|
|
55
17
|
for (const node of batch.nodes) {
|
|
@@ -66,18 +28,13 @@ export function buildGraph(batches, options = {}) {
|
|
|
66
28
|
const collisions = [];
|
|
67
29
|
let mergedNodes = 0;
|
|
68
30
|
let mergedEdges = 0;
|
|
69
|
-
// Which
|
|
70
|
-
//
|
|
71
|
-
// tracked — a repo-scoped node can never be supplied by two repos by
|
|
72
|
-
// construction, so counting it would cost memory to learn nothing.
|
|
31
|
+
// Which repos supplied each workspace-scoped node, and their resolved scope.
|
|
32
|
+
// Repo-scoped nodes are never tracked — they can't be supplied by two repos.
|
|
73
33
|
const suppliers = new Map();
|
|
74
34
|
const reposByType = new Map();
|
|
75
35
|
const scopesByType = new Map();
|
|
76
|
-
//
|
|
77
|
-
//
|
|
78
|
-
// batch is actually considered — sorting here means a caller cannot change
|
|
79
|
-
// the outcome by shuffling its input, which is the property the permutation
|
|
80
|
-
// proof rests on.
|
|
36
|
+
// Deterministic order, not input order — the merge rule makes the result
|
|
37
|
+
// order-independent only if a caller can't change it by shuffling the input.
|
|
81
38
|
const ordered = [...batches].sort((a, b) => `${a.producedBy}\u0000${a.repo}\u0000${a.commitSha}`.localeCompare(`${b.producedBy}\u0000${b.repo}\u0000${b.commitSha}`));
|
|
82
39
|
for (const batch of ordered) {
|
|
83
40
|
const normaliseOptions = {
|
|
@@ -149,10 +106,8 @@ export function buildGraph(batches, options = {}) {
|
|
|
149
106
|
unresolved.set(key, ref);
|
|
150
107
|
}
|
|
151
108
|
}
|
|
152
|
-
//
|
|
153
|
-
//
|
|
154
|
-
// it, or a collision may have discarded it. Dropping the edge is the only
|
|
155
|
-
// option that does not invent something.
|
|
109
|
+
// pass 3: drop edges whose endpoints didn't survive (rejected or discarded
|
|
110
|
+
// by a collision) — dropping is the only option that invents nothing.
|
|
156
111
|
const surviving = [];
|
|
157
112
|
let droppedEdges = 0;
|
|
158
113
|
for (const edge of edges.values()) {
|
|
@@ -181,10 +136,8 @@ export function buildGraph(batches, options = {}) {
|
|
|
181
136
|
repos,
|
|
182
137
|
scopes,
|
|
183
138
|
});
|
|
184
|
-
// Two
|
|
185
|
-
//
|
|
186
|
-
// mistyped workspace id or two genuinely unrelated services, it is the one
|
|
187
|
-
// outcome that looks identical to success, so it is stated.
|
|
139
|
+
// Two+ repos emitted the type, no node in common — a mistyped workspace id
|
|
140
|
+
// or genuinely unrelated services, but it looks identical to success either way.
|
|
188
141
|
if (repos.length > 1 && suppliedByTwoOrMoreRepos === 0) {
|
|
189
142
|
warnings.push({
|
|
190
143
|
code: "NO_CROSS_REPO_JOIN",
|
package/dist/graph/build.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/graph/build.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/graph/build.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,45 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* themselves rather than inside any one adapter, because the target id an
|
|
6
|
-
* unresolved reference should join to is not something the referencing
|
|
7
|
-
* adapter can compute — it does not have the declaring language's source.
|
|
8
|
-
*
|
|
9
|
-
* ## Why the key is a string neither side derives from the other
|
|
10
|
-
*
|
|
11
|
-
* `UnresolvedRef.rawTarget` is what the referencing side's own source spells —
|
|
12
|
-
* a Java `import okhttp3.OkHttpClient;` cannot carry Kotlin's module or source
|
|
13
|
-
* set, because nothing in that line names either.
|
|
14
|
-
* `CrossLanguageDeclaration.qualifiedName` is the same kind of fact, stated by
|
|
15
|
-
* the *declaring* adapter about how an external reader would reach its node.
|
|
16
|
-
* Matching the two is a string comparison over two independently-computed
|
|
17
|
-
* facts, not a derivation of one from the other — which is what keeps this a
|
|
18
|
-
* resolver rather than a heuristic.
|
|
19
|
-
*
|
|
20
|
-
* ## Mutual declaration
|
|
21
|
-
*
|
|
22
|
-
* Two adapters resolve against each other only when each names the other as a
|
|
23
|
-
* peer (`CapabilityMatrix.crossLanguageNamespace`). A one-sided declaration —
|
|
24
|
-
* or two unrelated adapters that happen to pick the same namespace `id` by
|
|
25
|
-
* accident — resolves nothing. This is deliberate: equality-only comparison
|
|
26
|
-
* makes an accidental id collision silent otherwise, and that is the exact
|
|
27
|
-
* failure this mechanism exists to prevent, arriving through its own door if
|
|
28
|
-
* declaration were not mutual.
|
|
29
|
-
*
|
|
30
|
-
* ## Ambiguity is the normal case, not the exception
|
|
31
|
-
*
|
|
32
|
-
* More than one candidate for a `qualifiedName`, with no stated basis to
|
|
33
|
-
* choose between them, is reported and resolves nothing — precision over
|
|
34
|
-
* recall, and the same rule `dup-ids.mjs` enforces on plain node identity.
|
|
35
|
-
*
|
|
36
|
-
* ## Resolution and provenance
|
|
37
|
-
*
|
|
38
|
-
* Every resolved edge is stamped `resolution: 1` (R1 — a name match between
|
|
39
|
-
* two adapters, neither of which type-checked the other's file) and
|
|
40
|
-
* `producedBy: RESOLVER_PRODUCED_BY`. Neither adapter produced this edge, and
|
|
41
|
-
* attributing it to one would make that adapter's own precision figures
|
|
42
|
-
* answer for a join it did not make.
|
|
2
|
+
* Cross-language declaration index (DEC-161): matches `rawTarget` to `qualifiedName` as independently-
|
|
3
|
+
* computed strings, never derived from each other. Requires mutual peer declaration or resolves nothing;
|
|
4
|
+
* ambiguity is reported, never guessed. Every resolved edge stamped R1, `RESOLVER_PRODUCED_BY`.
|
|
43
5
|
*/
|
|
44
6
|
import type { IRBatch, IREdge, UnresolvedRef } from "@descryy/ir";
|
|
45
7
|
/** Stamped on every edge this pass mints. Neither adapter's own id, on purpose. */
|
|
@@ -48,8 +10,7 @@ export interface NamespaceDeclaration {
|
|
|
48
10
|
readonly id: string;
|
|
49
11
|
readonly peers: readonly string[];
|
|
50
12
|
}
|
|
51
|
-
/** More than one declared node answers to this `qualifiedName`
|
|
52
|
-
* matched namespace pair — refused rather than guessed. */
|
|
13
|
+
/** More than one declared node answers to this `qualifiedName` — refused rather than guessed. */
|
|
53
14
|
export interface CrossLanguageAmbiguity {
|
|
54
15
|
readonly unresolved: UnresolvedRef;
|
|
55
16
|
readonly qualifiedName: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cross-language.d.ts","sourceRoot":"","sources":["../../src/graph/cross-language.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"cross-language.d.ts","sourceRoot":"","sources":["../../src/graph/cross-language.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAY,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5E,mFAAmF;AACnF,eAAO,MAAM,oBAAoB,8BAA8B,CAAC;AAEhE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,iGAAiG;AACjG,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC;IACnC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9C;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,SAAS,sBAAsB,EAAE,CAAC;CACvD;AAqBD,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,SAAS,OAAO,EAAE,EAC3B,WAAW,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,oBAAoB,GAAG,SAAS,GACpE,mBAAmB,CAmDrB"}
|
|
@@ -1,80 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* themselves rather than inside any one adapter, because the target id an
|
|
6
|
-
* unresolved reference should join to is not something the referencing
|
|
7
|
-
* adapter can compute — it does not have the declaring language's source.
|
|
8
|
-
*
|
|
9
|
-
* ## Why the key is a string neither side derives from the other
|
|
10
|
-
*
|
|
11
|
-
* `UnresolvedRef.rawTarget` is what the referencing side's own source spells —
|
|
12
|
-
* a Java `import okhttp3.OkHttpClient;` cannot carry Kotlin's module or source
|
|
13
|
-
* set, because nothing in that line names either.
|
|
14
|
-
* `CrossLanguageDeclaration.qualifiedName` is the same kind of fact, stated by
|
|
15
|
-
* the *declaring* adapter about how an external reader would reach its node.
|
|
16
|
-
* Matching the two is a string comparison over two independently-computed
|
|
17
|
-
* facts, not a derivation of one from the other — which is what keeps this a
|
|
18
|
-
* resolver rather than a heuristic.
|
|
19
|
-
*
|
|
20
|
-
* ## Mutual declaration
|
|
21
|
-
*
|
|
22
|
-
* Two adapters resolve against each other only when each names the other as a
|
|
23
|
-
* peer (`CapabilityMatrix.crossLanguageNamespace`). A one-sided declaration —
|
|
24
|
-
* or two unrelated adapters that happen to pick the same namespace `id` by
|
|
25
|
-
* accident — resolves nothing. This is deliberate: equality-only comparison
|
|
26
|
-
* makes an accidental id collision silent otherwise, and that is the exact
|
|
27
|
-
* failure this mechanism exists to prevent, arriving through its own door if
|
|
28
|
-
* declaration were not mutual.
|
|
29
|
-
*
|
|
30
|
-
* ## Ambiguity is the normal case, not the exception
|
|
31
|
-
*
|
|
32
|
-
* More than one candidate for a `qualifiedName`, with no stated basis to
|
|
33
|
-
* choose between them, is reported and resolves nothing — precision over
|
|
34
|
-
* recall, and the same rule `dup-ids.mjs` enforces on plain node identity.
|
|
35
|
-
*
|
|
36
|
-
* ## Resolution and provenance
|
|
37
|
-
*
|
|
38
|
-
* Every resolved edge is stamped `resolution: 1` (R1 — a name match between
|
|
39
|
-
* two adapters, neither of which type-checked the other's file) and
|
|
40
|
-
* `producedBy: RESOLVER_PRODUCED_BY`. Neither adapter produced this edge, and
|
|
41
|
-
* attributing it to one would make that adapter's own precision figures
|
|
42
|
-
* answer for a join it did not make.
|
|
2
|
+
* Cross-language declaration index (DEC-161): matches `rawTarget` to `qualifiedName` as independently-
|
|
3
|
+
* computed strings, never derived from each other. Requires mutual peer declaration or resolves nothing;
|
|
4
|
+
* ambiguity is reported, never guessed. Every resolved edge stamped R1, `RESOLVER_PRODUCED_BY`.
|
|
43
5
|
*/
|
|
44
6
|
/** Stamped on every edge this pass mints. Neither adapter's own id, on purpose. */
|
|
45
7
|
export const RESOLVER_PRODUCED_BY = "cross-language-resolver@1";
|
|
46
8
|
function isMutualPeer(a, b) {
|
|
47
9
|
return a.peers.includes(b.id) && b.peers.includes(a.id);
|
|
48
10
|
}
|
|
49
|
-
/**
|
|
50
|
-
|
|
51
|
-
* @param namespaceOf A batch's `producedBy` (`adapterId@version`) to its
|
|
52
|
-
* declared namespace, if any. The caller supplies this because a
|
|
53
|
-
* `CapabilityMatrix` is a per-adapter fact, not a per-batch one, and this
|
|
54
|
-
* pass is deliberately kept ignorant of how an adapter is instantiated.
|
|
55
|
-
*/
|
|
56
|
-
/**
|
|
57
|
-
* A batch's `unresolved` list, tolerating the producer that has never heard of
|
|
58
|
-
* the field.
|
|
59
|
-
*
|
|
60
|
-
* `normaliseBatch` — every batch's gatekeeper on the way to the store — treats
|
|
61
|
-
* `unresolved` as absent-means-none, and says why in its own comment: absent is
|
|
62
|
-
* what a producer not yet updated to report it sends. Adapters are versioned
|
|
63
|
-
* and released on their own cadence exactly so that can happen, so a batch this
|
|
64
|
-
* pass rejects is one the Normaliser would have accepted.
|
|
65
|
-
*
|
|
66
|
-
* This is the same unguarded `.length` that crashed a real `analyze` run
|
|
67
|
-
* (b9044b2), reported as the *adapter* failing while the adapter was returning
|
|
68
|
-
* over a thousand perfectly good nodes. This pass is not reachable from
|
|
69
|
-
* `analyze` today, so it was latent rather than live — which is a reason to
|
|
70
|
-
* close it while the reason is written down, not a reason to leave it.
|
|
71
|
-
*
|
|
72
|
-
* Absent and malformed stay different, the line the Normaliser draws too: a
|
|
73
|
-
* missing field is an older producer, a field holding a string is a broken one,
|
|
74
|
-
* and defaulting the second away would hide a real defect. The producer is
|
|
75
|
-
* named in the message because that is the one thing a reader needs and cannot
|
|
76
|
-
* recover from the stack.
|
|
77
|
-
*/
|
|
11
|
+
/** @param batches Every batch in this build. @param namespaceOf A batch's producedBy to its declared namespace, if any. */
|
|
12
|
+
/** A batch's `unresolved` list, absent-means-none (same as `normaliseBatch`) — but malformed is a real defect (crashed a real `analyze` run, b9044b2). */
|
|
78
13
|
function referencingRefs(batch) {
|
|
79
14
|
const raw = batch.unresolved;
|
|
80
15
|
if (raw === undefined || raw === null)
|
|
@@ -87,16 +22,13 @@ function referencingRefs(batch) {
|
|
|
87
22
|
return raw;
|
|
88
23
|
}
|
|
89
24
|
export function resolveCrossLanguage(batches, namespaceOf) {
|
|
90
|
-
// One entry per batch that
|
|
91
|
-
//
|
|
92
|
-
// of candidates nor a consumer of them.
|
|
25
|
+
// One entry per batch that declared a namespace — a batch with none
|
|
26
|
+
// contributes nothing to either side.
|
|
93
27
|
const declaring = batches
|
|
94
28
|
.map((batch) => ({ batch, namespace: namespaceOf(batch.producedBy) }))
|
|
95
29
|
.filter((entry) => entry.namespace !== undefined);
|
|
96
|
-
//
|
|
97
|
-
//
|
|
98
|
-
// would let two same-language batches silently stand in for each other,
|
|
99
|
-
// which is not a claim this pass is entitled to make.
|
|
30
|
+
// Scoped to ONE declaring batch at a time, never pooled across batches
|
|
31
|
+
// sharing a namespace id — pooling would let them silently stand in for each other.
|
|
100
32
|
const resolved = [];
|
|
101
33
|
const ambiguous = [];
|
|
102
34
|
for (const referencing of declaring) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cross-language.js","sourceRoot":"","sources":["../../src/graph/cross-language.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"cross-language.js","sourceRoot":"","sources":["../../src/graph/cross-language.ts"],"names":[],"mappings":"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"}
|