@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
package/dist/graph/merge.d.ts
CHANGED
|
@@ -1,41 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* construction: `hash(from, to, type)` deliberately excludes resolution,
|
|
6
|
-
* confidence and producer. On the prior-art graphs measured for this build, 30%
|
|
7
|
-
* of edges were exact duplicates, so this is the common path rather than an
|
|
8
|
-
* edge case.
|
|
9
|
-
*
|
|
10
|
-
* ## The rule
|
|
11
|
-
*
|
|
12
|
-
* higher `resolution` wins
|
|
13
|
-
* → tie: higher `confidence` wins
|
|
14
|
-
* → tie: lexicographically smaller `producedBy` wins
|
|
15
|
-
*
|
|
16
|
-
* ## What the rule refuses to do
|
|
17
|
-
*
|
|
18
|
-
* **Confidence is never combined.** Two adapters each 0.8 confident does not
|
|
19
|
-
* make 0.96, or 0.8, or anything else — there is no evidence-combination model
|
|
20
|
-
* here, the two adapters are not independent observers, and inventing a formula
|
|
21
|
-
* would silently move every impact score in §12.4 with nothing in the output to
|
|
22
|
-
* show it happened. Corroboration is recorded as a fact (`attrs.corroboratedBy`)
|
|
23
|
-
* rather than folded into a number.
|
|
24
|
-
*
|
|
25
|
-
* The third tie-break exists only to make the result independent of the order
|
|
26
|
-
* batches arrive in. Lexicographic order is arbitrary; determinism is not.
|
|
27
|
-
*
|
|
28
|
-
* ## Why the rule is written twice
|
|
29
|
-
*
|
|
30
|
-
* The merge has to hold in two places: in memory, when the Graph Builder folds
|
|
31
|
-
* several batches together, and in SQL, when a later batch upserts onto an edge
|
|
32
|
-
* an earlier one already wrote. A rule enforced in only the first is not
|
|
33
|
-
* enforced at all, because the writer is reachable directly.
|
|
34
|
-
*
|
|
35
|
-
* So it appears as a TypeScript predicate and as a SQL `WHERE` fragment, side by
|
|
36
|
-
* side, with a differential test that runs the same case table through both.
|
|
37
|
-
* Two copies with a test that they agree beats one copy that only covers one of
|
|
38
|
-
* the two paths.
|
|
2
|
+
* Merge policy (DEC-012): higher `resolution` wins, then `confidence`, then smaller `producedBy`.
|
|
3
|
+
* Confidence is never combined — recorded as `attrs.corroboratedBy` instead of folded into a number.
|
|
4
|
+
* Enforced twice, TypeScript predicate + SQL `WHERE` fragment, with a differential test proving they agree.
|
|
39
5
|
*/
|
|
40
6
|
import type { IREdge, IRNode } from "@descryy/ir";
|
|
41
7
|
/** The fields the merge decides between. Both the graph and a stored row satisfy it. */
|
|
@@ -44,64 +10,18 @@ export interface Mergeable {
|
|
|
44
10
|
readonly confidence: number;
|
|
45
11
|
readonly producedBy: string;
|
|
46
12
|
}
|
|
47
|
-
/**
|
|
48
|
-
* Should `incoming` replace `existing`?
|
|
49
|
-
*
|
|
50
|
-
* Strict: an exact tie on all three keeps what is already there, so re-ingesting
|
|
51
|
-
* the same batch is a no-op rather than a rewrite.
|
|
52
|
-
*/
|
|
13
|
+
/** Should `incoming` replace `existing`? Strict: an exact tie keeps what's there — re-ingest is a no-op. */
|
|
53
14
|
export declare function preferIncoming(incoming: Mergeable, existing: Mergeable): boolean;
|
|
54
|
-
/**
|
|
55
|
-
* The same rule as a SQL `WHERE` clause on an upsert's `DO UPDATE`.
|
|
56
|
-
*
|
|
57
|
-
* `excluded` is the incoming row, `edges` the one already stored — SQLite's
|
|
58
|
-
* upsert names them that way. Kept adjacent to `preferIncoming` on purpose:
|
|
59
|
-
* `merge.test.ts` runs one case table through both and fails if they disagree.
|
|
60
|
-
*/
|
|
15
|
+
/** Same rule as SQL `WHERE` on an upsert. `excluded` = incoming, `edges` = stored; `merge.test.ts` checks both agree. */
|
|
61
16
|
export declare const EDGE_MERGE_CONDITION = "\n excluded.resolution > edges.resolution\n OR (excluded.resolution = edges.resolution AND excluded.confidence > edges.confidence)\n OR (excluded.resolution = edges.resolution\n AND excluded.confidence = edges.confidence\n AND excluded.produced_by < edges.produced_by)\n";
|
|
62
17
|
/** The same, for nodes. Nodes carry no confidence, so the middle key drops out. */
|
|
63
18
|
export declare const NODE_MERGE_CONDITION = "\n excluded.resolution > nodes.resolution\n OR (excluded.resolution = nodes.resolution AND excluded.produced_by < nodes.produced_by)\n";
|
|
64
|
-
/**
|
|
65
|
-
* Producers that corroborated a merged item, sorted and de-duplicated.
|
|
66
|
-
*
|
|
67
|
-
* DEC-012 records this instead of combining confidence. It is not decoration:
|
|
68
|
-
* "two independent adapters agree" is a materially different statement from "one
|
|
69
|
-
* adapter is fairly sure", and it is the only form in which the graph can carry
|
|
70
|
-
* that distinction without inventing an evidence model.
|
|
71
|
-
*/
|
|
19
|
+
/** Producers that corroborated a merged item, sorted/deduped. DEC-012 records this instead of combining confidence. */
|
|
72
20
|
export declare function corroborators(existing: Readonly<Record<string, unknown>> | undefined, ...producers: string[]): string[];
|
|
73
21
|
/** Merge two edges that share an id. Returns the winner, carrying corroboration. */
|
|
74
22
|
export declare function mergeEdge(incoming: IREdge, existing: IREdge): IREdge;
|
|
75
|
-
/**
|
|
76
|
-
* Merge two nodes that share an id.
|
|
77
|
-
*
|
|
78
|
-
* DEC-012's original text ("attrs are NOT unioned … pooling two adapters'
|
|
79
|
-
* attributes would produce a node describing a thing that does not exist")
|
|
80
|
-
* was written for two *language adapters* disagreeing about one symbol, where
|
|
81
|
-
* pooling really would invent a hybrid fact. `mark_incident` (UAT round 3, B2)
|
|
82
|
-
* showed a second, disjoint shape: `git-history` and `confirmed-incidents`
|
|
83
|
-
* mint the same `FILE` node with entirely non-overlapping key sets, and the
|
|
84
|
-
* old all-or-nothing rule silently deleted `changeCount` every time the
|
|
85
|
-
* incident node happened to win the tie-break.
|
|
86
|
-
*
|
|
87
|
-
* Superseding text (documents/decisions-inbox/DEC-NEXT-union-non-conflicting-node-attrs.md):
|
|
88
|
-
* start from the winner's attrs, add every key only the loser defines, and
|
|
89
|
-
* where both define a key with *different* values, keep the winner's value —
|
|
90
|
-
* no value is ever combined or invented, DEC-012's real commitment — and
|
|
91
|
-
* record the key in `attrs.disputedAttrs` (sorted) instead of silently
|
|
92
|
-
* dropping the disagreement. This is commutative in the keys it touches, so
|
|
93
|
-
* the order-independence the tie-break exists for is unaffected.
|
|
94
|
-
*/
|
|
23
|
+
/** Merge two nodes sharing an id. Unions non-conflicting attrs; on conflict keeps the winner's value and records the key in `attrs.disputedAttrs`. Supersedes DEC-012's all-or-nothing rule. */
|
|
95
24
|
export declare function mergeNode(incoming: IRNode, existing: IRNode): IRNode;
|
|
96
|
-
/**
|
|
97
|
-
* The fields two nodes sharing an id must agree on.
|
|
98
|
-
*
|
|
99
|
-
* Compared as one opaque string rather than field by field. That is not only
|
|
100
|
-
* tidier: `n.language !== m.language` reads to the boundary lint as branching on
|
|
101
|
-
* a language, and the lint is right to be suspicious — the exception here is
|
|
102
|
-
* that this asks whether two nodes *disagree*, never which language either one
|
|
103
|
-
* is. Folding both fields into a fingerprint states that intent in the code
|
|
104
|
-
* rather than in a lint suppression.
|
|
105
|
-
*/
|
|
25
|
+
/** Fields two nodes sharing an id must agree on. Compared as one opaque string — field-by-field would read as branching on language to the boundary lint. */
|
|
106
26
|
export declare function identityFingerprint(node: IRNode): string;
|
|
107
27
|
//# sourceMappingURL=merge.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/graph/merge.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/graph/merge.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAElD,wFAAwF;AACxF,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,4GAA4G;AAC5G,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,GAAG,OAAO,CAQhF;AAED,yHAAyH;AACzH,eAAO,MAAM,oBAAoB,gSAMhC,CAAC;AAEF,mFAAmF;AACnF,eAAO,MAAM,oBAAoB,6IAGhC,CAAC;AAEF,uHAAuH;AACvH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,EACvD,GAAG,SAAS,EAAE,MAAM,EAAE,GACrB,MAAM,EAAE,CAKV;AAED,oFAAoF;AACpF,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAWpE;AAKD,gMAAgM;AAChM,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAkCpE;AAED,6JAA6J;AAC7J,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExD"}
|
package/dist/graph/merge.js
CHANGED
|
@@ -1,48 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* construction: `hash(from, to, type)` deliberately excludes resolution,
|
|
6
|
-
* confidence and producer. On the prior-art graphs measured for this build, 30%
|
|
7
|
-
* of edges were exact duplicates, so this is the common path rather than an
|
|
8
|
-
* edge case.
|
|
9
|
-
*
|
|
10
|
-
* ## The rule
|
|
11
|
-
*
|
|
12
|
-
* higher `resolution` wins
|
|
13
|
-
* → tie: higher `confidence` wins
|
|
14
|
-
* → tie: lexicographically smaller `producedBy` wins
|
|
15
|
-
*
|
|
16
|
-
* ## What the rule refuses to do
|
|
17
|
-
*
|
|
18
|
-
* **Confidence is never combined.** Two adapters each 0.8 confident does not
|
|
19
|
-
* make 0.96, or 0.8, or anything else — there is no evidence-combination model
|
|
20
|
-
* here, the two adapters are not independent observers, and inventing a formula
|
|
21
|
-
* would silently move every impact score in §12.4 with nothing in the output to
|
|
22
|
-
* show it happened. Corroboration is recorded as a fact (`attrs.corroboratedBy`)
|
|
23
|
-
* rather than folded into a number.
|
|
24
|
-
*
|
|
25
|
-
* The third tie-break exists only to make the result independent of the order
|
|
26
|
-
* batches arrive in. Lexicographic order is arbitrary; determinism is not.
|
|
27
|
-
*
|
|
28
|
-
* ## Why the rule is written twice
|
|
29
|
-
*
|
|
30
|
-
* The merge has to hold in two places: in memory, when the Graph Builder folds
|
|
31
|
-
* several batches together, and in SQL, when a later batch upserts onto an edge
|
|
32
|
-
* an earlier one already wrote. A rule enforced in only the first is not
|
|
33
|
-
* enforced at all, because the writer is reachable directly.
|
|
34
|
-
*
|
|
35
|
-
* So it appears as a TypeScript predicate and as a SQL `WHERE` fragment, side by
|
|
36
|
-
* side, with a differential test that runs the same case table through both.
|
|
37
|
-
* Two copies with a test that they agree beats one copy that only covers one of
|
|
38
|
-
* the two paths.
|
|
39
|
-
*/
|
|
40
|
-
/**
|
|
41
|
-
* Should `incoming` replace `existing`?
|
|
42
|
-
*
|
|
43
|
-
* Strict: an exact tie on all three keeps what is already there, so re-ingesting
|
|
44
|
-
* the same batch is a no-op rather than a rewrite.
|
|
2
|
+
* Merge policy (DEC-012): higher `resolution` wins, then `confidence`, then smaller `producedBy`.
|
|
3
|
+
* Confidence is never combined — recorded as `attrs.corroboratedBy` instead of folded into a number.
|
|
4
|
+
* Enforced twice, TypeScript predicate + SQL `WHERE` fragment, with a differential test proving they agree.
|
|
45
5
|
*/
|
|
6
|
+
/** Should `incoming` replace `existing`? Strict: an exact tie keeps what's there — re-ingest is a no-op. */
|
|
46
7
|
export function preferIncoming(incoming, existing) {
|
|
47
8
|
if (incoming.resolution !== existing.resolution) {
|
|
48
9
|
return incoming.resolution > existing.resolution;
|
|
@@ -52,13 +13,7 @@ export function preferIncoming(incoming, existing) {
|
|
|
52
13
|
}
|
|
53
14
|
return incoming.producedBy < existing.producedBy;
|
|
54
15
|
}
|
|
55
|
-
/**
|
|
56
|
-
* The same rule as a SQL `WHERE` clause on an upsert's `DO UPDATE`.
|
|
57
|
-
*
|
|
58
|
-
* `excluded` is the incoming row, `edges` the one already stored — SQLite's
|
|
59
|
-
* upsert names them that way. Kept adjacent to `preferIncoming` on purpose:
|
|
60
|
-
* `merge.test.ts` runs one case table through both and fails if they disagree.
|
|
61
|
-
*/
|
|
16
|
+
/** Same rule as SQL `WHERE` on an upsert. `excluded` = incoming, `edges` = stored; `merge.test.ts` checks both agree. */
|
|
62
17
|
export const EDGE_MERGE_CONDITION = `
|
|
63
18
|
excluded.resolution > edges.resolution
|
|
64
19
|
OR (excluded.resolution = edges.resolution AND excluded.confidence > edges.confidence)
|
|
@@ -71,14 +26,7 @@ export const NODE_MERGE_CONDITION = `
|
|
|
71
26
|
excluded.resolution > nodes.resolution
|
|
72
27
|
OR (excluded.resolution = nodes.resolution AND excluded.produced_by < nodes.produced_by)
|
|
73
28
|
`;
|
|
74
|
-
/**
|
|
75
|
-
* Producers that corroborated a merged item, sorted and de-duplicated.
|
|
76
|
-
*
|
|
77
|
-
* DEC-012 records this instead of combining confidence. It is not decoration:
|
|
78
|
-
* "two independent adapters agree" is a materially different statement from "one
|
|
79
|
-
* adapter is fairly sure", and it is the only form in which the graph can carry
|
|
80
|
-
* that distinction without inventing an evidence model.
|
|
81
|
-
*/
|
|
29
|
+
/** Producers that corroborated a merged item, sorted/deduped. DEC-012 records this instead of combining confidence. */
|
|
82
30
|
export function corroborators(existing, ...producers) {
|
|
83
31
|
const prior = existing?.["corroboratedBy"];
|
|
84
32
|
const all = new Set(Array.isArray(prior) ? prior : []);
|
|
@@ -95,32 +43,9 @@ export function mergeEdge(incoming, existing) {
|
|
|
95
43
|
attrs: { ...(winner.attrs ?? {}), corroboratedBy },
|
|
96
44
|
};
|
|
97
45
|
}
|
|
98
|
-
/**
|
|
99
|
-
* Bookkeeping keys `mergeNode` itself writes. Never unioned or disputed as
|
|
100
|
-
* ordinary data — they are the merge's own record, recomputed on every call
|
|
101
|
-
* from both sides' history rather than carried over as a plain attr.
|
|
102
|
-
*/
|
|
46
|
+
/** Bookkeeping keys `mergeNode` itself writes — never unioned/disputed as ordinary data, always recomputed. */
|
|
103
47
|
const MERGE_BOOKKEEPING_KEYS = new Set(["corroboratedBy", "disputedAttrs"]);
|
|
104
|
-
/**
|
|
105
|
-
* Merge two nodes that share an id.
|
|
106
|
-
*
|
|
107
|
-
* DEC-012's original text ("attrs are NOT unioned … pooling two adapters'
|
|
108
|
-
* attributes would produce a node describing a thing that does not exist")
|
|
109
|
-
* was written for two *language adapters* disagreeing about one symbol, where
|
|
110
|
-
* pooling really would invent a hybrid fact. `mark_incident` (UAT round 3, B2)
|
|
111
|
-
* showed a second, disjoint shape: `git-history` and `confirmed-incidents`
|
|
112
|
-
* mint the same `FILE` node with entirely non-overlapping key sets, and the
|
|
113
|
-
* old all-or-nothing rule silently deleted `changeCount` every time the
|
|
114
|
-
* incident node happened to win the tie-break.
|
|
115
|
-
*
|
|
116
|
-
* Superseding text (documents/decisions-inbox/DEC-NEXT-union-non-conflicting-node-attrs.md):
|
|
117
|
-
* start from the winner's attrs, add every key only the loser defines, and
|
|
118
|
-
* where both define a key with *different* values, keep the winner's value —
|
|
119
|
-
* no value is ever combined or invented, DEC-012's real commitment — and
|
|
120
|
-
* record the key in `attrs.disputedAttrs` (sorted) instead of silently
|
|
121
|
-
* dropping the disagreement. This is commutative in the keys it touches, so
|
|
122
|
-
* the order-independence the tie-break exists for is unaffected.
|
|
123
|
-
*/
|
|
48
|
+
/** Merge two nodes sharing an id. Unions non-conflicting attrs; on conflict keeps the winner's value and records the key in `attrs.disputedAttrs`. Supersedes DEC-012's all-or-nothing rule. */
|
|
124
49
|
export function mergeNode(incoming, existing) {
|
|
125
50
|
const winner = preferIncoming({ ...incoming, confidence: 0 }, { ...existing, confidence: 0 })
|
|
126
51
|
? incoming
|
|
@@ -149,16 +74,7 @@ export function mergeNode(incoming, existing) {
|
|
|
149
74
|
},
|
|
150
75
|
};
|
|
151
76
|
}
|
|
152
|
-
/**
|
|
153
|
-
* The fields two nodes sharing an id must agree on.
|
|
154
|
-
*
|
|
155
|
-
* Compared as one opaque string rather than field by field. That is not only
|
|
156
|
-
* tidier: `n.language !== m.language` reads to the boundary lint as branching on
|
|
157
|
-
* a language, and the lint is right to be suspicious — the exception here is
|
|
158
|
-
* that this asks whether two nodes *disagree*, never which language either one
|
|
159
|
-
* is. Folding both fields into a fingerprint states that intent in the code
|
|
160
|
-
* rather than in a lint suppression.
|
|
161
|
-
*/
|
|
77
|
+
/** Fields two nodes sharing an id must agree on. Compared as one opaque string — field-by-field would read as branching on language to the boundary lint. */
|
|
162
78
|
export function identityFingerprint(node) {
|
|
163
79
|
return JSON.stringify([node.type, node.language]);
|
|
164
80
|
}
|
package/dist/graph/merge.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge.js","sourceRoot":"","sources":["../../src/graph/merge.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"merge.js","sourceRoot":"","sources":["../../src/graph/merge.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,55 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `observed_tests` —
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* layer §20 separates *"what I actually verified"* from *"how sure am I"*, and
|
|
6
|
-
* the five report categories say nothing about the first. This module is the
|
|
7
|
-
* carrier for that separation, ruled in
|
|
8
|
-
* `documents/decisions-inbox/DEC-NEXT-test-run-coverage-has-no-carrier.md`.
|
|
9
|
-
*
|
|
10
|
-
* ## Why this is a table and not an R4 edge promotion
|
|
11
|
-
*
|
|
12
|
-
* The obvious-looking design is to run the suite and promote each `TESTS` edge
|
|
13
|
-
* it exercised to R4, reusing {@link applyRuntimeObservations}. That is not
|
|
14
|
-
* available, and the reason is the same one `observe-runtime.ts`'s header
|
|
15
|
-
* already gives for refusing to derive edges from correlated evidence.
|
|
16
|
-
*
|
|
17
|
-
* An edge needs **two endpoints and a witnessed relationship between them**. A
|
|
18
|
-
* test-runner's evidence carries no stack — every item it emits has
|
|
19
|
-
* `stackTrace: null` — so an observed test names exactly one node, its own
|
|
20
|
-
* `TEST_CASE`. Nothing in the run witnesses which function that test reached.
|
|
21
|
-
* Pairing the test with a function that merely co-occurred in the same run
|
|
22
|
-
* would mint an edge from temporal coincidence, which is precisely the
|
|
23
|
-
* wrong-direction failure rule 2 exists to prevent, arriving through the one
|
|
24
|
-
* mechanism built to make the graph *more* trustworthy.
|
|
25
|
-
*
|
|
26
|
-
* So the honest fact a test run establishes is a fact about **one node**: this
|
|
27
|
-
* test case executed, and this is what happened. That is not an edge and R4 in
|
|
28
|
-
* this store is a property of an edge, so it needs a carrier of its own.
|
|
29
|
-
*
|
|
30
|
-
* ## Why EARNED
|
|
31
|
-
*
|
|
32
|
-
* Same argument as `observed_edges`, one step over. Nothing in the source says
|
|
33
|
-
* which tests ran — the source says which tests *exist*. A rebuild that dropped
|
|
34
|
-
* this table would silently turn "what I actually verified" back into "what
|
|
35
|
-
* might be affected", which is the exact collapse the coverage axis exists to
|
|
36
|
-
* prevent.
|
|
37
|
-
*
|
|
38
|
-
* ## What this module refuses to do
|
|
39
|
-
*
|
|
40
|
-
* - **Invent a node.** An observation naming a node this graph does not hold is
|
|
41
|
-
* refused with its reason, never created — rule 2, and the same posture
|
|
42
|
-
* {@link applyRuntimeObservations} takes for an edge endpoint.
|
|
43
|
-
* - **Accept a category error.** A test outcome against a node that is not a
|
|
44
|
-
* `TEST_CASE` is refused rather than written. The graph holds the id, so this
|
|
45
|
-
* is not a missing-node refusal; it is a claim that would make every later
|
|
46
|
-
* coverage read meaningless, and it is far more likely to be a resolver bug
|
|
47
|
-
* than a real observation.
|
|
48
|
-
* - **Judge anything.** No finding, no hypothesis, no report category. It
|
|
49
|
-
* records what ran; whether that is *enough* is a judgement for a layer above
|
|
50
|
-
* this one.
|
|
51
|
-
*
|
|
52
|
-
* @see `packages/core/src/graph/runtime-confirmation.ts` — the edge half.
|
|
2
|
+
* `observed_tests` — EARNED record of which tests ran (coverage axis, separate from confidence per AI layer §20; DEC-NEXT-test-run-coverage-has-no-carrier).
|
|
3
|
+
* Not an R4 edge promotion: a runner's evidence has no stack trace, so it witnesses only its own TEST_CASE node, never which function it reached — pairing on co-occurrence would mint an edge from coincidence (rule 2).
|
|
4
|
+
* EARNED because source says which tests exist, never which ran. Refuses to invent a node, accept a non-TEST_CASE target, or judge anything.
|
|
53
5
|
*/
|
|
54
6
|
import type { SqlDriver } from "../store/driver/driver.ts";
|
|
55
7
|
/** What a runner reported for one test. `skipped` covers `.skip` and `.todo` alike. */
|
|
@@ -57,14 +9,8 @@ export type ObservedTestOutcome = "passed" | "failed" | "skipped";
|
|
|
57
9
|
export interface ObservedTestObservation {
|
|
58
10
|
/** The `TEST_CASE` node this test resolved to. Resolution happens above this module. */
|
|
59
11
|
readonly nodeId: string;
|
|
60
|
-
/**
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
* Stored even though `nodeId` already identifies the test, because the two
|
|
64
|
-
* can disagree later: the node id survives a rename, the recorded name is
|
|
65
|
-
* what the run actually printed, and a reader comparing them is how a
|
|
66
|
-
* mis-resolution becomes visible instead of silently plausible.
|
|
67
|
-
*/
|
|
12
|
+
/** Runner's own suite-prefixed name, kept verbatim. Stored alongside nodeId
|
|
13
|
+
* so a later mismatch (rename vs. printed name) becomes visible. */
|
|
68
14
|
readonly qualifiedName: string;
|
|
69
15
|
readonly outcome: ObservedTestOutcome;
|
|
70
16
|
/** Null when the runner did not report one — never defaulted to zero, which would read as "instant". */
|
|
@@ -101,15 +47,8 @@ export interface ObservedTestRow {
|
|
|
101
47
|
export interface Clock {
|
|
102
48
|
now(): number;
|
|
103
49
|
}
|
|
104
|
-
/**
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
* Total over its input: every observation lands in exactly one of
|
|
108
|
-
* {@link ObservedTestsResult.recorded} or {@link ObservedTestsResult.refused},
|
|
109
|
-
* so a caller can account for all of them without inspecting the store. Never
|
|
110
|
-
* throws for an observation it cannot act on — that is a refusal, per the
|
|
111
|
-
* five-result-states rule the tool contract applies one layer up.
|
|
112
|
-
*/
|
|
50
|
+
/** Record a run's test observations. Total over its input: every observation
|
|
51
|
+
* lands in `recorded` or `refused`. Never throws — a refusal instead. */
|
|
113
52
|
export declare function applyObservedTests(driver: SqlDriver, input: ObservedTestsInput, clock?: Clock): ObservedTestsResult;
|
|
114
53
|
/** Read the EARNED ledger, newest observation first, optionally for one run. */
|
|
115
54
|
export declare function observedTests(driver: SqlDriver, options?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observed-tests.d.ts","sourceRoot":"","sources":["../../src/graph/observed-tests.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"observed-tests.d.ts","sourceRoot":"","sources":["../../src/graph/observed-tests.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAE3D,uFAAuF;AACvF,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAElE,MAAM,WAAW,uBAAuB;IACtC,wFAAwF;IACxF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;yEACqE;IACrE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;IACtC,wGAAwG;IACxG,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,kBAAkB;IACjC,uFAAuF;IACvF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,0HAA0H;IAC1H,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,SAAS,uBAAuB,EAAE,CAAC;CAC3D;AAED,oFAAoF;AACpF,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,mBAAmB;IAClC,wBAAwB;IACxB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,SAAS,mBAAmB,EAAE,CAAC;CAClD;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;IACtC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,gGAAgG;AAChG,MAAM,WAAW,KAAK;IACpB,GAAG,IAAI,MAAM,CAAC;CACf;AAaD;0EAC0E;AAC1E,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,kBAAkB,EACzB,KAAK,GAAE,KAAoB,GAC1B,mBAAmB,CAqDrB;AAED,gFAAgF;AAChF,wBAAgB,aAAa,CAC3B,MAAM,EAAE,SAAS,EACjB,OAAO,GAAE;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GACxC,SAAS,eAAe,EAAE,CA0B5B"}
|
|
@@ -1,70 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `observed_tests` —
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* layer §20 separates *"what I actually verified"* from *"how sure am I"*, and
|
|
6
|
-
* the five report categories say nothing about the first. This module is the
|
|
7
|
-
* carrier for that separation, ruled in
|
|
8
|
-
* `documents/decisions-inbox/DEC-NEXT-test-run-coverage-has-no-carrier.md`.
|
|
9
|
-
*
|
|
10
|
-
* ## Why this is a table and not an R4 edge promotion
|
|
11
|
-
*
|
|
12
|
-
* The obvious-looking design is to run the suite and promote each `TESTS` edge
|
|
13
|
-
* it exercised to R4, reusing {@link applyRuntimeObservations}. That is not
|
|
14
|
-
* available, and the reason is the same one `observe-runtime.ts`'s header
|
|
15
|
-
* already gives for refusing to derive edges from correlated evidence.
|
|
16
|
-
*
|
|
17
|
-
* An edge needs **two endpoints and a witnessed relationship between them**. A
|
|
18
|
-
* test-runner's evidence carries no stack — every item it emits has
|
|
19
|
-
* `stackTrace: null` — so an observed test names exactly one node, its own
|
|
20
|
-
* `TEST_CASE`. Nothing in the run witnesses which function that test reached.
|
|
21
|
-
* Pairing the test with a function that merely co-occurred in the same run
|
|
22
|
-
* would mint an edge from temporal coincidence, which is precisely the
|
|
23
|
-
* wrong-direction failure rule 2 exists to prevent, arriving through the one
|
|
24
|
-
* mechanism built to make the graph *more* trustworthy.
|
|
25
|
-
*
|
|
26
|
-
* So the honest fact a test run establishes is a fact about **one node**: this
|
|
27
|
-
* test case executed, and this is what happened. That is not an edge and R4 in
|
|
28
|
-
* this store is a property of an edge, so it needs a carrier of its own.
|
|
29
|
-
*
|
|
30
|
-
* ## Why EARNED
|
|
31
|
-
*
|
|
32
|
-
* Same argument as `observed_edges`, one step over. Nothing in the source says
|
|
33
|
-
* which tests ran — the source says which tests *exist*. A rebuild that dropped
|
|
34
|
-
* this table would silently turn "what I actually verified" back into "what
|
|
35
|
-
* might be affected", which is the exact collapse the coverage axis exists to
|
|
36
|
-
* prevent.
|
|
37
|
-
*
|
|
38
|
-
* ## What this module refuses to do
|
|
39
|
-
*
|
|
40
|
-
* - **Invent a node.** An observation naming a node this graph does not hold is
|
|
41
|
-
* refused with its reason, never created — rule 2, and the same posture
|
|
42
|
-
* {@link applyRuntimeObservations} takes for an edge endpoint.
|
|
43
|
-
* - **Accept a category error.** A test outcome against a node that is not a
|
|
44
|
-
* `TEST_CASE` is refused rather than written. The graph holds the id, so this
|
|
45
|
-
* is not a missing-node refusal; it is a claim that would make every later
|
|
46
|
-
* coverage read meaningless, and it is far more likely to be a resolver bug
|
|
47
|
-
* than a real observation.
|
|
48
|
-
* - **Judge anything.** No finding, no hypothesis, no report category. It
|
|
49
|
-
* records what ran; whether that is *enough* is a judgement for a layer above
|
|
50
|
-
* this one.
|
|
51
|
-
*
|
|
52
|
-
* @see `packages/core/src/graph/runtime-confirmation.ts` — the edge half.
|
|
2
|
+
* `observed_tests` — EARNED record of which tests ran (coverage axis, separate from confidence per AI layer §20; DEC-NEXT-test-run-coverage-has-no-carrier).
|
|
3
|
+
* Not an R4 edge promotion: a runner's evidence has no stack trace, so it witnesses only its own TEST_CASE node, never which function it reached — pairing on co-occurrence would mint an edge from coincidence (rule 2).
|
|
4
|
+
* EARNED because source says which tests exist, never which ran. Refuses to invent a node, accept a non-TEST_CASE target, or judge anything.
|
|
53
5
|
*/
|
|
54
6
|
const SYSTEM_CLOCK = { now: () => Date.now() };
|
|
55
7
|
function nodeTypeOf(driver, id) {
|
|
56
8
|
const row = driver.prepare("SELECT type FROM nodes WHERE id = ?").get(id);
|
|
57
9
|
return row?.type;
|
|
58
10
|
}
|
|
59
|
-
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* Total over its input: every observation lands in exactly one of
|
|
63
|
-
* {@link ObservedTestsResult.recorded} or {@link ObservedTestsResult.refused},
|
|
64
|
-
* so a caller can account for all of them without inspecting the store. Never
|
|
65
|
-
* throws for an observation it cannot act on — that is a refusal, per the
|
|
66
|
-
* five-result-states rule the tool contract applies one layer up.
|
|
67
|
-
*/
|
|
11
|
+
/** Record a run's test observations. Total over its input: every observation
|
|
12
|
+
* lands in `recorded` or `refused`. Never throws — a refusal instead. */
|
|
68
13
|
export function applyObservedTests(driver, input, clock = SYSTEM_CLOCK) {
|
|
69
14
|
const recorded = [];
|
|
70
15
|
const refused = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observed-tests.js","sourceRoot":"","sources":["../../src/graph/observed-tests.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"observed-tests.js","sourceRoot":"","sources":["../../src/graph/observed-tests.ts"],"names":[],"mappings":"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"}
|
package/dist/graph/persist.d.ts
CHANGED
|
@@ -1,29 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Writing a built graph back out, split by producer.
|
|
3
|
-
*
|
|
4
|
-
* `buildGraph` merges many producers into one graph; `writeBatch` invalidates
|
|
5
|
-
* and writes **one producer's** rows at a time, because DEC-014's invalidation
|
|
6
|
-
* rule is per-adapter — re-running the Python adapter must not evict the
|
|
7
|
-
* TypeScript adapter's rows. So the merged graph has to be partitioned back
|
|
8
|
-
* before it can be stored.
|
|
9
|
-
*
|
|
10
|
-
* That partition was written out by hand in every bench script that has ever
|
|
11
|
-
* stored a graph, identically, five times. It is not a measurement concern: it
|
|
12
|
-
* is the engine's own write path, and the MCP server needs it too. Lifted here
|
|
13
|
-
* so there is one copy and one place for it to be wrong.
|
|
14
|
-
*
|
|
15
|
-
* ## The subtlety worth stating
|
|
16
|
-
*
|
|
17
|
-
* The rows written for a producer are the **post-merge** ones, not the batch's
|
|
18
|
-
* originals. A node supplied by two adapters is merged (DEC-012) and the merged
|
|
19
|
-
* row carries the winning `producedBy`; writing the pre-merge originals would
|
|
20
|
-
* store the losing version under the loser's producer and then let the next
|
|
21
|
-
* incremental run resurrect it. Filtering the merged graph by `producedBy` is
|
|
22
|
-
* what makes the store agree with the builder.
|
|
23
|
-
*
|
|
24
|
-
* A batch that contributed nothing after the merge is still written, with empty
|
|
25
|
-
* rows, on purpose: that is how a re-run that *removes* a symbol evicts the row
|
|
26
|
-
* it used to own. Skipping empty batches would make deletions invisible.
|
|
2
|
+
* Writing a built graph back out, split by producer. `writeBatch` invalidates per-producer (DEC-014): re-running one adapter must not evict another's rows, so the merged graph is partitioned back before storing.
|
|
3
|
+
* Rows written are post-merge (DEC-012's winning `producedBy`), never pre-merge originals, or the loser gets resurrected next incremental run. An empty-after-merge batch is still written (empty rows) so a removed symbol's row gets evicted, not left invisible.
|
|
27
4
|
*/
|
|
28
5
|
import type { IRBatch } from "@descryy/ir";
|
|
29
6
|
import type { SqlDriver } from "../store/driver/driver.ts";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persist.d.ts","sourceRoot":"","sources":["../../src/graph/persist.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"persist.d.ts","sourceRoot":"","sources":["../../src/graph/persist.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAc,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACrF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC;IACxC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,4FAA4F;IAC5F,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,SAAS,OAAO,EAAE,EAC3B,KAAK,EAAE,WAAW,EAClB,OAAO,GAAE,YAAiB,GACzB,aAAa,CA6Bf"}
|
package/dist/graph/persist.js
CHANGED
|
@@ -1,29 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Writing a built graph back out, split by producer.
|
|
3
|
-
*
|
|
4
|
-
* `buildGraph` merges many producers into one graph; `writeBatch` invalidates
|
|
5
|
-
* and writes **one producer's** rows at a time, because DEC-014's invalidation
|
|
6
|
-
* rule is per-adapter — re-running the Python adapter must not evict the
|
|
7
|
-
* TypeScript adapter's rows. So the merged graph has to be partitioned back
|
|
8
|
-
* before it can be stored.
|
|
9
|
-
*
|
|
10
|
-
* That partition was written out by hand in every bench script that has ever
|
|
11
|
-
* stored a graph, identically, five times. It is not a measurement concern: it
|
|
12
|
-
* is the engine's own write path, and the MCP server needs it too. Lifted here
|
|
13
|
-
* so there is one copy and one place for it to be wrong.
|
|
14
|
-
*
|
|
15
|
-
* ## The subtlety worth stating
|
|
16
|
-
*
|
|
17
|
-
* The rows written for a producer are the **post-merge** ones, not the batch's
|
|
18
|
-
* originals. A node supplied by two adapters is merged (DEC-012) and the merged
|
|
19
|
-
* row carries the winning `producedBy`; writing the pre-merge originals would
|
|
20
|
-
* store the losing version under the loser's producer and then let the next
|
|
21
|
-
* incremental run resurrect it. Filtering the merged graph by `producedBy` is
|
|
22
|
-
* what makes the store agree with the builder.
|
|
23
|
-
*
|
|
24
|
-
* A batch that contributed nothing after the merge is still written, with empty
|
|
25
|
-
* rows, on purpose: that is how a re-run that *removes* a symbol evicts the row
|
|
26
|
-
* it used to own. Skipping empty batches would make deletions invisible.
|
|
2
|
+
* Writing a built graph back out, split by producer. `writeBatch` invalidates per-producer (DEC-014): re-running one adapter must not evict another's rows, so the merged graph is partitioned back before storing.
|
|
3
|
+
* Rows written are post-merge (DEC-012's winning `producedBy`), never pre-merge originals, or the loser gets resurrected next incremental run. An empty-after-merge batch is still written (empty rows) so a removed symbol's row gets evicted, not left invisible.
|
|
27
4
|
*/
|
|
28
5
|
import { writeBatch } from "../store/writer.js";
|
|
29
6
|
export function persistGraph(driver, batches, built, options = {}) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persist.js","sourceRoot":"","sources":["../../src/graph/persist.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"persist.js","sourceRoot":"","sources":["../../src/graph/persist.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,UAAU,EAAuC,MAAM,oBAAoB,CAAC;AAarF,MAAM,UAAU,YAAY,CAC1B,MAAiB,EACjB,OAA2B,EAC3B,KAAkB,EAClB,UAAwB,EAAE;IAE1B,MAAM,MAAM,GAAkB,EAAE,CAAC;IACjC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAElC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,CAAC,IAAI,CACT,UAAU,CACR,MAAM,EACN;YACE,GAAG,KAAK;YACR,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,KAAK,KAAK,CAAC,UAAU,CAAC;YACzE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,KAAK,KAAK,CAAC,UAAU,CAAC;YACzE,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,KAAK,KAAK,CAAC,UAAU,CAAC;SAClF,EACD,OAAO,CACR,CACF,CAAC;IACJ,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,MAAM;QAAE,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,YAAY;YAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAErF,OAAO;QACL,MAAM;QACN,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC;QAC5D,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC;QAC5D,iBAAiB,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,iBAAiB,EAAE,CAAC,CAAC;QACtE,YAAY,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,EAAE;QACjC,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC;KAC/D,CAAC;AACJ,CAAC"}
|