@descryy/core 0.1.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/LICENSE +21 -0
- package/dist/capabilities/index.d.ts +3 -0
- package/dist/capabilities/index.d.ts.map +1 -0
- package/dist/capabilities/index.js +2 -0
- package/dist/capabilities/index.js.map +1 -0
- package/dist/capabilities/preconditions.d.ts +99 -0
- package/dist/capabilities/preconditions.d.ts.map +1 -0
- package/dist/capabilities/preconditions.js +94 -0
- package/dist/capabilities/preconditions.js.map +1 -0
- package/dist/contracts/engine.d.ts +90 -0
- package/dist/contracts/engine.d.ts.map +1 -0
- package/dist/contracts/engine.js +291 -0
- package/dist/contracts/engine.js.map +1 -0
- package/dist/contracts/index.d.ts +9 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +5 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/contracts/orphans.d.ts +96 -0
- package/dist/contracts/orphans.d.ts.map +1 -0
- package/dist/contracts/orphans.js +241 -0
- package/dist/contracts/orphans.js.map +1 -0
- package/dist/contracts/paths.d.ts +132 -0
- package/dist/contracts/paths.d.ts.map +1 -0
- package/dist/contracts/paths.js +245 -0
- package/dist/contracts/paths.js.map +1 -0
- package/dist/contracts/shapes.d.ts +99 -0
- package/dist/contracts/shapes.d.ts.map +1 -0
- package/dist/contracts/shapes.js +196 -0
- package/dist/contracts/shapes.js.map +1 -0
- package/dist/governance/budget.d.ts +89 -0
- package/dist/governance/budget.d.ts.map +1 -0
- package/dist/governance/budget.js +101 -0
- package/dist/governance/budget.js.map +1 -0
- package/dist/governance/candidate-boundary.d.ts +49 -0
- package/dist/governance/candidate-boundary.d.ts.map +1 -0
- package/dist/governance/candidate-boundary.js +51 -0
- package/dist/governance/candidate-boundary.js.map +1 -0
- package/dist/governance/escalation.d.ts +63 -0
- package/dist/governance/escalation.d.ts.map +1 -0
- package/dist/governance/escalation.js +72 -0
- package/dist/governance/escalation.js.map +1 -0
- package/dist/governance/fact-boundary.d.ts +77 -0
- package/dist/governance/fact-boundary.d.ts.map +1 -0
- package/dist/governance/fact-boundary.js +91 -0
- package/dist/governance/fact-boundary.js.map +1 -0
- package/dist/governance/finding-funnel.d.ts +109 -0
- package/dist/governance/finding-funnel.d.ts.map +1 -0
- package/dist/governance/finding-funnel.js +137 -0
- package/dist/governance/finding-funnel.js.map +1 -0
- package/dist/governance/index.d.ts +11 -0
- package/dist/governance/index.d.ts.map +1 -0
- package/dist/governance/index.js +6 -0
- package/dist/governance/index.js.map +1 -0
- package/dist/graph/build.d.ts +127 -0
- package/dist/graph/build.d.ts.map +1 -0
- package/dist/graph/build.js +0 -0
- package/dist/graph/build.js.map +1 -0
- package/dist/graph/cross-language.d.ts +70 -0
- package/dist/graph/cross-language.d.ts.map +1 -0
- package/dist/graph/cross-language.js +104 -0
- package/dist/graph/cross-language.js.map +1 -0
- package/dist/graph/index.d.ts +11 -0
- package/dist/graph/index.d.ts.map +1 -0
- package/dist/graph/index.js +6 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph/merge.d.ts +95 -0
- package/dist/graph/merge.d.ts.map +1 -0
- package/dist/graph/merge.js +131 -0
- package/dist/graph/merge.js.map +1 -0
- package/dist/graph/persist.d.ts +42 -0
- package/dist/graph/persist.d.ts.map +1 -0
- package/dist/graph/persist.js +52 -0
- package/dist/graph/persist.js.map +1 -0
- package/dist/graph/runtime-confirmation.d.ts +169 -0
- package/dist/graph/runtime-confirmation.d.ts.map +1 -0
- package/dist/graph/runtime-confirmation.js +318 -0
- package/dist/graph/runtime-confirmation.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/ledger/index.d.ts +5 -0
- package/dist/ledger/index.d.ts.map +1 -0
- package/dist/ledger/index.js +3 -0
- package/dist/ledger/index.js.map +1 -0
- package/dist/ledger/mint.d.ts +81 -0
- package/dist/ledger/mint.d.ts.map +1 -0
- package/dist/ledger/mint.js +138 -0
- package/dist/ledger/mint.js.map +1 -0
- package/dist/ledger/resolve.d.ts +124 -0
- package/dist/ledger/resolve.d.ts.map +1 -0
- package/dist/ledger/resolve.js +290 -0
- package/dist/ledger/resolve.js.map +1 -0
- package/dist/multipr/fingerprint.d.ts +56 -0
- package/dist/multipr/fingerprint.d.ts.map +1 -0
- package/dist/multipr/fingerprint.js +169 -0
- package/dist/multipr/fingerprint.js.map +1 -0
- package/dist/multipr/hidden-dependency.d.ts +120 -0
- package/dist/multipr/hidden-dependency.d.ts.map +1 -0
- package/dist/multipr/hidden-dependency.js +185 -0
- package/dist/multipr/hidden-dependency.js.map +1 -0
- package/dist/multipr/index.d.ts +14 -0
- package/dist/multipr/index.d.ts.map +1 -0
- package/dist/multipr/index.js +8 -0
- package/dist/multipr/index.js.map +1 -0
- package/dist/multipr/mechanical.d.ts +239 -0
- package/dist/multipr/mechanical.d.ts.map +1 -0
- package/dist/multipr/mechanical.js +333 -0
- package/dist/multipr/mechanical.js.map +1 -0
- package/dist/multipr/migration-heads.d.ts +160 -0
- package/dist/multipr/migration-heads.d.ts.map +1 -0
- package/dist/multipr/migration-heads.js +212 -0
- package/dist/multipr/migration-heads.js.map +1 -0
- package/dist/multipr/overlap.d.ts +186 -0
- package/dist/multipr/overlap.d.ts.map +1 -0
- package/dist/multipr/overlap.js +254 -0
- package/dist/multipr/overlap.js.map +1 -0
- package/dist/multipr/scope-store.d.ts +105 -0
- package/dist/multipr/scope-store.d.ts.map +1 -0
- package/dist/multipr/scope-store.js +182 -0
- package/dist/multipr/scope-store.js.map +1 -0
- package/dist/multipr/superseded.d.ts +133 -0
- package/dist/multipr/superseded.d.ts.map +1 -0
- package/dist/multipr/superseded.js +128 -0
- package/dist/multipr/superseded.js.map +1 -0
- package/dist/query/confirmed-facts.d.ts +56 -0
- package/dist/query/confirmed-facts.d.ts.map +1 -0
- package/dist/query/confirmed-facts.js +64 -0
- package/dist/query/confirmed-facts.js.map +1 -0
- package/dist/query/declared-value-closure.d.ts +126 -0
- package/dist/query/declared-value-closure.d.ts.map +1 -0
- package/dist/query/declared-value-closure.js +156 -0
- package/dist/query/declared-value-closure.js.map +1 -0
- package/dist/query/index.d.ts +28 -0
- package/dist/query/index.d.ts.map +1 -0
- package/dist/query/index.js +15 -0
- package/dist/query/index.js.map +1 -0
- package/dist/query/memory.d.ts +20 -0
- package/dist/query/memory.d.ts.map +1 -0
- package/dist/query/memory.js +55 -0
- package/dist/query/memory.js.map +1 -0
- package/dist/query/provider.d.ts +127 -0
- package/dist/query/provider.d.ts.map +1 -0
- package/dist/query/provider.js +54 -0
- package/dist/query/provider.js.map +1 -0
- package/dist/query/queries.d.ts +119 -0
- package/dist/query/queries.d.ts.map +1 -0
- package/dist/query/queries.js +267 -0
- package/dist/query/queries.js.map +1 -0
- package/dist/query/refusal-fetch.d.ts +114 -0
- package/dist/query/refusal-fetch.d.ts.map +1 -0
- package/dist/query/refusal-fetch.js +200 -0
- package/dist/query/refusal-fetch.js.map +1 -0
- package/dist/query/refusal-questions.d.ts +123 -0
- package/dist/query/refusal-questions.d.ts.map +1 -0
- package/dist/query/refusal-questions.js +122 -0
- package/dist/query/refusal-questions.js.map +1 -0
- package/dist/query/root-cause-score.d.ts +218 -0
- package/dist/query/root-cause-score.d.ts.map +1 -0
- package/dist/query/root-cause-score.js +251 -0
- package/dist/query/root-cause-score.js.map +1 -0
- package/dist/query/row-closure-picture.d.ts +108 -0
- package/dist/query/row-closure-picture.d.ts.map +1 -0
- package/dist/query/row-closure-picture.js +131 -0
- package/dist/query/row-closure-picture.js.map +1 -0
- package/dist/query/similar-incidents.d.ts +76 -0
- package/dist/query/similar-incidents.d.ts.map +1 -0
- package/dist/query/similar-incidents.js +169 -0
- package/dist/query/similar-incidents.js.map +1 -0
- package/dist/query/sqlite.d.ts +13 -0
- package/dist/query/sqlite.d.ts.map +1 -0
- package/dist/query/sqlite.js +54 -0
- package/dist/query/sqlite.js.map +1 -0
- package/dist/query/traverse.d.ts +110 -0
- package/dist/query/traverse.d.ts.map +1 -0
- package/dist/query/traverse.js +0 -0
- package/dist/query/traverse.js.map +1 -0
- package/dist/query/unresolved.d.ts +195 -0
- package/dist/query/unresolved.d.ts.map +1 -0
- package/dist/query/unresolved.js +225 -0
- package/dist/query/unresolved.js.map +1 -0
- package/dist/query/verification-status.d.ts +134 -0
- package/dist/query/verification-status.d.ts.map +1 -0
- package/dist/query/verification-status.js +163 -0
- package/dist/query/verification-status.js.map +1 -0
- package/dist/recording/index.d.ts +26 -0
- package/dist/recording/index.d.ts.map +1 -0
- package/dist/recording/index.js +30 -0
- package/dist/recording/index.js.map +1 -0
- package/dist/recording/migrate.d.ts +22 -0
- package/dist/recording/migrate.d.ts.map +1 -0
- package/dist/recording/migrate.js +51 -0
- package/dist/recording/migrate.js.map +1 -0
- package/dist/recording/reader.d.ts +27 -0
- package/dist/recording/reader.d.ts.map +1 -0
- package/dist/recording/reader.js +55 -0
- package/dist/recording/reader.js.map +1 -0
- package/dist/recording/redact.d.ts +63 -0
- package/dist/recording/redact.d.ts.map +1 -0
- package/dist/recording/redact.js +98 -0
- package/dist/recording/redact.js.map +1 -0
- package/dist/recording/schema.d.ts +41 -0
- package/dist/recording/schema.d.ts.map +1 -0
- package/dist/recording/schema.js +104 -0
- package/dist/recording/schema.js.map +1 -0
- package/dist/recording/writer.d.ts +120 -0
- package/dist/recording/writer.d.ts.map +1 -0
- package/dist/recording/writer.js +81 -0
- package/dist/recording/writer.js.map +1 -0
- package/dist/scoping/fanout.d.ts +86 -0
- package/dist/scoping/fanout.d.ts.map +1 -0
- package/dist/scoping/fanout.js +95 -0
- package/dist/scoping/fanout.js.map +1 -0
- package/dist/scoping/index.d.ts +10 -0
- package/dist/scoping/index.d.ts.map +1 -0
- package/dist/scoping/index.js +6 -0
- package/dist/scoping/index.js.map +1 -0
- package/dist/scoping/score.d.ts +83 -0
- package/dist/scoping/score.d.ts.map +1 -0
- package/dist/scoping/score.js +125 -0
- package/dist/scoping/score.js.map +1 -0
- package/dist/scoping/tiers.d.ts +32 -0
- package/dist/scoping/tiers.d.ts.map +1 -0
- package/dist/scoping/tiers.js +35 -0
- package/dist/scoping/tiers.js.map +1 -0
- package/dist/scoping/traverse.d.ts +60 -0
- package/dist/scoping/traverse.d.ts.map +1 -0
- package/dist/scoping/traverse.js +172 -0
- package/dist/scoping/traverse.js.map +1 -0
- package/dist/scoping/weights.d.ts +97 -0
- package/dist/scoping/weights.d.ts.map +1 -0
- package/dist/scoping/weights.js +167 -0
- package/dist/scoping/weights.js.map +1 -0
- package/dist/sources/git/diff.d.ts +53 -0
- package/dist/sources/git/diff.d.ts.map +1 -0
- package/dist/sources/git/diff.js +140 -0
- package/dist/sources/git/diff.js.map +1 -0
- package/dist/sources/git/env.d.ts +2 -0
- package/dist/sources/git/env.d.ts.map +1 -0
- package/dist/sources/git/env.js +21 -0
- package/dist/sources/git/env.js.map +1 -0
- package/dist/sources/git/history.d.ts +140 -0
- package/dist/sources/git/history.d.ts.map +1 -0
- package/dist/sources/git/history.js +314 -0
- package/dist/sources/git/history.js.map +1 -0
- package/dist/sources/git/index.d.ts +7 -0
- package/dist/sources/git/index.d.ts.map +1 -0
- package/dist/sources/git/index.js +4 -0
- package/dist/sources/git/index.js.map +1 -0
- package/dist/sources/git/source.d.ts +95 -0
- package/dist/sources/git/source.d.ts.map +1 -0
- package/dist/sources/git/source.js +0 -0
- package/dist/sources/git/source.js.map +1 -0
- package/dist/sources/migrations/dialects.d.ts +59 -0
- package/dist/sources/migrations/dialects.d.ts.map +1 -0
- package/dist/sources/migrations/dialects.js +84 -0
- package/dist/sources/migrations/dialects.js.map +1 -0
- package/dist/sources/migrations/index.d.ts +3 -0
- package/dist/sources/migrations/index.d.ts.map +1 -0
- package/dist/sources/migrations/index.js +2 -0
- package/dist/sources/migrations/index.js.map +1 -0
- package/dist/sources/migrations/read.d.ts +113 -0
- package/dist/sources/migrations/read.d.ts.map +1 -0
- package/dist/sources/migrations/read.js +270 -0
- package/dist/sources/migrations/read.js.map +1 -0
- package/dist/sources/workspace/index.d.ts +3 -0
- package/dist/sources/workspace/index.d.ts.map +1 -0
- package/dist/sources/workspace/index.js +2 -0
- package/dist/sources/workspace/index.js.map +1 -0
- package/dist/sources/workspace/workspace.d.ts +64 -0
- package/dist/sources/workspace/workspace.d.ts.map +1 -0
- package/dist/sources/workspace/workspace.js +294 -0
- package/dist/sources/workspace/workspace.js.map +1 -0
- package/dist/store/driver/driver.d.ts +82 -0
- package/dist/store/driver/driver.d.ts.map +1 -0
- package/dist/store/driver/driver.js +31 -0
- package/dist/store/driver/driver.js.map +1 -0
- package/dist/store/driver/node-sqlite.d.ts +28 -0
- package/dist/store/driver/node-sqlite.d.ts.map +1 -0
- package/dist/store/driver/node-sqlite.js +188 -0
- package/dist/store/driver/node-sqlite.js.map +1 -0
- package/dist/store/index.d.ts +33 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +46 -0
- package/dist/store/index.js.map +1 -0
- package/dist/store/migrate.d.ts +68 -0
- package/dist/store/migrate.d.ts.map +1 -0
- package/dist/store/migrate.js +140 -0
- package/dist/store/migrate.js.map +1 -0
- package/dist/store/reader.d.ts +127 -0
- package/dist/store/reader.d.ts.map +1 -0
- package/dist/store/reader.js +269 -0
- package/dist/store/reader.js.map +1 -0
- package/dist/store/schema.d.ts +87 -0
- package/dist/store/schema.d.ts.map +1 -0
- package/dist/store/schema.js +322 -0
- package/dist/store/schema.js.map +1 -0
- package/dist/store/writer.d.ts +116 -0
- package/dist/store/writer.d.ts.map +1 -0
- package/dist/store/writer.js +279 -0
- package/dist/store/writer.js.map +1 -0
- package/dist/tiers/certify.d.ts +375 -0
- package/dist/tiers/certify.d.ts.map +1 -0
- package/dist/tiers/certify.js +434 -0
- package/dist/tiers/certify.js.map +1 -0
- package/dist/tiers/index.d.ts +5 -0
- package/dist/tiers/index.d.ts.map +1 -0
- package/dist/tiers/index.js +3 -0
- package/dist/tiers/index.js.map +1 -0
- package/dist/tiers/ladder.d.ts +73 -0
- package/dist/tiers/ladder.d.ts.map +1 -0
- package/dist/tiers/ladder.js +197 -0
- package/dist/tiers/ladder.js.map +1 -0
- package/dist/validation/config-graph.d.ts +104 -0
- package/dist/validation/config-graph.d.ts.map +1 -0
- package/dist/validation/config-graph.js +205 -0
- package/dist/validation/config-graph.js.map +1 -0
- package/dist/validation/env.d.ts +243 -0
- package/dist/validation/env.d.ts.map +1 -0
- package/dist/validation/env.js +447 -0
- package/dist/validation/env.js.map +1 -0
- package/dist/validation/index.d.ts +16 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/index.js +9 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/join-substitution.d.ts +186 -0
- package/dist/validation/join-substitution.d.ts.map +1 -0
- package/dist/validation/join-substitution.js +191 -0
- package/dist/validation/join-substitution.js.map +1 -0
- package/dist/validation/migrations.d.ts +133 -0
- package/dist/validation/migrations.d.ts.map +1 -0
- package/dist/validation/migrations.js +315 -0
- package/dist/validation/migrations.js.map +1 -0
- package/dist/validation/nodes.d.ts +32 -0
- package/dist/validation/nodes.d.ts.map +1 -0
- package/dist/validation/nodes.js +45 -0
- package/dist/validation/nodes.js.map +1 -0
- package/dist/validation/rollback.d.ts +124 -0
- package/dist/validation/rollback.d.ts.map +1 -0
- package/dist/validation/rollback.js +302 -0
- package/dist/validation/rollback.js.map +1 -0
- package/dist/validation/route-drift.d.ts +108 -0
- package/dist/validation/route-drift.d.ts.map +1 -0
- package/dist/validation/route-drift.js +103 -0
- package/dist/validation/route-drift.js.map +1 -0
- package/dist/validation/sources.d.ts +153 -0
- package/dist/validation/sources.d.ts.map +1 -0
- package/dist/validation/sources.js +409 -0
- package/dist/validation/sources.js.map +1 -0
- package/dist/worker/index.d.ts +5 -0
- package/dist/worker/index.d.ts.map +1 -0
- package/dist/worker/index.js +3 -0
- package/dist/worker/index.js.map +1 -0
- package/dist/worker/pool.d.ts +73 -0
- package/dist/worker/pool.d.ts.map +1 -0
- package/dist/worker/pool.js +203 -0
- package/dist/worker/pool.js.map +1 -0
- package/dist/worker/protocol.d.ts +91 -0
- package/dist/worker/protocol.d.ts.map +1 -0
- package/dist/worker/protocol.js +19 -0
- package/dist/worker/protocol.js.map +1 -0
- package/dist/worker/traversal.worker.d.ts +25 -0
- package/dist/worker/traversal.worker.d.ts.map +1 -0
- package/dist/worker/traversal.worker.js +124 -0
- package/dist/worker/traversal.worker.js.map +1 -0
- package/package.json +29 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scoring configuration for diff scoping — §12.4.
|
|
3
|
+
*
|
|
4
|
+
* ## The one number in the architecture that cannot be used as written
|
|
5
|
+
*
|
|
6
|
+
* §12.3's worked example decays a `CALLS` edge by **×1.0** on its first hop and
|
|
7
|
+
* by **×0.95** on its third. The 0.95 is the usable one; 1.0 is not, for two
|
|
8
|
+
* independent reasons:
|
|
9
|
+
*
|
|
10
|
+
* 1. **It breaks the premise of the whole engine.** §12.2 argues that hop count
|
|
11
|
+
* is a poor proxy for importance and that expansion must stop on *score*. An
|
|
12
|
+
* edge weight of 1.0 means a `CALLS` chain never decays — every node reachable
|
|
13
|
+
* by calls scores exactly 1.0 forever, so the stopping rule degenerates into
|
|
14
|
+
* "stop when the budget runs out", which is hop-count scoping wearing a
|
|
15
|
+
* different name.
|
|
16
|
+
* 2. **It does not terminate.** With `EdgeConfidence` at 1.0 for an R3 edge, the
|
|
17
|
+
* hop factor is exactly 1.0, and on a `CALLS` cycle the traversal never ends.
|
|
18
|
+
* DEC-028 requires the factor to be strictly inside (0, 1).
|
|
19
|
+
*
|
|
20
|
+
* The defaults below therefore use 0.95, and §12.3's stated outcome still holds:
|
|
21
|
+
* the payment gateway three hops out survives and `logger.ts` two hops out is
|
|
22
|
+
* dropped. That test discriminates on the *shape* of the decay, not on whether
|
|
23
|
+
* the first hop was 1.00 or 0.95.
|
|
24
|
+
*
|
|
25
|
+
* ## Three parts of the architecture cannot all be true — and the resolution
|
|
26
|
+
*
|
|
27
|
+
* Writing this file surfaced a genuine inconsistency between §12.3, §12.4 and
|
|
28
|
+
* §12.7. Any two can hold; all three cannot.
|
|
29
|
+
*
|
|
30
|
+
* - **§12.3** needs *high* weights. Its worked example decays `CALLS` and
|
|
31
|
+
* `PROPAGATES_TO` at ~0.95 so a three-hop chain still scores 0.90.
|
|
32
|
+
* - **§12.7** tiers on *absolute* thresholds — tier 2 above 0.7, tier 4 below
|
|
33
|
+
* 0.3 — which are only meaningful if a few hops of a strong edge stay high.
|
|
34
|
+
* Scale the weights down for headroom and the payment gateway §12.3 calls
|
|
35
|
+
* critical lands in tier 4, "dropped under budget pressure".
|
|
36
|
+
* - **§12.4** multiplies by `ChangeCouplingFactor` and
|
|
37
|
+
* `IncidentCorrelationFactor` *at every hop*, and both are boosts above 1.0.
|
|
38
|
+
* A weight of 0.95 with any coupling above 1.053 makes the hop factor exceed
|
|
39
|
+
* 1.0, at which point the score stops decaying and a cycle never terminates.
|
|
40
|
+
*
|
|
41
|
+
* **Resolution: the history factors adjust a node's score once, they do not
|
|
42
|
+
* compound per hop.** Path decay is the product of `edgeWeight × confidence`
|
|
43
|
+
* over the hops, strictly below 1 at every step, so termination is structural.
|
|
44
|
+
* Coupling and incident are then applied to the node's final score.
|
|
45
|
+
*
|
|
46
|
+
* This keeps §12.3's numbers exactly, keeps §12.7's thresholds meaningful, and
|
|
47
|
+
* keeps §12.4's terms doing the work they were introduced for. It is also more
|
|
48
|
+
* defensible than the literal formula: compounding a node's incident history at
|
|
49
|
+
* every hop of a path that merely *passes through* it counts the same evidence
|
|
50
|
+
* repeatedly, which the multiplicative form does silently. See DEC-037.
|
|
51
|
+
*/
|
|
52
|
+
import { EDGE_TYPES } from "@descryy/ir";
|
|
53
|
+
import { DEFAULT_FANOUT_BUCKETS, maxAttenuation } from "./fanout.js";
|
|
54
|
+
/**
|
|
55
|
+
* Default weights.
|
|
56
|
+
*
|
|
57
|
+
* **Tuning, not architecture.** §12 is marked `DECIDED, TUNING OPEN` and §32
|
|
58
|
+
* items 1 and 4 list edge weights as values to set from real traversal data.
|
|
59
|
+
* These are starting points chosen to reproduce §12.3's example, and the three
|
|
60
|
+
* that matter are the ones that example names: `CALLS`, `PROPAGATES_TO` and
|
|
61
|
+
* `IMPORTS`.
|
|
62
|
+
*/
|
|
63
|
+
export const DEFAULT_EDGE_WEIGHTS = {
|
|
64
|
+
// Structural: a change here really does reach the other side.
|
|
65
|
+
CALLS: 0.95,
|
|
66
|
+
PROPAGATES_TO: 0.95,
|
|
67
|
+
SERVES_API: 0.9,
|
|
68
|
+
USES_API: 0.9,
|
|
69
|
+
RETURNS: 0.85,
|
|
70
|
+
WRITES: 0.8,
|
|
71
|
+
READS: 0.75,
|
|
72
|
+
// A shape dependency is structural and real — change the type and the
|
|
73
|
+
// declaration that embeds it may stop compiling — but it is weaker than a
|
|
74
|
+
// call: the dependant names the type, it does not execute anything. Placed
|
|
75
|
+
// between READS and IMPLEMENTS, and provisional like every other value here.
|
|
76
|
+
USES_TYPE: 0.7,
|
|
77
|
+
IMPLEMENTS: 0.7,
|
|
78
|
+
INHERITS: 0.7,
|
|
79
|
+
// §12.3's example: an import is a weak signal and must decay fast, or
|
|
80
|
+
// `logger.ts` survives and the engine reports noise as impact.
|
|
81
|
+
IMPORTS: 0.4,
|
|
82
|
+
// Tests are reached deliberately by the test-discovery query rather than by
|
|
83
|
+
// impact decay, so this only needs to be non-zero.
|
|
84
|
+
TESTS: 0.5,
|
|
85
|
+
// History, not structure. Everything from the git source is R0 and capped at
|
|
86
|
+
// 0.5 confidence already (DEC-019); a low weight keeps it as a hint.
|
|
87
|
+
CHANGES_WITH: 0.35,
|
|
88
|
+
INCIDENT_CORRELATED: 0.3,
|
|
89
|
+
FIXED_BY: 0.3,
|
|
90
|
+
};
|
|
91
|
+
export const DEFAULT_SCOPING_CONFIG = {
|
|
92
|
+
edgeWeights: DEFAULT_EDGE_WEIGHTS,
|
|
93
|
+
fanOutBuckets: DEFAULT_FANOUT_BUCKETS,
|
|
94
|
+
maxCouplingFactor: 1.3,
|
|
95
|
+
maxIncidentFactor: 1.2,
|
|
96
|
+
maxScore: 1,
|
|
97
|
+
// §12.3's example drops `logger.ts` at 0.16 and keeps `utils.ts` at 0.40, so
|
|
98
|
+
// the prune point sits between them. Above it, §12.7's tier 4 (below 0.3) is
|
|
99
|
+
// kept but is the first thing budget pressure discards.
|
|
100
|
+
threshold: 0.2,
|
|
101
|
+
};
|
|
102
|
+
export class ScopingConfigError extends Error {
|
|
103
|
+
name = "ScopingConfigError";
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Refuse a configuration that could fail to terminate — DEC-028's config-load half.
|
|
107
|
+
*
|
|
108
|
+
* The check is per edge type because the failure is: one type's weight, boosted
|
|
109
|
+
* to its declared maxima, reaching 1.0. A global average would hide exactly the
|
|
110
|
+
* case that matters.
|
|
111
|
+
*/
|
|
112
|
+
export function validateScopingConfig(config) {
|
|
113
|
+
if (!(config.maxScore > 0) || config.maxScore > 1) {
|
|
114
|
+
throw new ScopingConfigError(`maxScore must be within (0, 1]; got ${config.maxScore}`);
|
|
115
|
+
}
|
|
116
|
+
if (config.maxCouplingFactor < 1 || config.maxIncidentFactor < 1) {
|
|
117
|
+
throw new ScopingConfigError("coupling and incident factors are boosts and default to 1.0 (neutral); a maximum below 1 " +
|
|
118
|
+
"would penalise files with history rather than leaving them unaffected (§12.4)");
|
|
119
|
+
}
|
|
120
|
+
if (!(config.threshold > 0) || config.threshold >= 1) {
|
|
121
|
+
throw new ScopingConfigError(`threshold must be within (0, 1); got ${config.threshold}`);
|
|
122
|
+
}
|
|
123
|
+
// DEC-067's table, checked before it can reach the termination assertion.
|
|
124
|
+
const buckets = config.fanOutBuckets;
|
|
125
|
+
if (buckets.length === 0) {
|
|
126
|
+
throw new ScopingConfigError("fanOutBuckets must not be empty; use a single open bucket to disable attenuation");
|
|
127
|
+
}
|
|
128
|
+
let previous = -1;
|
|
129
|
+
for (const bucket of buckets) {
|
|
130
|
+
if (!(bucket.upTo > previous)) {
|
|
131
|
+
throw new ScopingConfigError(`fanOutBuckets must have strictly increasing bounds; ${bucket.label} (upTo ${bucket.upTo}) does not exceed ${previous}`);
|
|
132
|
+
}
|
|
133
|
+
previous = bucket.upTo;
|
|
134
|
+
if (!(bucket.multiplier > 0)) {
|
|
135
|
+
throw new ScopingConfigError(`fan-out multiplier for ${bucket.label} must be > 0; got ${bucket.multiplier}. Zero would ` +
|
|
136
|
+
`silently delete a real dependency from every blast radius that reaches it, which is a ` +
|
|
137
|
+
`missing edge wearing a score.`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (buckets[buckets.length - 1].upTo !== Number.POSITIVE_INFINITY) {
|
|
141
|
+
throw new ScopingConfigError(`the last fan-out bucket must be open (upTo: Infinity), or a node above ${previous} falls in no bucket`);
|
|
142
|
+
}
|
|
143
|
+
// DEC-028's config-load half, widened by DEC-067. Because history factors no
|
|
144
|
+
// longer compound per hop, the requirement is on the weight alone — and
|
|
145
|
+
// `maxConfidence` is 1.0 by definition, so a weight of 1.0 is exactly the
|
|
146
|
+
// non-terminating case. Attenuation multiplies into the same product, so a
|
|
147
|
+
// multiplier above 1.0 would make a weight that decays on its own stop
|
|
148
|
+
// decaying in transit. DEC-067 requires this check to widen *before* such a
|
|
149
|
+
// value ships, so it is written now while every multiplier is still <= 1.
|
|
150
|
+
const largest = maxAttenuation(buckets);
|
|
151
|
+
const offenders = [];
|
|
152
|
+
for (const type of EDGE_TYPES) {
|
|
153
|
+
const weight = config.edgeWeights[type];
|
|
154
|
+
if (!(weight > 0) || weight * largest >= 1) {
|
|
155
|
+
offenders.push(largest === 1 ? `${type} (${weight})` : `${type} (${weight} × ${largest})`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (offenders.length > 0) {
|
|
159
|
+
throw new ScopingConfigError(`these edge weights do not decay, so expansion stops on hop count rather than on score ` +
|
|
160
|
+
`(§12.2) and never terminates on a cyclic graph: ${offenders.join(", ")}. Required: ` +
|
|
161
|
+
`0 < edgeWeight × maxFanOutMultiplier × maxConfidence < 1, and maxConfidence is 1.0 by ` +
|
|
162
|
+
`definition (DEC-028, widened by DEC-067). ` +
|
|
163
|
+
`§12.3's own example uses ×1.0 for a CALLS hop and ×0.95 three hops later; the 0.95 is ` +
|
|
164
|
+
`the usable one.`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=weights.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weights.js","sourceRoot":"","sources":["../../src/scoping/weights.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AAEH,OAAO,EAAE,UAAU,EAAiB,MAAM,aAAa,CAAC;AAExD,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAqB,MAAM,aAAa,CAAC;AAwBxF;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAuC;IACtE,8DAA8D;IAC9D,KAAK,EAAE,IAAI;IACX,aAAa,EAAE,IAAI;IACnB,UAAU,EAAE,GAAG;IACf,QAAQ,EAAE,GAAG;IACb,OAAO,EAAE,IAAI;IACb,MAAM,EAAE,GAAG;IACX,KAAK,EAAE,IAAI;IACX,sEAAsE;IACtE,0EAA0E;IAC1E,2EAA2E;IAC3E,6EAA6E;IAC7E,SAAS,EAAE,GAAG;IACd,UAAU,EAAE,GAAG;IACf,QAAQ,EAAE,GAAG;IACb,sEAAsE;IACtE,+DAA+D;IAC/D,OAAO,EAAE,GAAG;IACZ,4EAA4E;IAC5E,mDAAmD;IACnD,KAAK,EAAE,GAAG;IACV,6EAA6E;IAC7E,qEAAqE;IACrE,YAAY,EAAE,IAAI;IAClB,mBAAmB,EAAE,GAAG;IACxB,QAAQ,EAAE,GAAG;CACd,CAAC;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAAkB;IACnD,WAAW,EAAE,oBAAoB;IACjC,aAAa,EAAE,sBAAsB;IACrC,iBAAiB,EAAE,GAAG;IACtB,iBAAiB,EAAE,GAAG;IACtB,QAAQ,EAAE,CAAC;IACX,6EAA6E;IAC7E,6EAA6E;IAC7E,wDAAwD;IACxD,SAAS,EAAE,GAAG;CACf,CAAC;AAEF,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IACzB,IAAI,GAAG,oBAAoB,CAAC;CAC/C;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAqB;IACzD,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,GAAG,CAAC,CAAC,IAAI,MAAM,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,kBAAkB,CAAC,uCAAuC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IACzF,CAAC;IACD,IAAI,MAAM,CAAC,iBAAiB,GAAG,CAAC,IAAI,MAAM,CAAC,iBAAiB,GAAG,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,kBAAkB,CAC1B,2FAA2F;YACzF,+EAA+E,CAClF,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC,IAAI,MAAM,CAAC,SAAS,IAAI,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,kBAAkB,CAAC,wCAAwC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;IAC3F,CAAC;IAED,0EAA0E;IAC1E,MAAM,OAAO,GAAG,MAAM,CAAC,aAAa,CAAC;IACrC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,kBAAkB,CAAC,kFAAkF,CAAC,CAAC;IACnH,CAAC;IACD,IAAI,QAAQ,GAAG,CAAC,CAAC,CAAC;IAClB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,GAAG,QAAQ,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,kBAAkB,CAC1B,uDAAuD,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAI,qBAAqB,QAAQ,EAAE,CACxH,CAAC;QACJ,CAAC;QACD,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC;QACvB,IAAI,CAAC,CAAC,MAAM,CAAC,UAAU,GAAG,CAAC,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,kBAAkB,CAC1B,0BAA0B,MAAM,CAAC,KAAK,qBAAqB,MAAM,CAAC,UAAU,eAAe;gBACzF,wFAAwF;gBACxF,+BAA+B,CAClC,CAAC;QACJ,CAAC;IACH,CAAC;IACD,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,IAAI,KAAK,MAAM,CAAC,iBAAiB,EAAE,CAAC;QACnE,MAAM,IAAI,kBAAkB,CAC1B,0EAA0E,QAAQ,qBAAqB,CACxG,CAAC;IACJ,CAAC;IAED,6EAA6E;IAC7E,wEAAwE;IACxE,0EAA0E;IAC1E,2EAA2E;IAC3E,uEAAuE;IACvE,4EAA4E;IAC5E,0EAA0E;IAC1E,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,MAAM,GAAG,OAAO,IAAI,CAAC,EAAE,CAAC;YAC3C,SAAS,CAAC,IAAI,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC;QAC7F,CAAC;IACH,CAAC;IAED,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,kBAAkB,CAC1B,wFAAwF;YACtF,mDAAmD,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc;YACrF,wFAAwF;YACxF,4CAA4C;YAC5C,wFAAwF;YACxF,iBAAiB,CACpB,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `gitDiff` — a live textual diff between two refs. §18's `get_git_diff`.
|
|
3
|
+
*
|
|
4
|
+
* `changedFiles` (`history.ts`) already answers "which files changed" — a
|
|
5
|
+
* bare path list. This answers "what changed in them" — per-file status and
|
|
6
|
+
* line counts always, plus the actual unified-diff patch text when it is
|
|
7
|
+
* cheap enough to hand to a model. §4's own worry ("the client's context
|
|
8
|
+
* window is not yours to spend") is the reason a patch is never returned
|
|
9
|
+
* unconditionally: a single large file rewrite can be tens of thousands of
|
|
10
|
+
* tokens, and a caller that wanted only "did this file change and how much"
|
|
11
|
+
* pays that cost with no way to decline it. `patchOmittedReason` names why,
|
|
12
|
+
* rather than silently shrinking the reply — the empty-denominator rule
|
|
13
|
+
* applies to a dropped patch exactly as it does to a dropped finding.
|
|
14
|
+
*
|
|
15
|
+
* One `git diff` invocation for every file at once, not one per file — a
|
|
16
|
+
* PR touching fifty files would otherwise spawn fifty processes. The output
|
|
17
|
+
* is a concatenation of per-file blocks, each beginning with a line
|
|
18
|
+
* `diff --git a/<path> b/<path>`; parsing splits on that boundary and reads
|
|
19
|
+
* the more specific `rename from`/`rename to`/`new file mode`/
|
|
20
|
+
* `deleted file mode`/`Binary files … differ`/`---`/`+++` lines within each
|
|
21
|
+
* block, which are unambiguous where the `diff --git` header line alone is
|
|
22
|
+
* not (a path containing the literal substring `" b/"` defeats that header's
|
|
23
|
+
* own regex — an accepted, narrow gap, not a silent one, since every other
|
|
24
|
+
* line used here does not share it).
|
|
25
|
+
*/
|
|
26
|
+
export interface GitDiffFile {
|
|
27
|
+
/** Path as it is known after the change (the only path for A/M/D). */
|
|
28
|
+
readonly path: string;
|
|
29
|
+
/** Set only when `status === "R"`. */
|
|
30
|
+
readonly fromPath: string | null;
|
|
31
|
+
readonly status: "A" | "M" | "D" | "R";
|
|
32
|
+
readonly binary: boolean;
|
|
33
|
+
/** `null` for a binary file — a line count is not a meaningful claim about one. */
|
|
34
|
+
readonly additions: number | null;
|
|
35
|
+
readonly deletions: number | null;
|
|
36
|
+
/** The unified diff text for this file, or `null` — see `patchOmittedReason`. */
|
|
37
|
+
readonly patch: string | null;
|
|
38
|
+
/** Non-null exactly when `patch` is null: why it was withheld. */
|
|
39
|
+
readonly patchOmittedReason: string | null;
|
|
40
|
+
}
|
|
41
|
+
export interface GitDiffOptions {
|
|
42
|
+
/** Scope the diff to these repo-relative paths. Default: the whole diff. */
|
|
43
|
+
readonly files?: readonly string[];
|
|
44
|
+
/** A file's patch is omitted (stats are still reported) above this many bytes. Default 20,000. */
|
|
45
|
+
readonly maxPatchBytes?: number;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* `base...head` (three dots), matching `changedFiles`'s own reasoning: two
|
|
49
|
+
* dots would include everything changed on `base` since the branch point,
|
|
50
|
+
* misattributing someone else's history to this diff.
|
|
51
|
+
*/
|
|
52
|
+
export declare function gitDiff(cwd: string, base: string, head?: string, options?: GitDiffOptions): Promise<readonly GitDiffFile[]>;
|
|
53
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../../src/sources/git/diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAwBH,MAAM,WAAW,WAAW;IAC1B,sEAAsE;IACtE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,mFAAmF;IACnF,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,iFAAiF;IACjF,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,kEAAkE;IAClE,QAAQ,CAAC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5C;AAED,MAAM,WAAW,cAAc;IAC7B,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,kGAAkG;IAClG,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAmED;;;;GAIG;AACH,wBAAsB,OAAO,CAC3B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,IAAI,SAAS,EACb,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,SAAS,WAAW,EAAE,CAAC,CAqCjC"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `gitDiff` — a live textual diff between two refs. §18's `get_git_diff`.
|
|
3
|
+
*
|
|
4
|
+
* `changedFiles` (`history.ts`) already answers "which files changed" — a
|
|
5
|
+
* bare path list. This answers "what changed in them" — per-file status and
|
|
6
|
+
* line counts always, plus the actual unified-diff patch text when it is
|
|
7
|
+
* cheap enough to hand to a model. §4's own worry ("the client's context
|
|
8
|
+
* window is not yours to spend") is the reason a patch is never returned
|
|
9
|
+
* unconditionally: a single large file rewrite can be tens of thousands of
|
|
10
|
+
* tokens, and a caller that wanted only "did this file change and how much"
|
|
11
|
+
* pays that cost with no way to decline it. `patchOmittedReason` names why,
|
|
12
|
+
* rather than silently shrinking the reply — the empty-denominator rule
|
|
13
|
+
* applies to a dropped patch exactly as it does to a dropped finding.
|
|
14
|
+
*
|
|
15
|
+
* One `git diff` invocation for every file at once, not one per file — a
|
|
16
|
+
* PR touching fifty files would otherwise spawn fifty processes. The output
|
|
17
|
+
* is a concatenation of per-file blocks, each beginning with a line
|
|
18
|
+
* `diff --git a/<path> b/<path>`; parsing splits on that boundary and reads
|
|
19
|
+
* the more specific `rename from`/`rename to`/`new file mode`/
|
|
20
|
+
* `deleted file mode`/`Binary files … differ`/`---`/`+++` lines within each
|
|
21
|
+
* block, which are unambiguous where the `diff --git` header line alone is
|
|
22
|
+
* not (a path containing the literal substring `" b/"` defeats that header's
|
|
23
|
+
* own regex — an accepted, narrow gap, not a silent one, since every other
|
|
24
|
+
* line used here does not share it).
|
|
25
|
+
*/
|
|
26
|
+
import { execFile } from "node:child_process";
|
|
27
|
+
import { promisify } from "node:util";
|
|
28
|
+
import { cleanGitEnv } from "./env.js";
|
|
29
|
+
const execFileAsync = promisify(execFile);
|
|
30
|
+
// Always strips GIT_DIR/GIT_WORK_TREE/GIT_INDEX_FILE/GIT_COMMON_DIR — see env.ts.
|
|
31
|
+
function run(command, args, options) {
|
|
32
|
+
return execFileAsync(command, args, {
|
|
33
|
+
...options,
|
|
34
|
+
encoding: "utf8",
|
|
35
|
+
env: cleanGitEnv(),
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
const DEFAULT_MAX_PATCH_BYTES = 20_000;
|
|
39
|
+
function stripPrefix(path, prefix) {
|
|
40
|
+
return path.startsWith(prefix) ? path.slice(prefix.length) : path;
|
|
41
|
+
}
|
|
42
|
+
function parseDiffBlock(block) {
|
|
43
|
+
const lines = block.split("\n");
|
|
44
|
+
const header = /^diff --git a\/(.*) b\/(.*)$/.exec(lines[0] ?? "");
|
|
45
|
+
let fromPath = null;
|
|
46
|
+
let toPath = null;
|
|
47
|
+
let isNew = false;
|
|
48
|
+
let isDeleted = false;
|
|
49
|
+
let isRename = false;
|
|
50
|
+
let binary = false;
|
|
51
|
+
let additions = 0;
|
|
52
|
+
let deletions = 0;
|
|
53
|
+
for (const line of lines) {
|
|
54
|
+
if (line.startsWith("new file mode"))
|
|
55
|
+
isNew = true;
|
|
56
|
+
else if (line.startsWith("deleted file mode"))
|
|
57
|
+
isDeleted = true;
|
|
58
|
+
else if (line.startsWith("rename from ")) {
|
|
59
|
+
isRename = true;
|
|
60
|
+
fromPath = line.slice("rename from ".length);
|
|
61
|
+
}
|
|
62
|
+
else if (line.startsWith("rename to ")) {
|
|
63
|
+
isRename = true;
|
|
64
|
+
toPath = line.slice("rename to ".length);
|
|
65
|
+
}
|
|
66
|
+
else if (line.startsWith("Binary files ")) {
|
|
67
|
+
binary = true;
|
|
68
|
+
}
|
|
69
|
+
else if (line.startsWith("--- ")) {
|
|
70
|
+
const p = line.slice(4);
|
|
71
|
+
if (p !== "/dev/null" && !isRename)
|
|
72
|
+
fromPath = stripPrefix(p, "a/");
|
|
73
|
+
}
|
|
74
|
+
else if (line.startsWith("+++ ")) {
|
|
75
|
+
const p = line.slice(4);
|
|
76
|
+
if (p !== "/dev/null")
|
|
77
|
+
toPath = stripPrefix(p, "b/");
|
|
78
|
+
}
|
|
79
|
+
else if (line.startsWith("+") && !line.startsWith("+++")) {
|
|
80
|
+
additions += 1;
|
|
81
|
+
}
|
|
82
|
+
else if (line.startsWith("-") && !line.startsWith("---")) {
|
|
83
|
+
deletions += 1;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const path = toPath ?? (header ? header[2] : null) ?? fromPath;
|
|
87
|
+
if (path === null || path === undefined)
|
|
88
|
+
return null;
|
|
89
|
+
const status = isRename ? "R" : isNew ? "A" : isDeleted ? "D" : "M";
|
|
90
|
+
return {
|
|
91
|
+
path,
|
|
92
|
+
fromPath: status === "R" ? fromPath : null,
|
|
93
|
+
status,
|
|
94
|
+
binary,
|
|
95
|
+
additions: binary ? 0 : additions,
|
|
96
|
+
deletions: binary ? 0 : deletions,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* `base...head` (three dots), matching `changedFiles`'s own reasoning: two
|
|
101
|
+
* dots would include everything changed on `base` since the branch point,
|
|
102
|
+
* misattributing someone else's history to this diff.
|
|
103
|
+
*/
|
|
104
|
+
export async function gitDiff(cwd, base, head = "HEAD", options = {}) {
|
|
105
|
+
const maxPatchBytes = options.maxPatchBytes ?? DEFAULT_MAX_PATCH_BYTES;
|
|
106
|
+
const args = ["diff", "-M", `${base}...${head}`];
|
|
107
|
+
if (options.files !== undefined && options.files.length > 0)
|
|
108
|
+
args.push("--", ...options.files);
|
|
109
|
+
const { stdout } = await run("git", args, { cwd, maxBuffer: 256 * 1024 * 1024 });
|
|
110
|
+
if (stdout.trim() === "")
|
|
111
|
+
return [];
|
|
112
|
+
const blocks = stdout.split(/\n(?=diff --git )/);
|
|
113
|
+
const files = [];
|
|
114
|
+
for (const block of blocks) {
|
|
115
|
+
if (!block.startsWith("diff --git "))
|
|
116
|
+
continue;
|
|
117
|
+
const parsed = parseDiffBlock(block);
|
|
118
|
+
if (parsed === null)
|
|
119
|
+
continue;
|
|
120
|
+
const bytes = Buffer.byteLength(block, "utf8");
|
|
121
|
+
const overCap = !parsed.binary && bytes > maxPatchBytes;
|
|
122
|
+
files.push({
|
|
123
|
+
path: parsed.path,
|
|
124
|
+
fromPath: parsed.fromPath,
|
|
125
|
+
status: parsed.status,
|
|
126
|
+
binary: parsed.binary,
|
|
127
|
+
additions: parsed.binary ? null : parsed.additions,
|
|
128
|
+
deletions: parsed.binary ? null : parsed.deletions,
|
|
129
|
+
patch: parsed.binary || overCap ? null : block,
|
|
130
|
+
patchOmittedReason: parsed.binary
|
|
131
|
+
? "binary file — no textual patch"
|
|
132
|
+
: overCap
|
|
133
|
+
? `diff for this file is ${bytes} bytes, over the ${maxPatchBytes}-byte cap — narrow ` +
|
|
134
|
+
'"files" to fetch it on its own, or raise "maxPatchBytes"'
|
|
135
|
+
: null,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
return files;
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../../src/sources/git/diff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../../src/sources/git/env.ts"],"names":[],"mappings":"AAeA,wBAAgB,WAAW,CAAC,IAAI,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAAC,UAAU,CAIpF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The variables git exports into every hook and injects into every
|
|
3
|
+
* subprocess it spawns. Left in place, an inherited `GIT_DIR` (or
|
|
4
|
+
* `GIT_WORK_TREE`/`GIT_INDEX_FILE`/`GIT_COMMON_DIR`) overrides repository
|
|
5
|
+
* discovery even when a git subprocess is given an explicit `cwd` — confirmed
|
|
6
|
+
* directly: `GIT_DIR=<other>/.git` with `cwd` pointed elsewhere still
|
|
7
|
+
* initialises `<other>/.git`, not a repository at `cwd`.
|
|
8
|
+
*
|
|
9
|
+
* Anything here that shells out to git against a caller-supplied path must
|
|
10
|
+
* not inherit these, or a caller running inside a git hook (which always has
|
|
11
|
+
* `GIT_DIR` set) silently operates on the hook's own repository instead of
|
|
12
|
+
* the one it was given.
|
|
13
|
+
*/
|
|
14
|
+
const LEAKY_GIT_VARS = ["GIT_DIR", "GIT_WORK_TREE", "GIT_INDEX_FILE", "GIT_COMMON_DIR"];
|
|
15
|
+
export function cleanGitEnv(base = process.env) {
|
|
16
|
+
const env = { ...base };
|
|
17
|
+
for (const key of LEAKY_GIT_VARS)
|
|
18
|
+
delete env[key];
|
|
19
|
+
return env;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../../src/sources/git/env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,cAAc,GAAG,CAAC,SAAS,EAAE,eAAe,EAAE,gBAAgB,EAAE,gBAAgB,CAAU,CAAC;AAEjG,MAAM,UAAU,WAAW,CAAC,OAA0B,OAAO,CAAC,GAAG;IAC/D,MAAM,GAAG,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;IACxB,KAAK,MAAM,GAAG,IAAI,cAAc;QAAE,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC;IAClD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading git history.
|
|
3
|
+
*
|
|
4
|
+
* No dependency: `git` is invoked directly. A library would buy parsing help and
|
|
5
|
+
* cost a dependency in a package that has none by design, and the format below
|
|
6
|
+
* is chosen so parsing is unambiguous rather than clever.
|
|
7
|
+
*
|
|
8
|
+
* ## Renames are resolved, not ignored
|
|
9
|
+
*
|
|
10
|
+
* `CHANGES_WITH` is file-to-file, and `FILE` identity is DEC-004's documented
|
|
11
|
+
* path fallback — a file's only stable name *is* its path. So a rename silently
|
|
12
|
+
* splits a file's history in two: the co-change weight built up over two years
|
|
13
|
+
* resets to zero, and nothing in the output reveals it happened. That is the
|
|
14
|
+
* exact failure DEC-004 exists to prevent, arriving through the one node type
|
|
15
|
+
* that cannot avoid it.
|
|
16
|
+
*
|
|
17
|
+
* The fix is `-M` plus a canonicalisation pass: history is walked newest-first,
|
|
18
|
+
* and every historical path is mapped forward to the name the file has today. It
|
|
19
|
+
* makes DEC-004's guarantee total for files that git can *follow*; where git's
|
|
20
|
+
* rename detection fails (a rewrite with no similarity), the guarantee stays
|
|
21
|
+
* partial and that is now a bounded, stated gap rather than an unbounded one.
|
|
22
|
+
*/
|
|
23
|
+
export interface CommitChange {
|
|
24
|
+
/** Path as it is known **today**, after following renames forward. */
|
|
25
|
+
readonly path: string;
|
|
26
|
+
readonly status: "A" | "M" | "D" | "R" | "C";
|
|
27
|
+
/** Set only when `status` is `"R"` or `"C"` and the source line named it. */
|
|
28
|
+
readonly fromPath?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface Commit {
|
|
31
|
+
readonly sha: string;
|
|
32
|
+
/** Author timestamp, epoch seconds. Never part of any identity. */
|
|
33
|
+
readonly timestamp: number;
|
|
34
|
+
readonly subject: string;
|
|
35
|
+
readonly body: string;
|
|
36
|
+
readonly changes: readonly CommitChange[];
|
|
37
|
+
}
|
|
38
|
+
export interface HistoryOptions {
|
|
39
|
+
/** Cap on commits read. History is long and the tail is rarely informative. */
|
|
40
|
+
readonly maxCommits?: number;
|
|
41
|
+
/** Ignore commits touching more than this many files — see the note below. */
|
|
42
|
+
readonly maxFilesPerCommit?: number;
|
|
43
|
+
}
|
|
44
|
+
export declare function gitHead(cwd: string): Promise<string>;
|
|
45
|
+
export declare function isGitRepository(cwd: string): Promise<boolean>;
|
|
46
|
+
/**
|
|
47
|
+
* Read history newest-first, with renames followed forward to today's paths.
|
|
48
|
+
*
|
|
49
|
+
* `--no-merges` is deliberate: a merge commit's file list is the union of both
|
|
50
|
+
* branches, so counting it as co-change would report every file in a large merge
|
|
51
|
+
* as coupled to every other. That is the single largest source of false
|
|
52
|
+
* `CHANGES_WITH` edges, and it is free to exclude.
|
|
53
|
+
*/
|
|
54
|
+
export declare function readHistory(cwd: string, options?: HistoryOptions): Promise<Commit[]>;
|
|
55
|
+
export interface PathLogOptions {
|
|
56
|
+
/** Cap on commits returned. Default 20 — this is a live, on-demand read, not a bulk ingestion. */
|
|
57
|
+
readonly maxCommits?: number;
|
|
58
|
+
}
|
|
59
|
+
/** One commit that touched the followed path, as it was known *at that commit* — not forward-canonicalised. */
|
|
60
|
+
export interface PathLogCommit {
|
|
61
|
+
readonly sha: string;
|
|
62
|
+
readonly timestamp: number;
|
|
63
|
+
readonly subject: string;
|
|
64
|
+
readonly body: string;
|
|
65
|
+
readonly status: "A" | "M" | "D" | "R" | "C";
|
|
66
|
+
/** The path as this commit names it — the historical name for a commit at or before a later rename. */
|
|
67
|
+
readonly path: string;
|
|
68
|
+
/** Set only when `status` is `"R"` or `"C"`. */
|
|
69
|
+
readonly fromPath: string | null;
|
|
70
|
+
}
|
|
71
|
+
export interface PathLogResult {
|
|
72
|
+
readonly commits: readonly PathLogCommit[];
|
|
73
|
+
/**
|
|
74
|
+
* How many commits touch this path in total, independent of `maxCommits`.
|
|
75
|
+
* A second, cheap `git log --format=%H` count — not `commits.length`,
|
|
76
|
+
* which stops at the cap — so a caller can tell "here are the 20 most
|
|
77
|
+
* recent" from "here are all 3 there are" without guessing from the cap.
|
|
78
|
+
*/
|
|
79
|
+
readonly totalTouching: number;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Live commit history for one file, right now — distinct from `history.ts`'s
|
|
83
|
+
* `changesWith`, which only reads the graph's stored `CHANGES_WITH` ledger
|
|
84
|
+
* built once at `analyze` time. `--follow` tracks the file across renames;
|
|
85
|
+
* unlike `readHistory`'s whole-repo walk, each commit here reports its own
|
|
86
|
+
* historical name rather than today's — the rename itself is part of what a
|
|
87
|
+
* caller asking "what happened to this file" wants to see.
|
|
88
|
+
*/
|
|
89
|
+
export declare function logForPath(cwd: string, path: string, options?: PathLogOptions): Promise<PathLogResult>;
|
|
90
|
+
/**
|
|
91
|
+
* Resolve one commit directly by sha, bypassing both `readHistory`'s
|
|
92
|
+
* reachability filter and its `--no-merges` exclusion.
|
|
93
|
+
*
|
|
94
|
+
* `readHistory` walks history from `HEAD` only — co-change must stay scoped to
|
|
95
|
+
* mainline, or work in progress on other branches would pollute
|
|
96
|
+
* `CHANGES_WITH` — and drops merge commits, because a merge's file list is
|
|
97
|
+
* the union of both branches (see the module doc). Both are correct for
|
|
98
|
+
* co-change. Neither is correct for resolving what a revert commit names:
|
|
99
|
+
* `git revert`'s `This reverts commit <sha>` line can point at a commit that
|
|
100
|
+
* **is** a merge ("Revert Merge pull request #N"), or at a commit that is
|
|
101
|
+
* real and still in the object database but not an ancestor of `HEAD` — an
|
|
102
|
+
* abandoned branch, or one deleted after a squash/rebase merge whose objects
|
|
103
|
+
* have not yet been garbage-collected. Neither case means the commit does
|
|
104
|
+
* not exist; `readHistory`'s index just cannot see it.
|
|
105
|
+
*
|
|
106
|
+
* `git cat-file` and `git diff-tree` operate on the object database directly
|
|
107
|
+
* and enforce neither constraint, so this is the fallback `createGitSource`
|
|
108
|
+
* uses once `readHistory`'s own index has already missed a revert target.
|
|
109
|
+
*
|
|
110
|
+
* Returns `null` only when the object genuinely does not exist — the
|
|
111
|
+
* squash-merge case, where the original commit was never an ancestor of
|
|
112
|
+
* anything that survived and its object is gone from the store. That is the
|
|
113
|
+
* one case nothing can resolve; the caller must disclose it rather than
|
|
114
|
+
* drop it silently (CLAUDE.md rule 7 — every fallback is labelled).
|
|
115
|
+
*
|
|
116
|
+
* File paths returned here are **not** forward-canonicalised through
|
|
117
|
+
* `readHistory`'s rename map — this commit was never visited by that walk.
|
|
118
|
+
* A file renamed on mainline *after* this commit landed will show under its
|
|
119
|
+
* name at the time, not today's name. That is a narrower, disclosed version
|
|
120
|
+
* of the same rename gap the module doc already states for the primary walk.
|
|
121
|
+
*/
|
|
122
|
+
export declare function resolveCommitBySha(cwd: string, sha: string, maxFilesPerCommit?: number): Promise<Commit | null>;
|
|
123
|
+
/**
|
|
124
|
+
* Files changed between two refs — the input to PR analysis.
|
|
125
|
+
*
|
|
126
|
+
* `base...head` (three dots) rather than `base..head`, and the difference is the
|
|
127
|
+
* whole point: two dots diffs the two tips, so every file changed on `base`
|
|
128
|
+
* since the branch point appears in the result as though the PR had touched it.
|
|
129
|
+
* On a branch a week behind `main` that is most of the diff, and the blast
|
|
130
|
+
* radius it produces belongs to somebody else's change. Three dots diffs against
|
|
131
|
+
* the merge base, which is what a reviewer is actually looking at.
|
|
132
|
+
*
|
|
133
|
+
* Deletions are included. A deleted file's nodes may still be in the graph, and
|
|
134
|
+
* *what called the thing you just removed* is the most useful question a diff
|
|
135
|
+
* can be asked.
|
|
136
|
+
*/
|
|
137
|
+
export declare function changedFiles(cwd: string, base: string, head?: string): Promise<string[]>;
|
|
138
|
+
/** `git show --name-only` for one commit, with today's paths where known. */
|
|
139
|
+
export declare function filesInCommit(cwd: string, sha: string): Promise<string[]>;
|
|
140
|
+
//# sourceMappingURL=history.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../../src/sources/git/history.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AA0BH,MAAM,WAAW,YAAY;IAC3B,sEAAsE;IACtE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IAC7C,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,cAAc;IAC7B,+EAA+E;IAC/E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,8EAA8E;IAC9E,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CACrC;AAED,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAG1D;AAED,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOnE;AA0BD;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA4D9F;AAED,MAAM,WAAW,cAAc;IAC7B,kGAAkG;IAClG,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,+GAA+G;AAC/G,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IAC7C,uGAAuG;IACvG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gDAAgD;IAChD,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,CAAC;IAC3C;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,aAAa,CAAC,CAuDxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,iBAAiB,SAAK,GACrB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoExB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,IAAI,SAAS,GACZ,OAAO,CAAC,MAAM,EAAE,CAAC,CASnB;AAED,6EAA6E;AAC7E,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAU/E"}
|