@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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Descry
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/capabilities/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC3E,YAAY,EACV,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/capabilities/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A check declares what it needs; the engine refuses to run it if no loaded
|
|
3
|
+
* producer can supply that. DEC-112's implementation.
|
|
4
|
+
*
|
|
5
|
+
* ## The defect this makes impossible
|
|
6
|
+
*
|
|
7
|
+
* Three static checks read their graph side with `nodesOfType("FILE")`. **No
|
|
8
|
+
* shipped adapter emits a `FILE` node** — all nine use `MODULE`. So the graph
|
|
9
|
+
* half of every one of them was dead on every real repository, and 48 tests and
|
|
10
|
+
* three precision gates stayed green throughout, because all four instruments
|
|
11
|
+
* minted the node type the check wanted.
|
|
12
|
+
*
|
|
13
|
+
* The fact was *already known*. `packages/core/src/tiers/ladder.ts` records it in
|
|
14
|
+
* a comment, written after the tier ladder required `FILE` and failed every
|
|
15
|
+
* adapter at Tier C. A comment is not reachable from the place the next person
|
|
16
|
+
* writes a check.
|
|
17
|
+
*
|
|
18
|
+
* **`capabilities()` has declared `nodeTypes` since the adapter contract was
|
|
19
|
+
* written** (`packages/ir/src/contracts.ts`). Nobody asked it. This module is
|
|
20
|
+
* the asking.
|
|
21
|
+
*
|
|
22
|
+
* ## Declared, not emitted — and the distinction is the whole design
|
|
23
|
+
*
|
|
24
|
+
* The precondition is checked against what loaded producers **declare**, never
|
|
25
|
+
* against what a particular run emitted. Those are different failures and only
|
|
26
|
+
* one of them is a bug:
|
|
27
|
+
*
|
|
28
|
+
* | situation | verdict | why |
|
|
29
|
+
* | --- | --- | --- |
|
|
30
|
+
* | no loaded producer *declares* the type | **refuse** | the check can never work here; running it produces an empty result indistinguishable from a clean repository |
|
|
31
|
+
* | a producer declares it, this run emitted none | **run** | a legitimately empty answer, disclosed by the check in the ordinary way |
|
|
32
|
+
*
|
|
33
|
+
* Conflating them would make every quiet repository look like a wiring bug, and
|
|
34
|
+
* DEC-070 already machine-checks that a declaration matches what the adapter
|
|
35
|
+
* emitted, so a declaration is evidence rather than a promise.
|
|
36
|
+
*
|
|
37
|
+
* ## Refusal is `not_analysable`, not a crash
|
|
38
|
+
*
|
|
39
|
+
* §20.2's four categories are the point: *"we found nothing"* and *"we cannot
|
|
40
|
+
* look"* are different sentences. A refusal names the missing type and the
|
|
41
|
+
* producers that were loaded, so the answer a user sees is the second sentence
|
|
42
|
+
* rather than an empty list. It does not throw, because a repository analysed
|
|
43
|
+
* with only a Ruby adapter legitimately lacks most types — that is degradation,
|
|
44
|
+
* which is disclosed, not a defect.
|
|
45
|
+
*/
|
|
46
|
+
import type { CapabilityMatrix, EdgeType, NodeType } from "@descryy/ir";
|
|
47
|
+
export interface CapabilityRequirement {
|
|
48
|
+
/** The check's name, used in the refusal so a reader knows what did not run. */
|
|
49
|
+
readonly check: string;
|
|
50
|
+
readonly nodeTypes?: readonly NodeType[];
|
|
51
|
+
readonly edgeTypes?: readonly EdgeType[];
|
|
52
|
+
/**
|
|
53
|
+
* `attrs` keys the check reads, such as `envReads`.
|
|
54
|
+
*
|
|
55
|
+
* **Declared for the reader, never enforced**, and that asymmetry is
|
|
56
|
+
* deliberate: `capabilities()` describes node and edge types and says nothing
|
|
57
|
+
* about `attrs`, because nothing above the IR may read `attrs` (rule 9). So
|
|
58
|
+
* this cannot be machine-checked without extending the contract, and claiming
|
|
59
|
+
* to check it would be worse than not checking it. It is carried so a refusal
|
|
60
|
+
* can say *which attribute* is missing when the type is present and the data
|
|
61
|
+
* is not.
|
|
62
|
+
*/
|
|
63
|
+
readonly attrKeys?: readonly string[];
|
|
64
|
+
}
|
|
65
|
+
export interface ProducerCapabilities {
|
|
66
|
+
readonly id: string;
|
|
67
|
+
readonly capabilities: CapabilityMatrix;
|
|
68
|
+
}
|
|
69
|
+
export type PreconditionVerdict = {
|
|
70
|
+
readonly satisfied: true;
|
|
71
|
+
} | {
|
|
72
|
+
readonly satisfied: false;
|
|
73
|
+
readonly missingNodeTypes: readonly NodeType[];
|
|
74
|
+
readonly missingEdgeTypes: readonly EdgeType[];
|
|
75
|
+
/** One sentence, in §20.2's *not analysable* voice. */
|
|
76
|
+
readonly reason: string;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Can this check run against the producers that are loaded?
|
|
80
|
+
*
|
|
81
|
+
* **An empty producer list refuses everything**, which is correct rather than
|
|
82
|
+
* pedantic: a check run with no producers loaded returns an empty result, and an
|
|
83
|
+
* empty result from no data reads exactly like an empty result from clean code.
|
|
84
|
+
*/
|
|
85
|
+
export declare function checkPreconditions(requirement: CapabilityRequirement, producers: readonly ProducerCapabilities[]): PreconditionVerdict;
|
|
86
|
+
/**
|
|
87
|
+
* The same question asked the other way, for an audit rather than for a run:
|
|
88
|
+
* **which declared requirements can no loaded producer satisfy?**
|
|
89
|
+
*
|
|
90
|
+
* DEC-112's rule is that at least one gate per capability must consume what a
|
|
91
|
+
* shipped producer actually emits. This is how you find the ones that do not,
|
|
92
|
+
* on purpose rather than by accident — five instances were found by accident,
|
|
93
|
+
* and that is only the count so far.
|
|
94
|
+
*/
|
|
95
|
+
export declare function auditRequirements(requirements: readonly CapabilityRequirement[], producers: readonly ProducerCapabilities[]): readonly {
|
|
96
|
+
readonly requirement: CapabilityRequirement;
|
|
97
|
+
readonly verdict: PreconditionVerdict;
|
|
98
|
+
}[];
|
|
99
|
+
//# sourceMappingURL=preconditions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preconditions.d.ts","sourceRoot":"","sources":["../../src/capabilities/preconditions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAExE,MAAM,WAAW,qBAAqB;IACpC,gFAAgF;IAChF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAC;IACzC,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAC;IACzC;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,YAAY,EAAE,gBAAgB,CAAC;CACzC;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAA;CAAE,GAC5B;IACE,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC;IAC1B,QAAQ,CAAC,gBAAgB,EAAE,SAAS,QAAQ,EAAE,CAAC;IAC/C,QAAQ,CAAC,gBAAgB,EAAE,SAAS,QAAQ,EAAE,CAAC;IAC/C,uDAAuD;IACvD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,CAAC;AAEN;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,qBAAqB,EAClC,SAAS,EAAE,SAAS,oBAAoB,EAAE,GACzC,mBAAmB,CA2BrB;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,SAAS,qBAAqB,EAAE,EAC9C,SAAS,EAAE,SAAS,oBAAoB,EAAE,GACzC,SAAS;IAAE,QAAQ,CAAC,WAAW,EAAE,qBAAqB,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAA;CAAE,EAAE,CAKnG"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A check declares what it needs; the engine refuses to run it if no loaded
|
|
3
|
+
* producer can supply that. DEC-112's implementation.
|
|
4
|
+
*
|
|
5
|
+
* ## The defect this makes impossible
|
|
6
|
+
*
|
|
7
|
+
* Three static checks read their graph side with `nodesOfType("FILE")`. **No
|
|
8
|
+
* shipped adapter emits a `FILE` node** — all nine use `MODULE`. So the graph
|
|
9
|
+
* half of every one of them was dead on every real repository, and 48 tests and
|
|
10
|
+
* three precision gates stayed green throughout, because all four instruments
|
|
11
|
+
* minted the node type the check wanted.
|
|
12
|
+
*
|
|
13
|
+
* The fact was *already known*. `packages/core/src/tiers/ladder.ts` records it in
|
|
14
|
+
* a comment, written after the tier ladder required `FILE` and failed every
|
|
15
|
+
* adapter at Tier C. A comment is not reachable from the place the next person
|
|
16
|
+
* writes a check.
|
|
17
|
+
*
|
|
18
|
+
* **`capabilities()` has declared `nodeTypes` since the adapter contract was
|
|
19
|
+
* written** (`packages/ir/src/contracts.ts`). Nobody asked it. This module is
|
|
20
|
+
* the asking.
|
|
21
|
+
*
|
|
22
|
+
* ## Declared, not emitted — and the distinction is the whole design
|
|
23
|
+
*
|
|
24
|
+
* The precondition is checked against what loaded producers **declare**, never
|
|
25
|
+
* against what a particular run emitted. Those are different failures and only
|
|
26
|
+
* one of them is a bug:
|
|
27
|
+
*
|
|
28
|
+
* | situation | verdict | why |
|
|
29
|
+
* | --- | --- | --- |
|
|
30
|
+
* | no loaded producer *declares* the type | **refuse** | the check can never work here; running it produces an empty result indistinguishable from a clean repository |
|
|
31
|
+
* | a producer declares it, this run emitted none | **run** | a legitimately empty answer, disclosed by the check in the ordinary way |
|
|
32
|
+
*
|
|
33
|
+
* Conflating them would make every quiet repository look like a wiring bug, and
|
|
34
|
+
* DEC-070 already machine-checks that a declaration matches what the adapter
|
|
35
|
+
* emitted, so a declaration is evidence rather than a promise.
|
|
36
|
+
*
|
|
37
|
+
* ## Refusal is `not_analysable`, not a crash
|
|
38
|
+
*
|
|
39
|
+
* §20.2's four categories are the point: *"we found nothing"* and *"we cannot
|
|
40
|
+
* look"* are different sentences. A refusal names the missing type and the
|
|
41
|
+
* producers that were loaded, so the answer a user sees is the second sentence
|
|
42
|
+
* rather than an empty list. It does not throw, because a repository analysed
|
|
43
|
+
* with only a Ruby adapter legitimately lacks most types — that is degradation,
|
|
44
|
+
* which is disclosed, not a defect.
|
|
45
|
+
*/
|
|
46
|
+
/**
|
|
47
|
+
* Can this check run against the producers that are loaded?
|
|
48
|
+
*
|
|
49
|
+
* **An empty producer list refuses everything**, which is correct rather than
|
|
50
|
+
* pedantic: a check run with no producers loaded returns an empty result, and an
|
|
51
|
+
* empty result from no data reads exactly like an empty result from clean code.
|
|
52
|
+
*/
|
|
53
|
+
export function checkPreconditions(requirement, producers) {
|
|
54
|
+
const declaredNodes = new Set();
|
|
55
|
+
const declaredEdges = new Set();
|
|
56
|
+
for (const producer of producers) {
|
|
57
|
+
for (const type of producer.capabilities.nodeTypes)
|
|
58
|
+
declaredNodes.add(type);
|
|
59
|
+
for (const type of producer.capabilities.edgeTypes)
|
|
60
|
+
declaredEdges.add(type);
|
|
61
|
+
}
|
|
62
|
+
const missingNodeTypes = (requirement.nodeTypes ?? []).filter((t) => !declaredNodes.has(t));
|
|
63
|
+
const missingEdgeTypes = (requirement.edgeTypes ?? []).filter((t) => !declaredEdges.has(t));
|
|
64
|
+
if (missingNodeTypes.length === 0 && missingEdgeTypes.length === 0)
|
|
65
|
+
return { satisfied: true };
|
|
66
|
+
const missing = [...missingNodeTypes, ...missingEdgeTypes].join(", ");
|
|
67
|
+
const who = producers.length === 0
|
|
68
|
+
? "no producer is loaded"
|
|
69
|
+
: `the loaded producers (${producers.map((p) => p.id).join(", ")}) declare none of them`;
|
|
70
|
+
return {
|
|
71
|
+
satisfied: false,
|
|
72
|
+
missingNodeTypes,
|
|
73
|
+
missingEdgeTypes,
|
|
74
|
+
reason: `${requirement.check} needs ${missing}, and ${who}. ` +
|
|
75
|
+
`This is reported as not analysable rather than as an empty result: nothing looked, ` +
|
|
76
|
+
`so "no findings" would be a claim about the code that was never checked.`,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* The same question asked the other way, for an audit rather than for a run:
|
|
81
|
+
* **which declared requirements can no loaded producer satisfy?**
|
|
82
|
+
*
|
|
83
|
+
* DEC-112's rule is that at least one gate per capability must consume what a
|
|
84
|
+
* shipped producer actually emits. This is how you find the ones that do not,
|
|
85
|
+
* on purpose rather than by accident — five instances were found by accident,
|
|
86
|
+
* and that is only the count so far.
|
|
87
|
+
*/
|
|
88
|
+
export function auditRequirements(requirements, producers) {
|
|
89
|
+
return requirements.map((requirement) => ({
|
|
90
|
+
requirement,
|
|
91
|
+
verdict: checkPreconditions(requirement, producers),
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=preconditions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preconditions.js","sourceRoot":"","sources":["../../src/capabilities/preconditions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAsCH;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAChC,WAAkC,EAClC,SAA0C;IAE1C,MAAM,aAAa,GAAG,IAAI,GAAG,EAAY,CAAC;IAC1C,MAAM,aAAa,GAAG,IAAI,GAAG,EAAY,CAAC;IAC1C,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,YAAY,CAAC,SAAS;YAAE,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC5E,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,YAAY,CAAC,SAAS;YAAE,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9E,CAAC;IAED,MAAM,gBAAgB,GAAG,CAAC,WAAW,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5F,MAAM,gBAAgB,GAAG,CAAC,WAAW,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5F,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IAE/F,MAAM,OAAO,GAAG,CAAC,GAAG,gBAAgB,EAAE,GAAG,gBAAgB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtE,MAAM,GAAG,GACP,SAAS,CAAC,MAAM,KAAK,CAAC;QACpB,CAAC,CAAC,uBAAuB;QACzB,CAAC,CAAC,yBAAyB,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,wBAAwB,CAAC;IAE7F,OAAO;QACL,SAAS,EAAE,KAAK;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,MAAM,EACJ,GAAG,WAAW,CAAC,KAAK,UAAU,OAAO,SAAS,GAAG,IAAI;YACrD,qFAAqF;YACrF,0EAA0E;KAC7E,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAC/B,YAA8C,EAC9C,SAA0C;IAE1C,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QACxC,WAAW;QACX,OAAO,EAAE,kBAAkB,CAAC,WAAW,EAAE,SAAS,CAAC;KACpD,CAAC,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The contract engine — §13, both halves, each honest about its own reach.
|
|
3
|
+
*
|
|
4
|
+
* ```
|
|
5
|
+
* API_ROUTE ──SERVES_API──▶ API_ENDPOINT ◀──USES_API── caller
|
|
6
|
+
* │ │
|
|
7
|
+
* USES_TYPE (attrs.roles) attrs.requestType / responseType
|
|
8
|
+
* ▼ ▼
|
|
9
|
+
* DTO ◀───────────── shapes compared at R3 ─────────▶ DTO
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* The **path half** works at R2 and runs today; see `orphans.ts`. The **shape
|
|
13
|
+
* half** needs per-field detail on both sides, and this file is where the two
|
|
14
|
+
* meet.
|
|
15
|
+
*
|
|
16
|
+
* ## Which side is the reader — it flips between request and response
|
|
17
|
+
*
|
|
18
|
+
* A shape mismatch is only a defect in one direction: the side that *reads* a
|
|
19
|
+
* field the other side does not *send*. For a **response** the caller reads and
|
|
20
|
+
* the route sends. For a **request body the route reads and the caller sends**.
|
|
21
|
+
* So the two comparisons are run with their arguments in opposite order, and
|
|
22
|
+
* getting that backwards would report every optional request field in every
|
|
23
|
+
* codebase as a defect.
|
|
24
|
+
*
|
|
25
|
+
* ## What the producers must attach, stated here because the engine is what needs it
|
|
26
|
+
*
|
|
27
|
+
* | side | carrier | key |
|
|
28
|
+
* | --- | --- | --- |
|
|
29
|
+
* | consumer | the `USES_API` edge | `attrs.requestType` / `attrs.responseType` — a node id — or `attrs.requestFields` / `attrs.responseFields`, a list of names |
|
|
30
|
+
* | provider | the route's `USES_TYPE` edge | `attrs.roles`: a list containing `"request"`, `"response"`, or both |
|
|
31
|
+
*
|
|
32
|
+
* **The consumer half does not exist in any adapter yet**, and the report says so
|
|
33
|
+
* by name rather than reporting "no mismatches" — the attribute and the edge, so
|
|
34
|
+
* it reads as a task rather than a shrug:
|
|
35
|
+
*
|
|
36
|
+
* 1. `USES_API` currently carries `attrs.client` and nothing about shape.
|
|
37
|
+
* 2. A route's `USES_TYPE` edges carry no direction, so a request DTO and a
|
|
38
|
+
* response DTO are indistinguishable. Comparing a caller's response
|
|
39
|
+
* expectation against a request schema would produce confident nonsense, so
|
|
40
|
+
* an unroled DTO is refused rather than assumed — even when a route names
|
|
41
|
+
* exactly one, because "one schema" does not say which direction it travels.
|
|
42
|
+
* **`adapter-openapi` now supplies `attrs.roles`**, so the provider half of
|
|
43
|
+
* this is closed; the consumer half is not.
|
|
44
|
+
*/
|
|
45
|
+
import type { IRNode, ResolutionLevel } from "@descryy/ir";
|
|
46
|
+
import type { AdjacencyProvider, QueryResult } from "../query/provider.ts";
|
|
47
|
+
import { type ContractReport, type OrphanOptions } from "./orphans.ts";
|
|
48
|
+
import { type ShapeDifference } from "./shapes.ts";
|
|
49
|
+
export type ShapeDirection = "request" | "response";
|
|
50
|
+
export interface ShapeMismatch {
|
|
51
|
+
readonly endpoint: IRNode;
|
|
52
|
+
readonly direction: ShapeDirection;
|
|
53
|
+
/** The node that reads the shape — the side a missing field breaks. */
|
|
54
|
+
readonly reader: IRNode;
|
|
55
|
+
/** The node that declares it. */
|
|
56
|
+
readonly writer: IRNode;
|
|
57
|
+
readonly differences: readonly ShapeDifference[];
|
|
58
|
+
readonly resolution: ResolutionLevel;
|
|
59
|
+
}
|
|
60
|
+
export interface ShapeCheck {
|
|
61
|
+
/** True when at least one endpoint had a comparable shape on both sides. */
|
|
62
|
+
readonly ran: boolean;
|
|
63
|
+
readonly comparable: number;
|
|
64
|
+
readonly mismatches: readonly ShapeMismatch[];
|
|
65
|
+
/**
|
|
66
|
+
* Endpoints where a shape existed on one side only, by side. The two counts
|
|
67
|
+
* are the size of the gap and point at which producer has to change.
|
|
68
|
+
*/
|
|
69
|
+
readonly consumerOnly: number;
|
|
70
|
+
readonly providerOnly: number;
|
|
71
|
+
/** Routes naming a DTO with no request/response role, so direction is unknown. */
|
|
72
|
+
readonly unroledDtos: number;
|
|
73
|
+
/**
|
|
74
|
+
* Directions where one route named **two different schemas**, so which body a
|
|
75
|
+
* caller reads is unknown. Refused rather than resolved by ranking.
|
|
76
|
+
*/
|
|
77
|
+
readonly ambiguousDirections: number;
|
|
78
|
+
/** Exactly what is missing, in plain words. Never empty when `ran` is false. */
|
|
79
|
+
readonly blockers: readonly string[];
|
|
80
|
+
}
|
|
81
|
+
export interface ContractCheck {
|
|
82
|
+
readonly paths: ContractReport;
|
|
83
|
+
readonly shapes: ShapeCheck;
|
|
84
|
+
}
|
|
85
|
+
export interface ContractOptions extends OrphanOptions {
|
|
86
|
+
/** Skip the shape half entirely — for a fast pre-push run. */
|
|
87
|
+
readonly pathsOnly?: boolean;
|
|
88
|
+
}
|
|
89
|
+
export declare function checkContracts(provider: AdjacencyProvider, options?: ContractOptions): QueryResult<ContractCheck>;
|
|
90
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/contracts/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE3D,OAAO,KAAK,EAAE,iBAAiB,EAAc,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACvF,OAAO,EAAuB,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAC5F,OAAO,EAAwC,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAEzF,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,UAAU,CAAC;AAEpD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC;IACnC,uEAAuE;IACvE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,iCAAiC;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,SAAS,eAAe,EAAE,CAAC;IACjD,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;CACtC;AAED,MAAM,WAAW,UAAU;IACzB,4EAA4E;IAC5E,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,SAAS,aAAa,EAAE,CAAC;IAC9C;;;OAGG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,kFAAkF;IAClF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;OAGG;IACH,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,gFAAgF;IAChF,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;CAC7B;AAED,MAAM,WAAW,eAAgB,SAAQ,aAAa;IACpD,8DAA8D;IAC9D,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC9B;AAqGD,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,iBAAiB,EAC3B,OAAO,GAAE,eAAoB,GAC5B,WAAW,CAAC,aAAa,CAAC,CAuK5B"}
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The contract engine — §13, both halves, each honest about its own reach.
|
|
3
|
+
*
|
|
4
|
+
* ```
|
|
5
|
+
* API_ROUTE ──SERVES_API──▶ API_ENDPOINT ◀──USES_API── caller
|
|
6
|
+
* │ │
|
|
7
|
+
* USES_TYPE (attrs.roles) attrs.requestType / responseType
|
|
8
|
+
* ▼ ▼
|
|
9
|
+
* DTO ◀───────────── shapes compared at R3 ─────────▶ DTO
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* The **path half** works at R2 and runs today; see `orphans.ts`. The **shape
|
|
13
|
+
* half** needs per-field detail on both sides, and this file is where the two
|
|
14
|
+
* meet.
|
|
15
|
+
*
|
|
16
|
+
* ## Which side is the reader — it flips between request and response
|
|
17
|
+
*
|
|
18
|
+
* A shape mismatch is only a defect in one direction: the side that *reads* a
|
|
19
|
+
* field the other side does not *send*. For a **response** the caller reads and
|
|
20
|
+
* the route sends. For a **request body the route reads and the caller sends**.
|
|
21
|
+
* So the two comparisons are run with their arguments in opposite order, and
|
|
22
|
+
* getting that backwards would report every optional request field in every
|
|
23
|
+
* codebase as a defect.
|
|
24
|
+
*
|
|
25
|
+
* ## What the producers must attach, stated here because the engine is what needs it
|
|
26
|
+
*
|
|
27
|
+
* | side | carrier | key |
|
|
28
|
+
* | --- | --- | --- |
|
|
29
|
+
* | consumer | the `USES_API` edge | `attrs.requestType` / `attrs.responseType` — a node id — or `attrs.requestFields` / `attrs.responseFields`, a list of names |
|
|
30
|
+
* | provider | the route's `USES_TYPE` edge | `attrs.roles`: a list containing `"request"`, `"response"`, or both |
|
|
31
|
+
*
|
|
32
|
+
* **The consumer half does not exist in any adapter yet**, and the report says so
|
|
33
|
+
* by name rather than reporting "no mismatches" — the attribute and the edge, so
|
|
34
|
+
* it reads as a task rather than a shrug:
|
|
35
|
+
*
|
|
36
|
+
* 1. `USES_API` currently carries `attrs.client` and nothing about shape.
|
|
37
|
+
* 2. A route's `USES_TYPE` edges carry no direction, so a request DTO and a
|
|
38
|
+
* response DTO are indistinguishable. Comparing a caller's response
|
|
39
|
+
* expectation against a request schema would produce confident nonsense, so
|
|
40
|
+
* an unroled DTO is refused rather than assumed — even when a route names
|
|
41
|
+
* exactly one, because "one schema" does not say which direction it travels.
|
|
42
|
+
* **`adapter-openapi` now supplies `attrs.roles`**, so the provider half of
|
|
43
|
+
* this is closed; the consumer half is not.
|
|
44
|
+
*/
|
|
45
|
+
import { findContractOrphans } from "./orphans.js";
|
|
46
|
+
import { compareShapes, readShape } from "./shapes.js";
|
|
47
|
+
/** Shapes a caller declared on its `USES_API` edge, by direction. */
|
|
48
|
+
function consumerShapes(provider, caller, edgeAttrs) {
|
|
49
|
+
const out = {};
|
|
50
|
+
for (const direction of ["request", "response"]) {
|
|
51
|
+
const idKey = `${direction}Type`;
|
|
52
|
+
const fieldsKey = `${direction}Fields`;
|
|
53
|
+
const id = edgeAttrs[idKey];
|
|
54
|
+
if (typeof id === "string") {
|
|
55
|
+
const node = provider.node(id);
|
|
56
|
+
const shape = node === undefined ? null : readShape(node);
|
|
57
|
+
if (shape !== null) {
|
|
58
|
+
out[direction] = shape;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// Inline names, for a producer that has field names but no node to hang them
|
|
63
|
+
// on. Name-level only — `readShape` will mark it undetailed and the
|
|
64
|
+
// comparator will refuse to compare types against it.
|
|
65
|
+
const names = edgeAttrs[fieldsKey];
|
|
66
|
+
if (Array.isArray(names)) {
|
|
67
|
+
const fields = names.filter((n) => typeof n === "string").map((name) => ({ name }));
|
|
68
|
+
if (fields.length > 0)
|
|
69
|
+
out[direction] = { source: caller, fields, detailed: false };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
74
|
+
/** Shapes the routes serving an endpoint declare, by direction. */
|
|
75
|
+
function providerShapes(provider, routes) {
|
|
76
|
+
const shapes = {};
|
|
77
|
+
const ambiguous = new Set();
|
|
78
|
+
let unroled = 0;
|
|
79
|
+
for (const route of routes) {
|
|
80
|
+
for (const edge of provider.outgoing(route.id, { types: ["USES_TYPE"] })) {
|
|
81
|
+
const target = provider.node(edge.to);
|
|
82
|
+
if (target === undefined)
|
|
83
|
+
continue;
|
|
84
|
+
const shape = readShape(target);
|
|
85
|
+
if (shape === null)
|
|
86
|
+
continue;
|
|
87
|
+
// `roles` is a **list**, and that is not over-engineering. Edge identity is
|
|
88
|
+
// hash(from, to, type) with attrs excluded (DEC-012), so a route naming one
|
|
89
|
+
// schema is exactly one edge — and `PUT /orders/{id}` that takes an `Order`
|
|
90
|
+
// and returns an `Order` is the ordinary REST shape. A singular label would
|
|
91
|
+
// force a guess or drop that pair entirely.
|
|
92
|
+
const raw = edge.attrs?.["roles"];
|
|
93
|
+
const declared = Array.isArray(raw) ? raw.filter((r) => typeof r === "string") : [];
|
|
94
|
+
const roles = declared.filter((r) => r === "request" || r === "response");
|
|
95
|
+
if (roles.length === 0) {
|
|
96
|
+
// Two different things, and conflating them misleads a producer. A
|
|
97
|
+
// schema labelled `errorResponse` has a **known** direction this check
|
|
98
|
+
// does not compare — a 4xx body is a different contract, not an unknown
|
|
99
|
+
// one — while a schema with no usable label really is direction-unknown
|
|
100
|
+
// and is the case a producer has to fix.
|
|
101
|
+
if (declared.length === 0)
|
|
102
|
+
unroled += 1;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
for (const role of roles) {
|
|
106
|
+
const existing = shapes[role];
|
|
107
|
+
if (existing === undefined) {
|
|
108
|
+
shapes[role] = shape;
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
if (existing.source.id === shape.source.id)
|
|
112
|
+
continue;
|
|
113
|
+
// **Two different schemas claiming one direction on one route.**
|
|
114
|
+
// First-wins is a guess wearing a `??=`: whichever schema the adjacency
|
|
115
|
+
// ranking returned first becomes "the response", and that ranking is by
|
|
116
|
+
// resolution then confidence then id — none of which knows which body a
|
|
117
|
+
// caller reads. Measured cost: four of seven findings on a real contract
|
|
118
|
+
// compared a success type against FastAPI's validation error and
|
|
119
|
+
// reported every field of the real response as missing.
|
|
120
|
+
ambiguous.add(`${route.id} ${role}`);
|
|
121
|
+
delete shapes[role];
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// A direction that ended up ambiguous is cleared, so nothing downstream can
|
|
126
|
+
// read a shape two schemas disagreed about.
|
|
127
|
+
return { shapes, unroled, ambiguous: ambiguous.size };
|
|
128
|
+
}
|
|
129
|
+
export function checkContracts(provider, options = {}) {
|
|
130
|
+
const paths = findContractOrphans(provider, options);
|
|
131
|
+
const notes = [...paths.notes];
|
|
132
|
+
if (options.pathsOnly === true) {
|
|
133
|
+
return assemble(provider, paths.data, skipped("the shape half was not requested"), paths, [
|
|
134
|
+
...notes,
|
|
135
|
+
"Only the path half ran. Request and response shapes were not compared.",
|
|
136
|
+
]);
|
|
137
|
+
}
|
|
138
|
+
// Endpoints with both sides present are the only ones a shape comparison can
|
|
139
|
+
// say anything about: with one side missing, the path half has already
|
|
140
|
+
// reported it and a shape check would report the same gap a second time.
|
|
141
|
+
const set = provider.nodesOfType("API_ENDPOINT", ...(options.limit === undefined ? [] : [options.limit]));
|
|
142
|
+
const mismatches = [];
|
|
143
|
+
let comparable = 0;
|
|
144
|
+
let consumerOnly = 0;
|
|
145
|
+
let providerOnly = 0;
|
|
146
|
+
let unroledDtos = 0;
|
|
147
|
+
let ambiguousDirections = 0;
|
|
148
|
+
let floor = 4;
|
|
149
|
+
for (const endpoint of set.nodes) {
|
|
150
|
+
const callers = [];
|
|
151
|
+
const routes = [];
|
|
152
|
+
let edgeFloor = 4;
|
|
153
|
+
for (const edge of provider.incoming(endpoint.id, { types: ["USES_API", "SERVES_API"] })) {
|
|
154
|
+
const other = provider.node(edge.from);
|
|
155
|
+
if (other === undefined)
|
|
156
|
+
continue;
|
|
157
|
+
if (edge.resolution < edgeFloor)
|
|
158
|
+
edgeFloor = edge.resolution;
|
|
159
|
+
if (edge.type === "USES_API") {
|
|
160
|
+
callers.push({ node: other, attrs: edge.attrs ?? {}, resolution: edge.resolution });
|
|
161
|
+
}
|
|
162
|
+
else
|
|
163
|
+
routes.push(other);
|
|
164
|
+
}
|
|
165
|
+
if (callers.length === 0 || routes.length === 0)
|
|
166
|
+
continue;
|
|
167
|
+
const supplied = providerShapes(provider, routes);
|
|
168
|
+
unroledDtos += supplied.unroled;
|
|
169
|
+
ambiguousDirections += supplied.ambiguous;
|
|
170
|
+
for (const caller of callers) {
|
|
171
|
+
const wanted = consumerShapes(provider, caller.node, caller.attrs);
|
|
172
|
+
for (const direction of ["request", "response"]) {
|
|
173
|
+
const consumer = wanted[direction];
|
|
174
|
+
const producer = supplied.shapes[direction];
|
|
175
|
+
if (consumer === undefined && producer === undefined)
|
|
176
|
+
continue;
|
|
177
|
+
if (consumer === undefined) {
|
|
178
|
+
providerOnly += 1;
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
if (producer === undefined) {
|
|
182
|
+
consumerOnly += 1;
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
comparable += 1;
|
|
186
|
+
// The reader is whoever consumes the payload, and it flips: the caller
|
|
187
|
+
// reads a response, the route reads a request body.
|
|
188
|
+
const [reader, writer] = direction === "response" ? [consumer, producer] : [producer, consumer];
|
|
189
|
+
const comparison = compareShapes(reader, writer);
|
|
190
|
+
if (comparison.differences.length === 0)
|
|
191
|
+
continue;
|
|
192
|
+
// Principle 3, at the point the claim is made rather than in the report.
|
|
193
|
+
// A shape claim is not name-level, so R2 evidence caps it at class B
|
|
194
|
+
// however confident the diff looks.
|
|
195
|
+
// `attrs.shapeResolution` when a producer supplies it — DEC-058 one
|
|
196
|
+
// level up. A `USES_API` edge carries two kinds of evidence: the path
|
|
197
|
+
// was matched at R2, the shape may have been read from a type checker at
|
|
198
|
+
// R3. Taking the edge's own resolution for both caps every shape claim
|
|
199
|
+
// at the weaker of the two facts it carries.
|
|
200
|
+
const declaredRes = caller.attrs["shapeResolution"];
|
|
201
|
+
const shapeEvidence = typeof declaredRes === "number" && declaredRes >= 0 && declaredRes <= 4
|
|
202
|
+
? declaredRes
|
|
203
|
+
: caller.resolution;
|
|
204
|
+
const resolution = Math.min(shapeEvidence, reader.detailed && writer.detailed ? 3 : 2);
|
|
205
|
+
if (resolution < floor)
|
|
206
|
+
floor = resolution;
|
|
207
|
+
mismatches.push({
|
|
208
|
+
endpoint,
|
|
209
|
+
direction,
|
|
210
|
+
reader: reader.source,
|
|
211
|
+
writer: writer.source,
|
|
212
|
+
differences: comparison.differences,
|
|
213
|
+
resolution,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
const blockers = [];
|
|
219
|
+
if (comparable === 0) {
|
|
220
|
+
if (consumerOnly === 0) {
|
|
221
|
+
blockers.push("No producer attaches a request or response shape to a USES_API edge. The engine reads " +
|
|
222
|
+
"attrs.requestType / attrs.responseType (a node id) or attrs.requestFields / " +
|
|
223
|
+
"attrs.responseFields (a list of names); a frontend extractor emits the edge today with " +
|
|
224
|
+
"only the client name on it.");
|
|
225
|
+
}
|
|
226
|
+
if (unroledDtos > 0) {
|
|
227
|
+
blockers.push(`${unroledDtos} route-to-DTO link(s) carry no direction. A route's USES_TYPE edge needs ` +
|
|
228
|
+
'attrs.roles listing "request", "response" or both — without it a request schema and a ' +
|
|
229
|
+
"response schema are indistinguishable, and the engine refuses to guess rather than " +
|
|
230
|
+
"compare a caller's response expectation against a request body.");
|
|
231
|
+
}
|
|
232
|
+
if (providerOnly > 0 && consumerOnly === 0 && blockers.length === 0) {
|
|
233
|
+
blockers.push(`${providerOnly} endpoint(s) have a shape on the provider side and none on the consumer ` +
|
|
234
|
+
"side, so there was nothing to compare it against.");
|
|
235
|
+
}
|
|
236
|
+
if (blockers.length === 0) {
|
|
237
|
+
blockers.push("No endpoint had a declared shape on both sides, so no comparison ran. This is not a " +
|
|
238
|
+
"result of zero mismatches.");
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
const shapes = {
|
|
242
|
+
ran: comparable > 0,
|
|
243
|
+
comparable,
|
|
244
|
+
mismatches: mismatches.sort((a, b) => b.resolution - a.resolution ||
|
|
245
|
+
a.endpoint.name.localeCompare(b.endpoint.name) ||
|
|
246
|
+
a.direction.localeCompare(b.direction)),
|
|
247
|
+
consumerOnly,
|
|
248
|
+
providerOnly,
|
|
249
|
+
unroledDtos,
|
|
250
|
+
ambiguousDirections,
|
|
251
|
+
blockers,
|
|
252
|
+
};
|
|
253
|
+
for (const blocker of blockers)
|
|
254
|
+
notes.push(blocker);
|
|
255
|
+
if (ambiguousDirections > 0) {
|
|
256
|
+
notes.push(`${ambiguousDirections} route direction(s) had two different schemas claiming them, so ` +
|
|
257
|
+
"which body a caller reads is unknown and no comparison was made for those. Picking one " +
|
|
258
|
+
"by rank would decide it by whichever row the index reached first.");
|
|
259
|
+
}
|
|
260
|
+
if (shapes.ran) {
|
|
261
|
+
notes.push(`${comparable} shape pair(s) were compared and ${mismatches.length} disagreed. A field the ` +
|
|
262
|
+
"reading side ignores is not reported — only one the reading side needs and the writing " +
|
|
263
|
+
"side does not supply.");
|
|
264
|
+
}
|
|
265
|
+
return assemble(provider, paths.data, shapes, paths, notes, floor);
|
|
266
|
+
}
|
|
267
|
+
function skipped(reason) {
|
|
268
|
+
return {
|
|
269
|
+
ran: false,
|
|
270
|
+
comparable: 0,
|
|
271
|
+
mismatches: [],
|
|
272
|
+
consumerOnly: 0,
|
|
273
|
+
providerOnly: 0,
|
|
274
|
+
unroledDtos: 0,
|
|
275
|
+
ambiguousDirections: 0,
|
|
276
|
+
blockers: [reason],
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
function assemble(provider, paths, shapes, pathResult, notes, shapeFloor = 4) {
|
|
280
|
+
// The floor is the weaker of the two halves, because the answer is both of
|
|
281
|
+
// them. A path check at R2 does not become R3 because a shape check reached it.
|
|
282
|
+
const resolutionFloor = Math.min(pathResult.stamp.resolutionFloor, shapes.ran ? shapeFloor : 4);
|
|
283
|
+
const stamp = { ...provider.baseStamp(), resolutionFloor };
|
|
284
|
+
return {
|
|
285
|
+
data: { paths, shapes },
|
|
286
|
+
stamp,
|
|
287
|
+
truncated: pathResult.truncated,
|
|
288
|
+
notes: [...notes],
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/contracts/engine.ts"],"names":[],"mappings":"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"}
|