@descryy/core 0.3.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 +26 -12
- package/dist/contracts/engine.d.ts.map +1 -1
- package/dist/contracts/engine.js +28 -11
- package/dist/contracts/engine.js.map +1 -1
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/index.d.ts.map +1 -1
- package/dist/contracts/index.js.map +1 -1
- package/dist/contracts/orphans.d.ts +28 -77
- package/dist/contracts/orphans.d.ts.map +1 -1
- package/dist/contracts/orphans.js +124 -94
- 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 +13 -75
- package/dist/graph/build.d.ts.map +1 -1
- package/dist/graph/build.js +0 -0
- 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/index.d.ts +1 -1
- package/dist/graph/index.d.ts.map +1 -1
- package/dist/graph/merge.d.ts +8 -76
- package/dist/graph/merge.d.ts.map +1 -1
- package/dist/graph/merge.js +27 -77
- 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 +5 -9
- package/dist/query/memory.d.ts.map +1 -1
- package/dist/query/memory.js +31 -15
- 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 +28 -81
- 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 +43 -100
- 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 +13 -16
- 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 +0 -0
- 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 +0 -0
- 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 +47 -0
- package/dist/validation/attributes.d.ts.map +1 -0
- package/dist/validation/attributes.js +130 -0
- package/dist/validation/attributes.js.map +1 -0
- 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 +53 -2
- package/dist/validation/env.d.ts.map +1 -1
- package/dist/validation/env.js +99 -4
- package/dist/validation/env.js.map +1 -1
- package/dist/validation/index.d.ts +5 -1
- package/dist/validation/index.d.ts.map +1 -1
- package/dist/validation/index.js +3 -1
- package/dist/validation/index.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 +72 -0
- package/dist/validation/migration-integrity.d.ts.map +1 -0
- package/dist/validation/migration-integrity.js +238 -0
- package/dist/validation/migration-integrity.js.map +1 -0
- package/dist/validation/migrations.d.ts +23 -88
- package/dist/validation/migrations.d.ts.map +1 -1
- package/dist/validation/migrations.js +20 -79
- 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 +23 -81
- package/dist/validation/rollback.js.map +1 -1
- package/dist/validation/route-drift.d.ts +9 -62
- package/dist/validation/route-drift.d.ts.map +1 -1
- package/dist/validation/route-drift.js +7 -52
- package/dist/validation/route-drift.js.map +1 -1
- package/dist/validation/sources.d.ts +16 -94
- package/dist/validation/sources.d.ts.map +1 -1
- package/dist/validation/sources.js +51 -147
- package/dist/validation/sources.js.map +1 -1
- package/dist/worker/pool.d.ts +6 -45
- package/dist/worker/pool.d.ts.map +1 -1
- package/dist/worker/pool.js +5 -42
- package/dist/worker/pool.js.map +1 -1
- package/dist/worker/protocol.d.ts +7 -20
- package/dist/worker/protocol.d.ts.map +1 -1
- package/dist/worker/protocol.js +3 -10
- package/dist/worker/protocol.js.map +1 -1
- package/dist/worker/traversal.worker.d.ts +2 -21
- package/dist/worker/traversal.worker.d.ts.map +1 -1
- package/dist/worker/traversal.worker.js +4 -23
- package/dist/worker/traversal.worker.js.map +1 -1
- package/package.json +11 -2
|
@@ -1,43 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Route drift
|
|
3
|
-
*
|
|
4
|
-
* The comparison logic only; identity from `@descryy/ir`, never re-implemented
|
|
5
|
-
* here. The `bench/route-drift.mjs` instrument does the harder half of this
|
|
6
|
-
* row — reading `php artisan route:list`, the `--introspection` file
|
|
7
|
-
* fallback, and the refusal to run an installer on a cloned repository (§5
|
|
8
|
-
* rule 10, DEC-115 clause 3). This module is the query it calls: given two
|
|
9
|
-
* already-extracted route lists, decide what they say about each other.
|
|
10
|
-
*
|
|
11
|
-
* ## The rule this file is built around, before anything else
|
|
12
|
-
*
|
|
13
|
-
* **A diff is the one measurement where an empty input produces the most
|
|
14
|
-
* reassuring possible output.** If introspection returns nothing —
|
|
15
|
-
* `artisan` not runnable, the application not bootable, the command failing
|
|
16
|
-
* quietly — the drift is zero, and zero drift is exactly what a healthy
|
|
17
|
-
* repository looks like. So both population *sizes* are part of the result,
|
|
18
|
-
* not scaffolding, and this module cannot report agreement it was not
|
|
19
|
-
* actually given. An empty or implausible side is a **refusal** to report
|
|
20
|
-
* drift, never a clean bill — the same shape this lane measured directly on
|
|
21
|
-
* `env-precision-adapter.mjs`: two runs both printed `decision accuracy
|
|
22
|
-
* 100.0%`, one on 5 decisions and one on 51, indistinguishable except for the
|
|
23
|
-
* confidence interval underneath. A diff has no interval to fall back on, so
|
|
24
|
-
* the refusal has to be explicit.
|
|
25
|
-
*
|
|
26
|
-
* ## The polarity is DEC-115's and is not re-opened here
|
|
27
|
-
*
|
|
28
|
-
* Static extraction is the **floor**; introspection is a **promotion** over
|
|
29
|
-
* the same node ids. The two disagreement directions are two findings with
|
|
30
|
-
* different audiences and different truth conditions, and collapsing them is
|
|
31
|
-
* the error:
|
|
32
|
-
*
|
|
33
|
-
* | direction | what it is | what it is NOT |
|
|
34
|
-
* | --- | --- | --- |
|
|
35
|
-
* | static says yes, listing says no | "these two sources disagree" | **never** "dead route" — ambiguous between the customer's app and our own false positive, and nothing here separates them |
|
|
36
|
-
* | listing says yes, static says no | a statement about **us**: the extractor missed one | not a finding about the customer at all |
|
|
37
|
-
*
|
|
38
|
-
* The second row is the more valuable one. Where a listing exists it is
|
|
39
|
-
* **ground truth for recall** — a complete denominator this project has
|
|
40
|
-
* never had without hand-building it.
|
|
2
|
+
* Route drift (DEC-115): compares two already-extracted route lists; identity via `@descryy/ir`, never re-implemented. An empty/implausible introspection side must be a *refusal*, never reported as zero drift — the emptiest input would otherwise be the most falsely reassuring output.
|
|
3
|
+
* Static extraction is the floor, introspection a promotion (DEC-115 polarity): static-yes/listing-no is an ambiguous disagreement, never "dead route"; listing-yes/static-no is a statement about our own extractor missing a route, and listing is ground truth for recall.
|
|
41
4
|
*/
|
|
42
5
|
/** One route, from either side, before identity is applied. */
|
|
43
6
|
export interface DriftRoute {
|
|
@@ -46,13 +9,8 @@ export interface DriftRoute {
|
|
|
46
9
|
/** Repo-relative, when the side has one (the static extractor always does). */
|
|
47
10
|
readonly file?: string;
|
|
48
11
|
}
|
|
49
|
-
/**
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* Three refusal states plus `read`, mirroring `RollbackReport.ran` /
|
|
53
|
-
* `blockers` one level down: a caller needs to know *why* nothing was
|
|
54
|
-
* compared, not just that nothing was.
|
|
55
|
-
*/
|
|
12
|
+
/** What the introspected side returned. Three refusal states plus `read` — a
|
|
13
|
+
* caller needs to know *why* nothing was compared, not just that it wasn't. */
|
|
56
14
|
export type Introspection = {
|
|
57
15
|
readonly state: "read";
|
|
58
16
|
readonly source: string;
|
|
@@ -86,23 +44,12 @@ export interface DriftReport {
|
|
|
86
44
|
readonly recallAgainstListing?: number;
|
|
87
45
|
}
|
|
88
46
|
export interface DriftOptions {
|
|
89
|
-
/**
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* A Laravel application with `artisan` and one route is far more likely to
|
|
93
|
-
* be a listing that failed than an application with one route. Crude on
|
|
94
|
-
* purpose — it exists to catch "the command produced almost nothing," not
|
|
95
|
-
* to model route counts.
|
|
96
|
-
*/
|
|
47
|
+
/** Below this, a listing isn't believed — crude on purpose, catches "the
|
|
48
|
+
* command produced almost nothing," not a route-count model. */
|
|
97
49
|
readonly implausibleBelow?: number;
|
|
98
50
|
}
|
|
99
|
-
/**
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
* `staticOnly`/`listedOnly`/`agreed` are only ever populated when both sides
|
|
103
|
-
* were actually read and the introspected side is not implausibly small.
|
|
104
|
-
* Every other path returns `reported: false` carrying both counts, because
|
|
105
|
-
* the counts are the evidence the refusal was necessary.
|
|
106
|
-
*/
|
|
51
|
+
/** The comparison, and the refusal that guards it. `staticOnly`/`listedOnly`/
|
|
52
|
+
* `agreed` populate only when both sides read and neither is implausibly
|
|
53
|
+
* small; otherwise `reported: false` carries both counts as evidence. */
|
|
107
54
|
export declare function checkRouteDrift(staticSide: readonly DriftRoute[], introspected: Introspection, options?: DriftOptions): DriftReport;
|
|
108
55
|
//# sourceMappingURL=route-drift.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-drift.d.ts","sourceRoot":"","sources":["../../src/validation/route-drift.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"route-drift.d.ts","sourceRoot":"","sources":["../../src/validation/route-drift.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,+DAA+D;AAC/D,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;gFACgF;AAChF,MAAM,MAAM,aAAa,GACrB;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAA;CAAE,GAC3F;IAAE,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC1D;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3D,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,2FAA2F;IAC3F,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;KAAE,EAAE,CAAC;IACtF,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;KAAE,EAAE,CAAC;IACtF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,kFAAkF;IAClF,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;CACxC;AAED,MAAM,WAAW,YAAY;IAC3B;qEACiE;IACjE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC;AASD;;0EAE0E;AAC1E,wBAAgB,eAAe,CAC7B,UAAU,EAAE,SAAS,UAAU,EAAE,EACjC,YAAY,EAAE,aAAa,EAC3B,OAAO,GAAE,YAAiB,GACzB,WAAW,CA+Cb"}
|
|
@@ -1,43 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Route drift
|
|
3
|
-
*
|
|
4
|
-
* The comparison logic only; identity from `@descryy/ir`, never re-implemented
|
|
5
|
-
* here. The `bench/route-drift.mjs` instrument does the harder half of this
|
|
6
|
-
* row — reading `php artisan route:list`, the `--introspection` file
|
|
7
|
-
* fallback, and the refusal to run an installer on a cloned repository (§5
|
|
8
|
-
* rule 10, DEC-115 clause 3). This module is the query it calls: given two
|
|
9
|
-
* already-extracted route lists, decide what they say about each other.
|
|
10
|
-
*
|
|
11
|
-
* ## The rule this file is built around, before anything else
|
|
12
|
-
*
|
|
13
|
-
* **A diff is the one measurement where an empty input produces the most
|
|
14
|
-
* reassuring possible output.** If introspection returns nothing —
|
|
15
|
-
* `artisan` not runnable, the application not bootable, the command failing
|
|
16
|
-
* quietly — the drift is zero, and zero drift is exactly what a healthy
|
|
17
|
-
* repository looks like. So both population *sizes* are part of the result,
|
|
18
|
-
* not scaffolding, and this module cannot report agreement it was not
|
|
19
|
-
* actually given. An empty or implausible side is a **refusal** to report
|
|
20
|
-
* drift, never a clean bill — the same shape this lane measured directly on
|
|
21
|
-
* `env-precision-adapter.mjs`: two runs both printed `decision accuracy
|
|
22
|
-
* 100.0%`, one on 5 decisions and one on 51, indistinguishable except for the
|
|
23
|
-
* confidence interval underneath. A diff has no interval to fall back on, so
|
|
24
|
-
* the refusal has to be explicit.
|
|
25
|
-
*
|
|
26
|
-
* ## The polarity is DEC-115's and is not re-opened here
|
|
27
|
-
*
|
|
28
|
-
* Static extraction is the **floor**; introspection is a **promotion** over
|
|
29
|
-
* the same node ids. The two disagreement directions are two findings with
|
|
30
|
-
* different audiences and different truth conditions, and collapsing them is
|
|
31
|
-
* the error:
|
|
32
|
-
*
|
|
33
|
-
* | direction | what it is | what it is NOT |
|
|
34
|
-
* | --- | --- | --- |
|
|
35
|
-
* | static says yes, listing says no | "these two sources disagree" | **never** "dead route" — ambiguous between the customer's app and our own false positive, and nothing here separates them |
|
|
36
|
-
* | listing says yes, static says no | a statement about **us**: the extractor missed one | not a finding about the customer at all |
|
|
37
|
-
*
|
|
38
|
-
* The second row is the more valuable one. Where a listing exists it is
|
|
39
|
-
* **ground truth for recall** — a complete denominator this project has
|
|
40
|
-
* never had without hand-building it.
|
|
2
|
+
* Route drift (DEC-115): compares two already-extracted route lists; identity via `@descryy/ir`, never re-implemented. An empty/implausible introspection side must be a *refusal*, never reported as zero drift — the emptiest input would otherwise be the most falsely reassuring output.
|
|
3
|
+
* Static extraction is the floor, introspection a promotion (DEC-115 polarity): static-yes/listing-no is an ambiguous disagreement, never "dead route"; listing-yes/static-no is a statement about our own extractor missing a route, and listing is ground truth for recall.
|
|
41
4
|
*/
|
|
42
5
|
import { endpointQsp, normaliseEndpointPath } from "@descryy/ir";
|
|
43
6
|
const DEFAULT_IMPLAUSIBLE_BELOW = 3;
|
|
@@ -45,14 +8,9 @@ const DEFAULT_IMPLAUSIBLE_BELOW = 3;
|
|
|
45
8
|
function key(method, path) {
|
|
46
9
|
return endpointQsp(String(method || "").toUpperCase(), normaliseEndpointPath(String(path || "")));
|
|
47
10
|
}
|
|
48
|
-
/**
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* `staticOnly`/`listedOnly`/`agreed` are only ever populated when both sides
|
|
52
|
-
* were actually read and the introspected side is not implausibly small.
|
|
53
|
-
* Every other path returns `reported: false` carrying both counts, because
|
|
54
|
-
* the counts are the evidence the refusal was necessary.
|
|
55
|
-
*/
|
|
11
|
+
/** The comparison, and the refusal that guards it. `staticOnly`/`listedOnly`/
|
|
12
|
+
* `agreed` populate only when both sides read and neither is implausibly
|
|
13
|
+
* small; otherwise `reported: false` carries both counts as evidence. */
|
|
56
14
|
export function checkRouteDrift(staticSide, introspected, options = {}) {
|
|
57
15
|
const implausibleBelow = options.implausibleBelow ?? DEFAULT_IMPLAUSIBLE_BELOW;
|
|
58
16
|
if (introspected.state !== "read") {
|
|
@@ -92,11 +50,8 @@ export function checkRouteDrift(staticSide, introspected, options = {}) {
|
|
|
92
50
|
staticOnly,
|
|
93
51
|
listedOnly,
|
|
94
52
|
agreed,
|
|
95
|
-
//
|
|
96
|
-
//
|
|
97
|
-
// is a real ratio — `listedKeys.size` is never 0 on this path, since
|
|
98
|
-
// `implausibleBelow` already refused anything under it, but the type
|
|
99
|
-
// stays honest about the precondition rather than asserting past it.
|
|
53
|
+
// listedKeys.size is never 0 here (implausibleBelow refused that), but the
|
|
54
|
+
// type stays honest about the precondition rather than asserting past it.
|
|
100
55
|
...(listedKeys.size === 0 ? {} : { recallAgainstListing: agreed / listedKeys.size }),
|
|
101
56
|
};
|
|
102
57
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-drift.js","sourceRoot":"","sources":["../../src/validation/route-drift.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"route-drift.js","sourceRoot":"","sources":["../../src/validation/route-drift.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAqCjE,MAAM,yBAAyB,GAAG,CAAC,CAAC;AAEpC,sFAAsF;AACtF,SAAS,GAAG,CAAC,MAAc,EAAE,IAAY;IACvC,OAAO,WAAW,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,EAAE,qBAAqB,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AACpG,CAAC;AAED;;0EAE0E;AAC1E,MAAM,UAAU,eAAe,CAC7B,UAAiC,EACjC,YAA2B,EAC3B,UAAwB,EAAE;IAE1B,MAAM,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,yBAAyB,CAAC;IAE/E,IAAI,YAAY,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC;QAClC,OAAO;YACL,QAAQ,EAAE,KAAK;YACf,WAAW,EAAE,UAAU,CAAC,MAAM;YAC9B,iBAAiB,EAAE,CAAC;YACpB,aAAa,EAAE,iBAAiB,YAAY,CAAC,KAAK,KAAK,YAAY,CAAC,GAAG,EAAE;SAC1E,CAAC;IACJ,CAAC;IAED,IAAI,YAAY,CAAC,MAAM,CAAC,MAAM,GAAG,gBAAgB,EAAE,CAAC;QAClD,OAAO;YACL,QAAQ,EAAE,KAAK;YACf,WAAW,EAAE,UAAU,CAAC,MAAM;YAC9B,iBAAiB,EAAE,YAAY,CAAC,MAAM,CAAC,MAAM;YAC7C,aAAa,EACX,8BAA8B,gBAAgB,8CAA8C;gBAC5F,gCAAgC;SACnC,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,GAAG,EAAsB,CAAC;IACjD,KAAK,MAAM,KAAK,IAAI,UAAU;QAAE,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;IACrF,MAAM,UAAU,GAAG,IAAI,GAAG,EAAsB,CAAC;IACjD,KAAK,MAAM,KAAK,IAAI,YAAY,CAAC,MAAM;QAAE,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;IAE9F,MAAM,UAAU,GAAG,CAAC,GAAG,UAAU,CAAC;SAC/B,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;SACnC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IAC5C,MAAM,UAAU,GAAG,CAAC,GAAG,UAAU,CAAC;SAC/B,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;SACnC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAEzE,OAAO;QACL,QAAQ,EAAE,IAAI;QACd,WAAW,EAAE,UAAU,CAAC,MAAM;QAC9B,iBAAiB,EAAE,YAAY,CAAC,MAAM,CAAC,MAAM;QAC7C,UAAU;QACV,UAAU;QACV,MAAM;QACN,2EAA2E;QAC3E,0EAA0E;QAC1E,GAAG,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,oBAAoB,EAAE,MAAM,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC;KACrF,CAAC;AACJ,CAAC"}
|
|
@@ -1,47 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* ## Why this is not an adapter, and why it is legal here
|
|
6
|
-
*
|
|
7
|
-
* §15.3's own wording is *"cross-check against declared variables **or the
|
|
8
|
-
* deploy target's actual state**"*. The deploy target's state is not in the graph
|
|
9
|
-
* and never will be. What holds it is `.env`, a container manifest, a CI
|
|
10
|
-
* workflow, an image build file — **formats, not languages.** Reading
|
|
11
|
-
* `KEY=value` and an indented `env:` block names no language, so it does not
|
|
12
|
-
* cross the Canonical IR boundary; it is legal above it for the same reason
|
|
13
|
-
* reading a commit log is (`sources/git`).
|
|
14
|
-
*
|
|
15
|
-
* That is what lets the check produce findings with no adapter change at all.
|
|
16
|
-
* See DEC-120.
|
|
17
|
-
*
|
|
18
|
-
* ## Precision over recall, three times, because a misparse here is a wrong finding
|
|
19
|
-
*
|
|
20
|
-
* A name invented by a sloppy scan becomes a confident sentence about somebody's
|
|
21
|
-
* configuration. So:
|
|
22
|
-
*
|
|
23
|
-
* 1. **Two different name rules, on purpose.** In a dotenv file `KEY=` is
|
|
24
|
-
* unambiguous, so any identifier shape is taken. Inside a structured document
|
|
25
|
-
* an `env:` block is indistinguishable from any other mapping once the scan
|
|
26
|
-
* loses its place, so only `UPPER_SNAKE` is accepted. The cost is a lowercase
|
|
27
|
-
* variable in a manifest, which is rare; the alternative is turning a stray
|
|
28
|
-
* key into a declaration.
|
|
29
|
-
* 2. **A block ends at the first line indented no deeper than its header.** No
|
|
30
|
-
* document model, no continuation handling, no anchors. A construct this scan
|
|
31
|
-
* cannot follow ends the block early, which *loses* names — a disclosed gap
|
|
32
|
-
* rather than a wrong one.
|
|
33
|
-
* 3. **A commented-out declaration counts, and is marked.** `# STRIPE_KEY=` in a
|
|
34
|
-
* sample file documents that the variable exists, which is exactly the
|
|
35
|
-
* question being asked. Treating it as absent would report every well
|
|
36
|
-
* documented optional setting as undeclared.
|
|
37
|
-
*
|
|
38
|
-
* ## The example/supply distinction
|
|
39
|
-
*
|
|
40
|
-
* `.env.example` **documents**; `.env.development` and a container manifest
|
|
41
|
-
* **supply**. Both are declarations for the purpose of "does this repository know
|
|
42
|
-
* this variable exists", and they are not interchangeable for anything else, so
|
|
43
|
-
* the distinction is carried on the surface rather than flattened.
|
|
44
|
-
*/
|
|
1
|
+
/** §15's env/config check reads `.env`/manifests/CI directly — formats, not
|
|
2
|
+
* languages, so it never crosses the IR boundary (DEC-120). Precision over
|
|
3
|
+
* recall: strict names, lossy block-end, commented lines count.
|
|
4
|
+
* `.env.example` documents, others supply. */
|
|
45
5
|
/** What a surface is evidence *of*. */
|
|
46
6
|
export type SurfaceRole =
|
|
47
7
|
/** The repository's own statement that a variable exists. */
|
|
@@ -71,15 +31,8 @@ export interface SurfaceScan {
|
|
|
71
31
|
readonly unreadable: readonly string[];
|
|
72
32
|
/** True when the walk hit its file budget before finishing. */
|
|
73
33
|
readonly truncated: boolean;
|
|
74
|
-
/**
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
* Empty means no adapter declared any, and the walk therefore descended into
|
|
78
|
-
* whatever vendored trees the repository holds. Reporting it is what keeps an
|
|
79
|
-
* undeclared scan from reading like a complete one (rule 7) — the caller can
|
|
80
|
-
* see that the surface count is inflated rather than inferring it from a number
|
|
81
|
-
* that looks fine.
|
|
82
|
-
*/
|
|
34
|
+
/** Noise dirs actually used. Empty means none declared (rule 7) — surface
|
|
35
|
+
* count may be inflated by vendored trees. */
|
|
83
36
|
readonly noiseDirectories: readonly string[];
|
|
84
37
|
}
|
|
85
38
|
export interface ScanOptions {
|
|
@@ -87,41 +40,21 @@ export interface ScanOptions {
|
|
|
87
40
|
readonly maxDepth?: number;
|
|
88
41
|
/** Total files a walk may consider. */
|
|
89
42
|
readonly maxFiles?: number;
|
|
90
|
-
/**
|
|
91
|
-
*
|
|
92
|
-
* into — `node_modules`, `vendor`, `target`. **Supplied by the caller from the
|
|
93
|
-
* active adapters' `CapabilityMatrix.noiseDirectories`, never known here**
|
|
94
|
-
* (DEC-110). Undeclared, they are walked, and `SurfaceScan` says so.
|
|
95
|
-
*/
|
|
43
|
+
/** Ecosystem install/build dirs, supplied by the caller's
|
|
44
|
+
* `CapabilityMatrix.noiseDirectories` (DEC-110); undeclared, they get walked. */
|
|
96
45
|
readonly noiseDirectories?: readonly string[];
|
|
97
46
|
}
|
|
98
|
-
/**
|
|
99
|
-
* Shared with the migration scan, so the two walks cannot disagree about what
|
|
100
|
-
* counts as vendored. A second copy of this rule is a second place to forget the
|
|
101
|
-
* next ecosystem.
|
|
102
|
-
*/
|
|
47
|
+
/** Shared with the migration scan — one rule, not two that can disagree. */
|
|
103
48
|
export declare function skipDirectory(name: string, noiseDirectories?: readonly string[]): boolean;
|
|
104
|
-
/**
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
* Structured documents are only opened when their path says they are a manifest
|
|
108
|
-
* or a workflow. Opening every YAML file in a repository would pull in test
|
|
109
|
-
* data, schema definitions and dependency lockfiles, and an `env:` key inside a
|
|
110
|
-
* schema definition is a description of a variable rather than a declaration of
|
|
111
|
-
* one.
|
|
112
|
-
*/
|
|
49
|
+
/** Reads every config surface. Structured docs open only when their path
|
|
50
|
+
* names a manifest/workflow, else a schema `env:` key would count as one. */
|
|
113
51
|
export declare function scanConfigSurfaces(root: string, options?: ScanOptions): SurfaceScan;
|
|
114
52
|
/** `KEY=value`, and `# KEY=value`, which documents the same variable. */
|
|
115
53
|
export declare function readDotenv(text: string): readonly EnvDeclaration[];
|
|
116
54
|
/** `ENV K=V`, the legacy `ENV K V`, and `ARG K`. */
|
|
117
55
|
export declare function readImageBuild(text: string): readonly EnvDeclaration[];
|
|
118
|
-
/**
|
|
119
|
-
* `
|
|
120
|
-
*
|
|
121
|
-
* Mapping — `KEY: value` — and sequence — `- KEY=value` or a bare `- KEY`. The
|
|
122
|
-
* bare sequence form declares a pass-through from the host, which is still the
|
|
123
|
-
* document stating that the variable exists.
|
|
124
|
-
*/
|
|
56
|
+
/** `env:`/`environment:` blocks: mapping (`KEY: value`) or sequence
|
|
57
|
+
* (`- KEY=value` / bare `- KEY`, a host pass-through — still a declaration). */
|
|
125
58
|
export declare function readStructured(text: string): readonly EnvDeclaration[];
|
|
126
59
|
/** One `KEY = "value"` line inside a `wrangler.toml` `[vars]` or `[env.<name>.vars]` table. */
|
|
127
60
|
export interface WranglerVarsEntry {
|
|
@@ -133,20 +66,9 @@ export interface WranglerVarsEntry {
|
|
|
133
66
|
readonly line: number;
|
|
134
67
|
readonly commented: boolean;
|
|
135
68
|
}
|
|
136
|
-
/**
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
* Every other table — `[[kv_namespaces]]`, `[assets]`, `[env.<name>]` itself
|
|
140
|
-
* (the deploy target's own settings, not its vars) — is out of scope by
|
|
141
|
-
* construction rather than by exclusion list: entering *any* table this
|
|
142
|
-
* function does not recognise as a vars table resets tracking to "outside",
|
|
143
|
-
* so a line that merely looks like `KEY = value` inside `[[kv_namespaces]]`
|
|
144
|
-
* (e.g. `binding = "HOSTNAMES"`) is never mistaken for a declared variable.
|
|
145
|
-
* `[[...]]` array-of-tables headers are matched and reset scope the same way,
|
|
146
|
-
* rather than silently falling through as an unrecognised line — an
|
|
147
|
-
* `[[env.staging.kv_namespaces]]` line right after `[env.staging.vars]` must
|
|
148
|
-
* end that table, not extend it.
|
|
149
|
-
*/
|
|
69
|
+
/** Only `[vars]`/`[env.<name>.vars]` tables are read; any other table (or
|
|
70
|
+
* `[[...]]` header) resets scope to "outside", so `[[kv_namespaces]]` lines
|
|
71
|
+
* are never mistaken for a var. */
|
|
150
72
|
export declare function readWranglerVarsEntries(text: string): readonly WranglerVarsEntry[];
|
|
151
73
|
/** The declaration-only projection `scanConfigSurfaces` uses. See `readWranglerVarsEntries` for the value-carrying form `resolve.ts` reads. */
|
|
152
74
|
export declare function readWranglerVars(text: string): readonly EnvDeclaration[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sources.d.ts","sourceRoot":"","sources":["../../src/validation/sources.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"sources.d.ts","sourceRoot":"","sources":["../../src/validation/sources.ts"],"names":[],"mappings":"AAAA;;;+CAG+C;AAK/C,uCAAuC;AACvC,MAAM,MAAM,WAAW;AACrB,6DAA6D;AAC3D,aAAa;AACf,oEAAoE;GAClE,cAAc,CAAC;AAEnB,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,YAAY,GAAG,YAAY,GAAG,cAAc,CAAC;AAEpF,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,2CAA2C;IAC3C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8DAA8D;IAC9D,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,2CAA2C;IAC3C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,sFAAsF;IACtF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,SAAS,cAAc,EAAE,CAAC;CAClD;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAC;IAC5C,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,+DAA+D;IAC/D,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B;mDAC+C;IAC/C,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9C;AAED,MAAM,WAAW,WAAW;IAC1B,oEAAoE;IACpE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,uCAAuC;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;sFACkF;IAClF,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC/C;AAkBD,4EAA4E;AAC5E,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,gBAAgB,GAAE,SAAS,MAAM,EAAO,GACvC,OAAO,CAKT;AAmCD;8EAC8E;AAC9E,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,WAAW,CAsDvF;AA+DD,yEAAyE;AACzE,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,cAAc,EAAE,CAelE;AAED,oDAAoD;AACpD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,cAAc,EAAE,CAwBtE;AAED;iFACiF;AACjF,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,cAAc,EAAE,CA4BtE;AAED,+FAA+F;AAC/F,MAAM,WAAW,iBAAiB;IAChC,2HAA2H;IAC3H,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gGAAgG;IAChG,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAWD;;oCAEoC;AACpC,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,iBAAiB,EAAE,CAoClF;AAED,+IAA+I;AAC/I,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,cAAc,EAAE,CAGxE"}
|
|
@@ -1,97 +1,15 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* ## Why this is not an adapter, and why it is legal here
|
|
6
|
-
*
|
|
7
|
-
* §15.3's own wording is *"cross-check against declared variables **or the
|
|
8
|
-
* deploy target's actual state**"*. The deploy target's state is not in the graph
|
|
9
|
-
* and never will be. What holds it is `.env`, a container manifest, a CI
|
|
10
|
-
* workflow, an image build file — **formats, not languages.** Reading
|
|
11
|
-
* `KEY=value` and an indented `env:` block names no language, so it does not
|
|
12
|
-
* cross the Canonical IR boundary; it is legal above it for the same reason
|
|
13
|
-
* reading a commit log is (`sources/git`).
|
|
14
|
-
*
|
|
15
|
-
* That is what lets the check produce findings with no adapter change at all.
|
|
16
|
-
* See DEC-120.
|
|
17
|
-
*
|
|
18
|
-
* ## Precision over recall, three times, because a misparse here is a wrong finding
|
|
19
|
-
*
|
|
20
|
-
* A name invented by a sloppy scan becomes a confident sentence about somebody's
|
|
21
|
-
* configuration. So:
|
|
22
|
-
*
|
|
23
|
-
* 1. **Two different name rules, on purpose.** In a dotenv file `KEY=` is
|
|
24
|
-
* unambiguous, so any identifier shape is taken. Inside a structured document
|
|
25
|
-
* an `env:` block is indistinguishable from any other mapping once the scan
|
|
26
|
-
* loses its place, so only `UPPER_SNAKE` is accepted. The cost is a lowercase
|
|
27
|
-
* variable in a manifest, which is rare; the alternative is turning a stray
|
|
28
|
-
* key into a declaration.
|
|
29
|
-
* 2. **A block ends at the first line indented no deeper than its header.** No
|
|
30
|
-
* document model, no continuation handling, no anchors. A construct this scan
|
|
31
|
-
* cannot follow ends the block early, which *loses* names — a disclosed gap
|
|
32
|
-
* rather than a wrong one.
|
|
33
|
-
* 3. **A commented-out declaration counts, and is marked.** `# STRIPE_KEY=` in a
|
|
34
|
-
* sample file documents that the variable exists, which is exactly the
|
|
35
|
-
* question being asked. Treating it as absent would report every well
|
|
36
|
-
* documented optional setting as undeclared.
|
|
37
|
-
*
|
|
38
|
-
* ## The example/supply distinction
|
|
39
|
-
*
|
|
40
|
-
* `.env.example` **documents**; `.env.development` and a container manifest
|
|
41
|
-
* **supply**. Both are declarations for the purpose of "does this repository know
|
|
42
|
-
* this variable exists", and they are not interchangeable for anything else, so
|
|
43
|
-
* the distinction is carried on the surface rather than flattened.
|
|
44
|
-
*/
|
|
1
|
+
/** §15's env/config check reads `.env`/manifests/CI directly — formats, not
|
|
2
|
+
* languages, so it never crosses the IR boundary (DEC-120). Precision over
|
|
3
|
+
* recall: strict names, lossy block-end, commented lines count.
|
|
4
|
+
* `.env.example` documents, others supply. */
|
|
45
5
|
import { readFileSync, readdirSync, statSync } from "node:fs";
|
|
46
6
|
import { join, relative, sep } from "node:path";
|
|
47
7
|
const DEFAULT_MAX_DEPTH = 5;
|
|
48
8
|
const DEFAULT_MAX_FILES = 20_000;
|
|
49
|
-
/**
|
|
50
|
-
*
|
|
51
|
-
|
|
52
|
-
*
|
|
53
|
-
* configuration is not this repository's declaration of anything. Including one
|
|
54
|
-
* would put another project's variable names into the denominator of the
|
|
55
|
-
* coverage guard, which is the number that decides whether anything is reported
|
|
56
|
-
* at all.
|
|
57
|
-
*
|
|
58
|
-
* **The rule is structural, not a list of ecosystems' cache directories.** The
|
|
59
|
-
* first version of this was such a list and the boundary lint rejected it, which
|
|
60
|
-
* was the correct call: engine code that knows one ecosystem's build cache by
|
|
61
|
-
* name is engine code that will be missing the next one's. Every dotted directory
|
|
62
|
-
* is skipped apart from the ones that hold pipeline definitions.
|
|
63
|
-
*
|
|
64
|
-
* **`node_modules`, `vendor`, `target`, `dist`, `build`, `out` and `coverage`
|
|
65
|
-
* used to sit here too**, and DEC-110 recorded them as the unfinished half of its
|
|
66
|
-
* own ruling — *"three ecosystems' names in the skip list"* — while naming the end
|
|
67
|
-
* state: `noiseDirectories` on `CapabilityMatrix`, declared per adapter. They are
|
|
68
|
-
* gone from the engine now and arrive through `ScanOptions.noiseDirectories`
|
|
69
|
-
* instead. **The knowledge moved to the layer that has it; a second list was not
|
|
70
|
-
* created** — DEC-110's *"what must not happen is a third list."*
|
|
71
|
-
*
|
|
72
|
-
* The cost is real and disclosed rather than hidden: with nothing declared, a
|
|
73
|
-
* dependency tree in an undotted directory is walked and a sample inside it is
|
|
74
|
-
* read. `SurfaceScan.noiseDirectories` reports the set actually used, so an empty
|
|
75
|
-
* declaration cannot pass for a complete one (rule 7), and
|
|
76
|
-
* `bench/env-precision.mjs` still reports the surface count per repository.
|
|
77
|
-
*/
|
|
78
|
-
/**
|
|
79
|
-
* Dotted directories that are walked anyway, because **configuration lives in
|
|
80
|
-
* them**.
|
|
81
|
-
*
|
|
82
|
-
* The list started as pipelines only and that was too narrow — found by the
|
|
83
|
-
* decisions denominator, not by reasoning. `dispatch` keeps a real
|
|
84
|
-
* `.devcontainer/.env.example` documenting five variables; skipping it made the
|
|
85
|
-
* declaration surface incomplete, which moved the coverage guard *and* made
|
|
86
|
-
* three variables look undocumented when the repository documents all three. A
|
|
87
|
-
* missing declaration source does not fail loudly here: it silently turns
|
|
88
|
-
* correct suppressions into findings.
|
|
89
|
-
*
|
|
90
|
-
* These are directories a human authors configuration in, as opposed to ones a
|
|
91
|
-
* tool writes state into — which is the distinction the dotted-skip rule is
|
|
92
|
-
* reaching for and cannot express structurally. DEC-110 records the end state:
|
|
93
|
-
* the adapter declares its own noise directories and this list goes away.
|
|
94
|
-
*/
|
|
9
|
+
/** Skip vendored/build dirs structurally (dotted-dir rule, not an ecosystem
|
|
10
|
+
* list) so another project's `.env.example` can't pollute the denominator. */
|
|
11
|
+
/** Dotted dirs walked anyway — config lives here. Missing one silently turns
|
|
12
|
+
* correct suppressions into findings. Adapter-declared list (DEC-110) replaces this. */
|
|
95
13
|
const CONFIG_DIRECTORIES = new Set([
|
|
96
14
|
".github",
|
|
97
15
|
".circleci",
|
|
@@ -99,22 +17,36 @@ const CONFIG_DIRECTORIES = new Set([
|
|
|
99
17
|
".devcontainer",
|
|
100
18
|
".config",
|
|
101
19
|
]);
|
|
102
|
-
/**
|
|
103
|
-
* Shared with the migration scan, so the two walks cannot disagree about what
|
|
104
|
-
* counts as vendored. A second copy of this rule is a second place to forget the
|
|
105
|
-
* next ecosystem.
|
|
106
|
-
*/
|
|
20
|
+
/** Shared with the migration scan — one rule, not two that can disagree. */
|
|
107
21
|
export function skipDirectory(name, noiseDirectories = []) {
|
|
108
|
-
//
|
|
109
|
-
//
|
|
110
|
-
// declares what its ecosystem installs, not what the engine's own rule means.
|
|
22
|
+
// Structural check first: a declaration can't re-admit a dotted dir or
|
|
23
|
+
// exclude `.github`; adapters declare installs, not the engine's own rule.
|
|
111
24
|
if (name.startsWith("."))
|
|
112
25
|
return !CONFIG_DIRECTORIES.has(name);
|
|
113
26
|
return noiseDirectories.includes(name);
|
|
114
27
|
}
|
|
115
|
-
/**
|
|
116
|
-
|
|
117
|
-
|
|
28
|
+
/**
|
|
29
|
+
* `.env`, `.env.local`, `.env-production` — but not `.env.d.ts` or `.envrc`.
|
|
30
|
+
*
|
|
31
|
+
* **The separator is `[.-]`, not `.`, and the leading dot is optional on an
|
|
32
|
+
* example file.** Both were `.`-and-dot-only, and both spellings the pattern
|
|
33
|
+
* missed are in real repositories: `.env-example` and `env.example`. The cost
|
|
34
|
+
* was not a missing surface, it was a **one-sided comparison** — with no
|
|
35
|
+
* example file read, every variable a `.env` sets reads as documented nowhere,
|
|
36
|
+
* so the check either reports the whole file or, past the coverage floor,
|
|
37
|
+
* reports nothing and says the examples cover 0%.
|
|
38
|
+
*
|
|
39
|
+
* The dotless form is admitted **only when it carries an example suffix**. A
|
|
40
|
+
* bare `env` is as likely a shell script or a directory as a declaration, and
|
|
41
|
+
* `env.ts` is code; requiring the suffix keeps both out rather than relying on
|
|
42
|
+
* the reader finding no `KEY=` in them.
|
|
43
|
+
*/
|
|
44
|
+
const DOTENV = /^\.env([.-][A-Za-z0-9_.-]+)?$/;
|
|
45
|
+
/** `env.example`, `env-sample` — the same file, without the leading dot. */
|
|
46
|
+
const BARE_ENV_EXAMPLE = /^env[.-](example|sample|template|dist|defaults?)$/i;
|
|
47
|
+
/** TypeScript that happens to be named for the environment. Never a declaration. */
|
|
48
|
+
const DECLARATION_FILE = /\.d\.[cm]?ts$/i;
|
|
49
|
+
const EXAMPLE_SUFFIX = /[.-](example|sample|template|dist|defaults?)$/i;
|
|
118
50
|
const CONTAINER_MANIFEST = /^(docker-)?compose([.-][A-Za-z0-9_.-]+)?\.ya?ml$/i;
|
|
119
51
|
const IMAGE_BUILD = /^(Containerfile|Dockerfile)([.-][A-Za-z0-9_.-]+)?$/i;
|
|
120
52
|
const STRUCTURED = /\.ya?ml$/i;
|
|
@@ -124,15 +56,8 @@ const WRANGLER_TOML = /^wrangler\.toml$/;
|
|
|
124
56
|
const UPPER_SNAKE = /^[A-Z][A-Z0-9_]*$/;
|
|
125
57
|
/** Any identifier shape, for the unambiguous `KEY=` form. */
|
|
126
58
|
const ANY_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
127
|
-
/**
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
* Structured documents are only opened when their path says they are a manifest
|
|
131
|
-
* or a workflow. Opening every YAML file in a repository would pull in test
|
|
132
|
-
* data, schema definitions and dependency lockfiles, and an `env:` key inside a
|
|
133
|
-
* schema definition is a description of a variable rather than a declaration of
|
|
134
|
-
* one.
|
|
135
|
-
*/
|
|
59
|
+
/** Reads every config surface. Structured docs open only when their path
|
|
60
|
+
* names a manifest/workflow, else a schema `env:` key would count as one. */
|
|
136
61
|
export function scanConfigSurfaces(root, options = {}) {
|
|
137
62
|
const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;
|
|
138
63
|
const maxFiles = options.maxFiles ?? DEFAULT_MAX_FILES;
|
|
@@ -161,6 +86,9 @@ export function scanConfigSurfaces(root, options = {}) {
|
|
|
161
86
|
directory = statSync(full).isDirectory();
|
|
162
87
|
}
|
|
163
88
|
catch {
|
|
89
|
+
// Same as an unreadable dir, on one entry (broken symlink, perm error,
|
|
90
|
+
// race). Disclosed via `unreadable` (rule 7), not dropped silently.
|
|
91
|
+
unreadable.push(rel(root, full));
|
|
164
92
|
continue;
|
|
165
93
|
}
|
|
166
94
|
if (directory) {
|
|
@@ -188,17 +116,16 @@ export function scanConfigSurfaces(root, options = {}) {
|
|
|
188
116
|
return { surfaces, unreadable, truncated, noiseDirectories };
|
|
189
117
|
}
|
|
190
118
|
function classify(root, dir, entry) {
|
|
191
|
-
if (DOTENV.test(entry)) {
|
|
192
|
-
const example = EXAMPLE_SUFFIX.test(entry)
|
|
119
|
+
if ((DOTENV.test(entry) || BARE_ENV_EXAMPLE.test(entry)) && !DECLARATION_FILE.test(entry)) {
|
|
120
|
+
const example = EXAMPLE_SUFFIX.test(entry);
|
|
193
121
|
// An example file states what exists; a concrete one states what is set.
|
|
194
122
|
// Neither is on a path to production by itself, so both are declarations —
|
|
195
123
|
// the deploy target is the manifest that mounts them.
|
|
196
124
|
return { format: "dotenv", role: "declaration", example };
|
|
197
125
|
}
|
|
198
126
|
if (WRANGLER_TOML.test(entry)) {
|
|
199
|
-
// Same status `.env.development
|
|
200
|
-
//
|
|
201
|
-
// `.env.development` are read the same way for the same reason.
|
|
127
|
+
// Same status as `.env.development`: repo's own statement, not a deploy
|
|
128
|
+
// manifest — `[vars]` read the same way for the same reason.
|
|
202
129
|
return { format: "wranglerVars", role: "declaration", example: false };
|
|
203
130
|
}
|
|
204
131
|
if (IMAGE_BUILD.test(entry)) {
|
|
@@ -212,13 +139,8 @@ function classify(root, dir, entry) {
|
|
|
212
139
|
}
|
|
213
140
|
return null;
|
|
214
141
|
}
|
|
215
|
-
/**
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
* Named rather than pattern-matched on content: a document that happens to
|
|
219
|
-
* contain an `env:` key is not necessarily setting one, and guessing from
|
|
220
|
-
* content is how a schema fragment becomes a declaration.
|
|
221
|
-
*/
|
|
142
|
+
/** Only path-classified pipeline docs are opened — matching content (an
|
|
143
|
+
* `env:` key) would turn a schema fragment into a false declaration. */
|
|
222
144
|
function isPipelineDirectory(dir) {
|
|
223
145
|
const parts = dir.split("/");
|
|
224
146
|
return (parts.includes("workflows") ||
|
|
@@ -250,8 +172,7 @@ export function readDotenv(text) {
|
|
|
250
172
|
for (let i = 0; i < lines.length; i += 1) {
|
|
251
173
|
const raw = lines[i] ?? "";
|
|
252
174
|
const commented = /^\s*#/.test(raw);
|
|
253
|
-
// `export KEY=value`
|
|
254
|
-
// common in deployment scripts.
|
|
175
|
+
// `export KEY=value` — shell-sourceable form, common in deploy scripts.
|
|
255
176
|
const match = /^\s*(?:#\s*)?(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/.exec(raw);
|
|
256
177
|
if (match === null)
|
|
257
178
|
continue;
|
|
@@ -290,13 +211,8 @@ export function readImageBuild(text) {
|
|
|
290
211
|
}
|
|
291
212
|
return dedupe(out);
|
|
292
213
|
}
|
|
293
|
-
/**
|
|
294
|
-
* `
|
|
295
|
-
*
|
|
296
|
-
* Mapping — `KEY: value` — and sequence — `- KEY=value` or a bare `- KEY`. The
|
|
297
|
-
* bare sequence form declares a pass-through from the host, which is still the
|
|
298
|
-
* document stating that the variable exists.
|
|
299
|
-
*/
|
|
214
|
+
/** `env:`/`environment:` blocks: mapping (`KEY: value`) or sequence
|
|
215
|
+
* (`- KEY=value` / bare `- KEY`, a host pass-through — still a declaration). */
|
|
300
216
|
export function readStructured(text) {
|
|
301
217
|
const out = [];
|
|
302
218
|
const lines = text.split(/\r?\n/);
|
|
@@ -334,20 +250,9 @@ function wranglerTableEnvironment(table) {
|
|
|
334
250
|
return "default";
|
|
335
251
|
return WRANGLER_ENV_VARS_TABLE.exec(trimmed)?.[1] ?? null;
|
|
336
252
|
}
|
|
337
|
-
/**
|
|
338
|
-
*
|
|
339
|
-
*
|
|
340
|
-
* Every other table — `[[kv_namespaces]]`, `[assets]`, `[env.<name>]` itself
|
|
341
|
-
* (the deploy target's own settings, not its vars) — is out of scope by
|
|
342
|
-
* construction rather than by exclusion list: entering *any* table this
|
|
343
|
-
* function does not recognise as a vars table resets tracking to "outside",
|
|
344
|
-
* so a line that merely looks like `KEY = value` inside `[[kv_namespaces]]`
|
|
345
|
-
* (e.g. `binding = "HOSTNAMES"`) is never mistaken for a declared variable.
|
|
346
|
-
* `[[...]]` array-of-tables headers are matched and reset scope the same way,
|
|
347
|
-
* rather than silently falling through as an unrecognised line — an
|
|
348
|
-
* `[[env.staging.kv_namespaces]]` line right after `[env.staging.vars]` must
|
|
349
|
-
* end that table, not extend it.
|
|
350
|
-
*/
|
|
253
|
+
/** Only `[vars]`/`[env.<name>.vars]` tables are read; any other table (or
|
|
254
|
+
* `[[...]]` header) resets scope to "outside", so `[[kv_namespaces]]` lines
|
|
255
|
+
* are never mistaken for a var. */
|
|
351
256
|
export function readWranglerVarsEntries(text) {
|
|
352
257
|
const out = [];
|
|
353
258
|
const lines = text.split(/\r?\n/);
|
|
@@ -394,8 +299,7 @@ function dedupe(declarations) {
|
|
|
394
299
|
const seen = new Map();
|
|
395
300
|
for (const declaration of declarations) {
|
|
396
301
|
const existing = seen.get(declaration.name);
|
|
397
|
-
//
|
|
398
|
-
// "set here" is a stronger fact than "documented here".
|
|
302
|
+
// Active assignment outranks a later commented one: "set" beats "documented".
|
|
399
303
|
if (existing === undefined || (existing.commented && !declaration.commented)) {
|
|
400
304
|
seen.set(declaration.name, declaration);
|
|
401
305
|
}
|