@afokapu/atdd-bun 0.5.0 → 0.6.1

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.
Files changed (66) hide show
  1. package/README.md +30 -0
  2. package/conventions/atdd-bun.planner/atdd-bun.planner.acceptance-identity.convention.yaml +27 -0
  3. package/conventions/atdd-bun.planner/atdd-bun.planner.identity-required.convention.yaml +28 -0
  4. package/conventions/atdd-bun.planner/atdd-bun.planner.identity-unique.convention.yaml +27 -0
  5. package/conventions/atdd-bun.planner/atdd-bun.planner.interlocking-participant-resolves.convention.yaml +28 -0
  6. package/conventions/atdd-bun.planner/atdd-bun.planner.parse.convention.yaml +27 -0
  7. package/conventions/atdd-bun.planner/atdd-bun.planner.reference-resolves.convention.yaml +28 -0
  8. package/conventions/atdd-bun.planner/atdd-bun.planner.schema.convention.yaml +30 -0
  9. package/conventions/atdd-bun.planner/atdd-bun.planner.train-wagon-resolves.convention.yaml +26 -0
  10. package/conventions/atdd-bun.topology/atdd-bun.topology.e2e-location.convention.yaml +38 -0
  11. package/conventions/atdd-bun.topology/atdd-bun.topology.feature-source-coverage.convention.yaml +30 -0
  12. package/conventions/atdd-bun.topology/atdd-bun.topology.feature-test-coverage.convention.yaml +29 -0
  13. package/conventions/atdd-bun.topology/atdd-bun.topology.plan-location.convention.yaml +31 -0
  14. package/conventions/atdd-bun.topology/atdd-bun.topology.source-location.convention.yaml +33 -0
  15. package/conventions/atdd-bun.topology/atdd-bun.topology.test-location.convention.yaml +34 -0
  16. package/detectors/atdd_topology/atdd.implementation.yaml +16 -0
  17. package/detectors/atdd_topology/detect.mjs +182 -0
  18. package/detectors/atdd_topology/fixtures/clean/atdd-bun.yaml +2 -0
  19. package/detectors/atdd_topology/fixtures/clean/e2e/interlockings/checkout/nominal.routes.test.ts +4 -0
  20. package/detectors/atdd_topology/fixtures/clean/e2e/journeys/checkout.journey.test.ts +5 -0
  21. package/detectors/atdd_topology/fixtures/clean/implementation/orders/features/place-order/domain/order.ts +4 -0
  22. package/detectors/atdd_topology/fixtures/clean/plan/_journeys/checkout.yaml +4 -0
  23. package/detectors/atdd_topology/fixtures/clean/plan/_trains/_interlockings/checkout.yaml +4 -0
  24. package/detectors/atdd_topology/fixtures/clean/plan/_trains/checkout.yaml +1 -0
  25. package/detectors/atdd_topology/fixtures/clean/plan/orders/E001.yaml +8 -0
  26. package/detectors/atdd_topology/fixtures/clean/plan/orders/_orders.yaml +5 -0
  27. package/detectors/atdd_topology/fixtures/clean/plan/orders/place-order.yaml +3 -0
  28. package/detectors/atdd_topology/fixtures/clean/tests/wagons/orders/features/place-order/unit/order.test.ts +4 -0
  29. package/detectors/atdd_topology/fixtures/dirty/plan/_journeys/checkout.yaml +3 -0
  30. package/detectors/atdd_topology/fixtures/dirty/plan/orders/E001.yaml +4 -0
  31. package/detectors/atdd_topology/fixtures/dirty/plan/orders/_orders.yaml +4 -0
  32. package/detectors/atdd_topology/fixtures/dirty/plan/orders/features/place-order.yaml +3 -0
  33. package/detectors/atdd_topology/fixtures/dirty/src/wagons/orders/features/place-order/domain/forged.ts +2 -0
  34. package/detectors/atdd_topology/fixtures/dirty/src/wagons/orders/features/place-order/domain/order.ts +2 -0
  35. package/detectors/atdd_topology/fixtures/dirty/tests/wagons/orders/features/place-order/unit/order.test.ts +4 -0
  36. package/detectors/atdd_traceability_closure/detect.mjs +5 -2
  37. package/detectors/bun_interlocking_binding/checks/interlocking_runtime_executes.mjs +3 -2
  38. package/detectors/bun_interlocking_binding/detect.mjs +6 -5
  39. package/detectors/bun_interlocking_coverage/_shared/interlocking.mjs +4 -3
  40. package/detectors/bun_interlocking_coverage/checks/interlocking_train_sequence.mjs +2 -2
  41. package/detectors/bun_interlocking_infrastructure/_shared/interlocking.mjs +2 -1
  42. package/detectors/bun_interlocking_infrastructure/checks/journey_runner_boundary.mjs +3 -2
  43. package/detectors/bun_interlocking_infrastructure/checks/journey_station_routing.mjs +2 -1
  44. package/detectors/bun_interlocking_infrastructure/checks/wagon_contract_honoured.mjs +3 -2
  45. package/detectors/bun_tester_discipline_detector/checks/t_acceptance_resolves.mjs +7 -6
  46. package/detectors/planner_docs_capability/atdd.implementation.yaml +7 -0
  47. package/detectors/planner_plan_integrity/atdd.implementation.yaml +1 -0
  48. package/detectors/planner_plan_integrity/detect.mjs +4 -1
  49. package/detectors/planner_plan_integrity/fixtures/dirty/plan/_trains/_interlockings/checkout.yaml +6 -0
  50. package/detectors/planner_plan_integrity/fixtures/dirty/plan/_trains/_interlockings/unnamed.yaml +2 -0
  51. package/detectors/planner_plan_integrity/fixtures/dirty/plan/_trains/dup-a.yaml +7 -0
  52. package/detectors/planner_plan_integrity/fixtures/dirty/plan/_trains/dup-b.yaml +6 -0
  53. package/detectors/planner_plan_integrity/fixtures/dirty/plan/orders/E001.yaml +5 -0
  54. package/detectors/planner_schema_validation/fixtures/dirty/plan/_trains/missing-description.yaml +5 -0
  55. package/integrity.json +65 -24
  56. package/package.json +1 -1
  57. package/planner-nodes/ENFORCEMENT_SCOPE.yaml +11 -1
  58. package/relationships.yaml +224 -0
  59. package/src/docs-capability.ts +3 -0
  60. package/src/enforce.ts +30 -5
  61. package/src/hooks.ts +2 -1
  62. package/src/index.ts +2 -0
  63. package/src/planner-kernel.ts +4 -2
  64. package/src/planner-schema-validator.ts +12 -10
  65. package/src/planner-validators.ts +16 -15
  66. package/src/topology.ts +40 -0
@@ -0,0 +1,6 @@
1
+ schema_version: 1.0.0
2
+ interlocking_id: interlocking:checkout
3
+ title: Checkout
4
+ lifelines:
5
+ - ref: wagon:nobody
6
+ routes: []
@@ -0,0 +1,7 @@
1
+ train_id: train:orders:duplicate
2
+ title: First declaration
3
+ description: Declares an identity a second file also declares.
4
+ themes: [orders]
5
+ participants: [wagon:ghost]
6
+ wagons: [ghost]
7
+ sequence: []
@@ -0,0 +1,6 @@
1
+ train_id: train:orders:duplicate
2
+ title: Second declaration
3
+ description: The duplicate identity.
4
+ themes: [orders]
5
+ participants: []
6
+ sequence: []
@@ -0,0 +1,5 @@
1
+ urn: wmbt:orders:E001
2
+ statement: Place an order.
3
+ acceptances:
4
+ - identity:
5
+ purpose: An acceptance with no acc identity.
@@ -0,0 +1,5 @@
1
+ train_id: train:orders:missing-description
2
+ title: A train without its required description
3
+ themes: [orders]
4
+ participants: [wagon:orders]
5
+ sequence: []
package/integrity.json CHANGED
@@ -1,10 +1,24 @@
1
1
  {
2
- "version": "0.5.0",
2
+ "version": "0.6.1",
3
3
  "files": {
4
4
  "HOOK_AUDIT.md": "5329d840db37671b1918f688ead26865473b87db73dbc75f7c8b2a8bbe8d6d43",
5
5
  "PLANNER_PORT.md": "fb5935bac8b7ac18994de21e43ace3a5ef8cd55f85b0e3349fca261280054f11",
6
- "README.md": "1b2ad5a7a1cc0a5e8f135dd819d077a44b94b549c5d2bbe5f45360221c232863",
6
+ "README.md": "622e7768f567099b0e30ac82f2053c165b8023e571966fc327f77f985ae1be0d",
7
7
  "bunfig.toml": "b9fc65eca9014c5179380259d70e76385a6a80788fa9a2df5fb3eaa5554fd2fe",
8
+ "conventions/atdd-bun.planner/atdd-bun.planner.acceptance-identity.convention.yaml": "81c5c773d5ee15e8d99a2c237aa9846b110b2533df45ebf407d0e3ec6ed3dd03",
9
+ "conventions/atdd-bun.planner/atdd-bun.planner.identity-required.convention.yaml": "e96d7c1455d0c221072d82e7f2b55da1c4f9ceb17718eb6ed96affdeef37675b",
10
+ "conventions/atdd-bun.planner/atdd-bun.planner.identity-unique.convention.yaml": "409ba1d035ed46bc45f3627b62fd3a6a5967d984cc4c071c41be3f3fa887c6d6",
11
+ "conventions/atdd-bun.planner/atdd-bun.planner.interlocking-participant-resolves.convention.yaml": "fef62f58ad2cd6b036556cfbe17d32fedcd13656eb04c0747e955af7f954ff02",
12
+ "conventions/atdd-bun.planner/atdd-bun.planner.parse.convention.yaml": "953ccd7de6d129f1bd17ce680a1a4819bff6d57b379aaa03323bb22cf255ae08",
13
+ "conventions/atdd-bun.planner/atdd-bun.planner.reference-resolves.convention.yaml": "b96927d269692c29c02fee38ecbeb999480791f8dc7486c4072a9ff30183d7d6",
14
+ "conventions/atdd-bun.planner/atdd-bun.planner.schema.convention.yaml": "16d0a26451758b759e6ca1f5b4f38ae1feff129688306ffcc2f70f6d3974b591",
15
+ "conventions/atdd-bun.planner/atdd-bun.planner.train-wagon-resolves.convention.yaml": "6410e248351e701dcba38c671c07c4d8f6d67927984ed4d18e567abd1eb1f3f0",
16
+ "conventions/atdd-bun.topology/atdd-bun.topology.e2e-location.convention.yaml": "3a3b991bc851b86d597636200f5cb10a0defda3920348860cdca28955ab91f4c",
17
+ "conventions/atdd-bun.topology/atdd-bun.topology.feature-source-coverage.convention.yaml": "2b64093f1e7f1fe0e2edcadf12e560fa80cecec19536abaa5bf09af362c6694e",
18
+ "conventions/atdd-bun.topology/atdd-bun.topology.feature-test-coverage.convention.yaml": "279be57399c9b79a1bd758414076e3053d67b7d4a7fcbbb950ea12d1201effeb",
19
+ "conventions/atdd-bun.topology/atdd-bun.topology.plan-location.convention.yaml": "82149598eb329a0f5db0feb345482a99fef65bef90d3fe34768db66406c30e24",
20
+ "conventions/atdd-bun.topology/atdd-bun.topology.source-location.convention.yaml": "7e7bb788eb1ff9cbe6f67dfddc78a20b3800e733ab1036b70adb67e404b77113",
21
+ "conventions/atdd-bun.topology/atdd-bun.topology.test-location.convention.yaml": "a1f7f772a889607d4b6c0f20e9924b88838199a3e763b6328dbe09b8f29f2e50",
8
22
  "conventions/coder.bun/coder.bun.boundaries-http-client.convention.yaml": "b846bb6ced2c4c967466520d52b00ff1ca802dafcdbb2ec2adbd0ce19e752a28",
9
23
  "conventions/coder.bun/coder.bun.commons-application-no-integration.convention.yaml": "f63e7f6442bcdf5cf79f58a091547a1a990d0ee7c006b797fd5187d6f8bf8712",
10
24
  "conventions/coder.bun/coder.bun.commons-cross-feature-imports-in.convention.yaml": "2d66bd3c04186fcef67a89c2b6d81a697f8f43f978ff27284a3b8a3848097182",
@@ -124,8 +138,28 @@
124
138
  "conventions/traceability/traceability.source.tested-by-present.convention.yaml": "27a2340a9dae9eee67a3fbdcea0d2f8f35f222f22dbce7f84b2a0c6ab6321018",
125
139
  "conventions/traceability/traceability.source.tested-by-resolves.convention.yaml": "ad4516670934dc82f1ebf9dc057110313059110302f88b4747dde89dd060870b",
126
140
  "conventions/traceability/traceability.test.binding-resolves.convention.yaml": "03c118f498b1e824d457d25c060c8f9689ccbcca49c58d8bcd158e3cd3144ee9",
141
+ "detectors/atdd_topology/atdd.implementation.yaml": "7879f441a62691bf041b0fd8220feb12996d4a036d74d6c79d0985ee20992efb",
142
+ "detectors/atdd_topology/detect.mjs": "33cb5584ce334352324e4a8331f75697cc9c09f7ebc07e59c5f917ad9879f447",
143
+ "detectors/atdd_topology/fixtures/clean/atdd-bun.yaml": "85049c05fb624037e1e2200a117b07d6c8d089d4e81fd784ade15a860a444f59",
144
+ "detectors/atdd_topology/fixtures/clean/e2e/interlockings/checkout/nominal.routes.test.ts": "be769e192e8165d4d36be743e8df578c1790b900c6b89acc7d2046ba40105135",
145
+ "detectors/atdd_topology/fixtures/clean/e2e/journeys/checkout.journey.test.ts": "345c391888e3e8c93d0437428dc1a3358968c7871ef54d313d6e083717254bbe",
146
+ "detectors/atdd_topology/fixtures/clean/implementation/orders/features/place-order/domain/order.ts": "b81c0630a2c518749ed6d81741ba4e1503ffdbc64f232747518a17e8e8a46927",
147
+ "detectors/atdd_topology/fixtures/clean/plan/_journeys/checkout.yaml": "c61021d0bf2f7f3bfe306b18c4b34563292de02acce47326db71ac4f8d67bc8d",
148
+ "detectors/atdd_topology/fixtures/clean/plan/_trains/_interlockings/checkout.yaml": "99ee3ef93e3098943878c947a584d93fec1407f0a5bd85c5383129229a98d0bc",
149
+ "detectors/atdd_topology/fixtures/clean/plan/_trains/checkout.yaml": "d022cd946cced5961d16535f93cc875b76e2cad872625e5e040242810f8cfad1",
150
+ "detectors/atdd_topology/fixtures/clean/plan/orders/E001.yaml": "97cec4c393561e40252c0f72bed3a471831006e4cf231653506c601df0ed9172",
151
+ "detectors/atdd_topology/fixtures/clean/plan/orders/_orders.yaml": "33f0f30b31e3fb1bedf1ba8d2071dc7cea02749b48d18196038c9d2321aaf628",
152
+ "detectors/atdd_topology/fixtures/clean/plan/orders/place-order.yaml": "cccbad80a40da7bbb52c475fe73f5cd6e523994b428dc133aefc37225b04a80c",
153
+ "detectors/atdd_topology/fixtures/clean/tests/wagons/orders/features/place-order/unit/order.test.ts": "01a9a560d3d977346e39b88a88e7112d9f47f02e8dc8d995ba5fb45f77842153",
154
+ "detectors/atdd_topology/fixtures/dirty/plan/_journeys/checkout.yaml": "407eeb607a94b08d3d48da6b28b6c6102ffe2f5d11a58b9557a3f3a4d1dda1bd",
155
+ "detectors/atdd_topology/fixtures/dirty/plan/orders/E001.yaml": "c3e3fc4784a034a4af8fd5babb6cfae39047e58131d204f76ad838a199ba92f9",
156
+ "detectors/atdd_topology/fixtures/dirty/plan/orders/_orders.yaml": "1d533ed773dd1a6317dfd24abf6aeddd13469321bd07ae60743ee9af58b6531a",
157
+ "detectors/atdd_topology/fixtures/dirty/plan/orders/features/place-order.yaml": "cccbad80a40da7bbb52c475fe73f5cd6e523994b428dc133aefc37225b04a80c",
158
+ "detectors/atdd_topology/fixtures/dirty/src/wagons/orders/features/place-order/domain/forged.ts": "313bff608d93a1a6790932e21d17b4582160df3b4f04642f1cbb04a67fc2131d",
159
+ "detectors/atdd_topology/fixtures/dirty/src/wagons/orders/features/place-order/domain/order.ts": "6fdaad52671ef25b47d93f9b4e97e12c62eb78f5b4cde727435c3ac135a1c0e5",
160
+ "detectors/atdd_topology/fixtures/dirty/tests/wagons/orders/features/place-order/unit/order.test.ts": "f117e6c8b034700e1f00889bea48cb1528f0003d699cfd3e279cd9164b264a38",
127
161
  "detectors/atdd_traceability_closure/atdd.implementation.yaml": "82e56cc85539476e42fc8d58e718bc998f1eff6c325a0cd240c0284625834d68",
128
- "detectors/atdd_traceability_closure/detect.mjs": "e83fa23070fcbe91ee88aa37b965129575fa0f8472eba169491ec737ab4045ec",
162
+ "detectors/atdd_traceability_closure/detect.mjs": "b8c454d7e136cdcc82524fea407490eefc8c2b8c9448831d94d51253f00a38a9",
129
163
  "detectors/atdd_traceability_closure/fixtures/clean/plan/orders/E001.yaml": "0ddad928dde10c2ab690558259a6975125af540a1f30eca9aa0c615bf0ad69fb",
130
164
  "detectors/atdd_traceability_closure/fixtures/clean/src/order.ts": "efe6db7e3f723c7b6096abdf58dec9c88b27ec8978d434a10135b3e77bfce321",
131
165
  "detectors/atdd_traceability_closure/fixtures/clean/test/order.test.ts": "bee451198d472749616f85c1f1e97c0a06ad28255b9a6a2cc8701bd2e8d56562",
@@ -268,8 +302,8 @@
268
302
  "detectors/bun_green_traceability_detector/fixtures/dirty/green_urn_wagon_feature/OrderRow.ts": "eed3e99b3a582a41e7179228ca8c33987fdf0ca1c06d78710951057a2355d902",
269
303
  "detectors/bun_green_traceability_detector/urn_header.mjs": "004b0ed1f71ec476fb57a959d302da4b5869ff91be049865a806bedca40f55b9",
270
304
  "detectors/bun_interlocking_binding/atdd.implementation.yaml": "8df233a7c337d38ab4fc92a309273b91fe713b27507a4b2cfa66ffc7a948d520",
271
- "detectors/bun_interlocking_binding/checks/interlocking_runtime_executes.mjs": "68414ad43c70fae78f703344c98b9d163ddfb078ffa09c268764fc0adb295877",
272
- "detectors/bun_interlocking_binding/detect.mjs": "ca7f35d5ffdc28056c602a178020eba4f7a165d6b65faaecb5e86492320ca724",
305
+ "detectors/bun_interlocking_binding/checks/interlocking_runtime_executes.mjs": "ea4c32914a007962012e9062cc64063fa939ff0a59c07960c34872d058720955",
306
+ "detectors/bun_interlocking_binding/detect.mjs": "42767b7d329b5b2623de37f450c416fe6feb4a7ae737201376e93aa74d493dea",
273
307
  "detectors/bun_interlocking_binding/fixtures/clean/e2e/interlockings/match-resolution/trace.test.ts": "5dadc041ca9825f404340ca428e14bbff5e00824ca6c25464f21cd2ce56044d8",
274
308
  "detectors/bun_interlocking_binding/fixtures/clean/plan/_trains/_interlockings/match-resolution.yaml": "11884309beb9bcceccfeda7917ea73d51a530366db5eb60772b03cf5eeb239cd",
275
309
  "detectors/bun_interlocking_binding/fixtures/clean/plan/_trains/train:match:match-resolution-standard.yaml": "a7067661a723e02e0e844e6b90ad187f620dd328e1b9be45163c04db1919ce77",
@@ -319,14 +353,14 @@
319
353
  "detectors/bun_interlocking_binding/fixtures/dirty_transcribed_runtime/server.ts": "d5bc34c5b1b2b0a511e0c4604ce6f9c77491dca9aee994be720540f3052babc1",
320
354
  "detectors/bun_interlocking_binding/fixtures/dirty_transcribed_runtime/src/trains/interlocking.ts": "9bcfdb4ecff6efd1f658b9fd587342615179924e25468c75daa07c2626d4d8ab",
321
355
  "detectors/bun_interlocking_binding/fixtures/dirty_transcribed_runtime/src/trains/runner.ts": "0e4b885e50f12cc2a8c8f6740bf83e7b2e7137a28e1e143586e9a8550ea5bd45",
322
- "detectors/bun_interlocking_coverage/_shared/interlocking.mjs": "5586a9e2f0f1a253ed2e9555784113e130eaed3db80bffa492cb63a1d7802602",
356
+ "detectors/bun_interlocking_coverage/_shared/interlocking.mjs": "dd484cec27919f342aa5a3ba631cf197acab4f359e7fe0ffd1123f968954fc52",
323
357
  "detectors/bun_interlocking_coverage/atdd.implementation.yaml": "f160517a8138ba3ca05e3d130e6fbfb796e643376f25743fdef4fc210196525b",
324
358
  "detectors/bun_interlocking_coverage/checks/_map.json": "0a218ea319cc6258af7bd721c2154cb9561fe67e80d80ef32d08fc77bc9403c3",
325
359
  "detectors/bun_interlocking_coverage/checks/interlocking_production_runner.mjs": "136eb0955052f2485740adfb888f5ba6f1414dcdb53d505034b8db40420a611a",
326
360
  "detectors/bun_interlocking_coverage/checks/interlocking_route_coverage.mjs": "55716c706818d3f724cdd5f1f16a67b92dacdc4bb4a2d23a037039ddd869acea",
327
361
  "detectors/bun_interlocking_coverage/checks/interlocking_smoke_coverage.mjs": "ea4b0155c4f151a36979d850aa2482901b37eacc0fe01cecc0a736089a3e15ce",
328
362
  "detectors/bun_interlocking_coverage/checks/interlocking_trace_binds.mjs": "61dcb8a8d04e9764aab7920f346bd3684fc98e2c294aa5c58eefec555145a1d0",
329
- "detectors/bun_interlocking_coverage/checks/interlocking_train_sequence.mjs": "f64b331a3dc6f8d5c8519049ba18cc2e4f84e26c1e9471b468aba4e4a39b6c35",
363
+ "detectors/bun_interlocking_coverage/checks/interlocking_train_sequence.mjs": "ab00524af6cce2a95c3a1232f2e6304c761533c2ac3f42d34683b2c0dc5f9c6a",
330
364
  "detectors/bun_interlocking_coverage/detect.mjs": "a124418dc29aaf8fda9cd09427230d25768206b3f563d516774667e8cf75b66e",
331
365
  "detectors/bun_interlocking_coverage/fixtures/clean/interlocking_production_runner/e2e/interlockings/match-resolution/routes.test.ts": "ba6ea85b3fbe15e3c49332da3ad2921a0ff3436a6fe3b5a5035fb35fdc874720",
332
366
  "detectors/bun_interlocking_coverage/fixtures/clean/interlocking_production_runner/e2e/interlockings/match-resolution/trace.test.ts": "aee4ea93ceb8636846344e915cd7e66f7e8f99ba08596f83266590fa2b9ff58e",
@@ -367,7 +401,7 @@
367
401
  "detectors/bun_interlocking_coverage/fixtures/dirty/interlocking_train_sequence/plan/_trains/_interlockings/match-resolution.yaml": "9e0f02cb0889826f2ac2fb88cd8c118c97d4321dcc5fccc0b767a511606841e6",
368
402
  "detectors/bun_interlocking_coverage/fixtures/dirty/interlocking_train_sequence/plan/_trains/train:match:match-resolution-standard.yaml": "9ea90f674e5fc565d8893e74ad2e47f273c971ca29284dbce58a366a3e832428",
369
403
  "detectors/bun_interlocking_coverage/fixtures/dirty/interlocking_train_sequence/plan/_trains/train:match:match-resolution-timeout.yaml": "aa1b7682f99f3a9a25ec0d3d03f3798ddda8c74eb728e148b38197ddab292493",
370
- "detectors/bun_interlocking_infrastructure/_shared/interlocking.mjs": "02b4ad53d52eece9fa892eff3a048ed0ccd991427f61fd64570659ff97c4739f",
404
+ "detectors/bun_interlocking_infrastructure/_shared/interlocking.mjs": "433977b3b8242c0f061924c53e9f7488cd5cc7368edacbe007c14d749cc805f4",
371
405
  "detectors/bun_interlocking_infrastructure/atdd.implementation.yaml": "fa7a1de97b19dff6515100131a3b6fc2dacf2766cd2bd44bc9dd792f6b01590d",
372
406
  "detectors/bun_interlocking_infrastructure/checks/_map.json": "5f86408f98de8f1562e679e2bd3a2194a8eb297fecf677ca774f19905942ec71",
373
407
  "detectors/bun_interlocking_infrastructure/checks/interlocking_delegates.mjs": "1aa4c87e234643e99ba5a2ff1fab3db8bfc7cbc9618c8e1a014eef2c11cce9c7",
@@ -375,9 +409,9 @@
375
409
  "detectors/bun_interlocking_infrastructure/checks/interlocking_resolution_model.mjs": "e761495b19eed0af09fcb4db34126d0e2398e91f086e04f5ef84d0b5c1c3ec16",
376
410
  "detectors/bun_interlocking_infrastructure/checks/interlocking_runner_exists.mjs": "6b63d3f26a51f2dd27847edd27c4d9c9f15c1f02747dba611cebccfc76f13169",
377
411
  "detectors/bun_interlocking_infrastructure/checks/interlocking_station_routing.mjs": "0221f5a8b49763388affefff670bc2a452e539e7658b08f6230a52f13edd36bd",
378
- "detectors/bun_interlocking_infrastructure/checks/journey_runner_boundary.mjs": "336d56f0dd3c0c7f3769a3f41689003e43de51066dbc25e364915fdf50e859bd",
379
- "detectors/bun_interlocking_infrastructure/checks/journey_station_routing.mjs": "018d28eed330b85b0699435158face40a31e0e94d63ae3c4df05cb87400fa152",
380
- "detectors/bun_interlocking_infrastructure/checks/wagon_contract_honoured.mjs": "88f8cf80e526beaa829860f78d1b1578aaf47e2a3fc680e60a957aa91cc0217d",
412
+ "detectors/bun_interlocking_infrastructure/checks/journey_runner_boundary.mjs": "8c7225f5ee387cbf7ba1e536f91c67c331a86025b4b2b38b961488d949cbdb21",
413
+ "detectors/bun_interlocking_infrastructure/checks/journey_station_routing.mjs": "b297f3f677e0239c5d14cf36218fc39ec23024a0f29620dd02945601aad20516",
414
+ "detectors/bun_interlocking_infrastructure/checks/wagon_contract_honoured.mjs": "728f710827295472dadec182fcdf6c3e8fc44cdedeae53a669754be8435fdd7f",
381
415
  "detectors/bun_interlocking_infrastructure/detect.mjs": "54c02f428596e057f828def0d68360b220b55dbf962b46694a21bc423ce57218",
382
416
  "detectors/bun_interlocking_infrastructure/fixtures/clean/interlocking_delegates/server.ts": "36913357fdd3c5e375829a0554c605d70f5c05e2e83349f47505741598f6eb15",
383
417
  "detectors/bun_interlocking_infrastructure/fixtures/clean/interlocking_delegates/src/match/wagon.ts": "ea202fa15fdf9d1391b1ae23343c9d1b09fcf8ef14f1dccfb8114ffaedea97c1",
@@ -476,7 +510,7 @@
476
510
  "detectors/bun_tester_discipline_detector/checks/_map.json": "d28273b975c4fbcda64026178b918dc9a84315d6312f29ae5221a0a9cb4c0b44",
477
511
  "detectors/bun_tester_discipline_detector/checks/t_acceptance_binding.mjs": "17861380275433ff79e191803456417454e2efa23801d9ac72bf6f8206337522",
478
512
  "detectors/bun_tester_discipline_detector/checks/t_acceptance_covers_tag.mjs": "2116c9936cb5863df643b968dece23c29e145ede30cf7c7862e5c17ac7beb6dd",
479
- "detectors/bun_tester_discipline_detector/checks/t_acceptance_resolves.mjs": "4fb51a28fd2e546cbe551dbe997ad29d8d2eb07451491d0220bb8e559514e96b",
513
+ "detectors/bun_tester_discipline_detector/checks/t_acceptance_resolves.mjs": "fe7047cc069be0d8ad85ebb701916a30eca667483d34bc75d4b95baf3b26c168",
480
514
  "detectors/bun_tester_discipline_detector/checks/t_isolation_no_live_state.mjs": "de2c396b83bc2e5317f6b8eee31c98103e7360d1cd25e7c1c53db6ff7627203f",
481
515
  "detectors/bun_tester_discipline_detector/checks/t_red_behavioral.mjs": "ac0b77bbf10a08d991272fbce41db2a34187c8f5faf1e04c5b1a858ecfbcc4ef",
482
516
  "detectors/bun_tester_discipline_detector/checks/t_red_fails_first.mjs": "06cb66f5ccf7d59e1d21f6d3a9db29ca7f3182c096b17ddb50b85b319b97208b",
@@ -663,7 +697,7 @@
663
697
  "detectors/htmx_tester_detector/fixtures/dirty/statusonly.test.ts": "a2daf2874bf68c6221374ac05619642a42d56b5d1f76e30fa3d2a1826adaf51b",
664
698
  "detectors/htmx_tester_detector/test_header.mjs": "a22221fe9ef6d10297ec777c5d0c6e7b84010ccf41e90db30c036206790ea198",
665
699
  "detectors/planner_docs_capability/README.md": "1e1f8ee258242c05293447fcde124543447ba375306e8a7e5f665881b038bcd1",
666
- "detectors/planner_docs_capability/atdd.implementation.yaml": "7e88a43ee43f5131d25debcc8f02f7381c3b356b6d8ea14357a89ead8e83342e",
700
+ "detectors/planner_docs_capability/atdd.implementation.yaml": "0bc4c27c61faa15147ad8ed55a866d7830875efb6222aa463d49f1163a8b6121",
667
701
  "detectors/planner_docs_capability/detect.mjs": "d10773fa5b2d8f65ce351804694171a6eb75e05eb4c80fa1edce4a5d56b72c5d",
668
702
  "detectors/planner_docs_capability/fixtures/clean/docs/architecture/decisions/adr-20260906-001-shared-control-root.adoc": "6d30e5545e7b051c80605c3dbee50286f71e344ab2e71a987db945941de42523",
669
703
  "detectors/planner_docs_capability/fixtures/clean/docs/architecture/decisions/index.adoc": "4a6cb87e249d587c85bb6389ff5fecae7a96194af8677b588eed0c791099123b",
@@ -790,10 +824,15 @@
790
824
  "detectors/planner_docs_capability/fixtures/dirty_unresolved_edge/docs/index.adoc": "8aabcd7a4ecfc6ef565a604c1172364f761bef7d3fc4f2c96c07dce4e0ebe19b",
791
825
  "detectors/planner_docs_capability/fixtures/dirty_unresolved_edge/docs/purpose/index.adoc": "e10193ea48f3c77b67ca8ed7221c53f23ce699e63f651cc340cea9ef6b44cffb",
792
826
  "detectors/planner_docs_capability/fixtures/dirty_unresolved_edge/docs/purpose/worktrees.adoc": "de957bd8aec411c930fa9785d793c3345c82f5d7cb7f28f40f73f1c53a436440",
793
- "detectors/planner_plan_integrity/atdd.implementation.yaml": "8ba6742949d5c72ba66a0eb5f2ebec94ae7a82270de10f985b45944e38742c18",
794
- "detectors/planner_plan_integrity/detect.mjs": "0172b6edaf66cc71cb9f5506ac25e679a90aeea1d0e0e2138689ec5079f87d16",
827
+ "detectors/planner_plan_integrity/atdd.implementation.yaml": "11e6c1a12c9abe5d4c169fd3ba181e13021e4c58b951757dddd4794417db4367",
828
+ "detectors/planner_plan_integrity/detect.mjs": "ee21ec706c48182250dbcb6045521185b2c91cc8dbcdbbad6e417f2dbfe641b8",
795
829
  "detectors/planner_plan_integrity/fixtures/clean/README.md": "d64b0a6ee983757a62b634bb5f64e19f4e5c1eb2e6b23dfd33cf8cb8f3ec0b4a",
830
+ "detectors/planner_plan_integrity/fixtures/dirty/plan/_trains/_interlockings/checkout.yaml": "4d994aae6517b6d8fc2398ca3c37e4a87d999fc559027ae9f2bab0b036e09870",
831
+ "detectors/planner_plan_integrity/fixtures/dirty/plan/_trains/_interlockings/unnamed.yaml": "1e4844007b6679c5d0555e56e088eab3a6d35d0b929261dda3033897e39eace8",
832
+ "detectors/planner_plan_integrity/fixtures/dirty/plan/_trains/dup-a.yaml": "1879b918b34af2a6bb929ae5010619002ece1698bf71ecbcc0414617f88da481",
833
+ "detectors/planner_plan_integrity/fixtures/dirty/plan/_trains/dup-b.yaml": "36bf938cde33a57a0316ffde20fe632b185d9f43a9429df2aa55bdaef987ebf9",
796
834
  "detectors/planner_plan_integrity/fixtures/dirty/plan/broken.yaml": "81865b7554ea4a1eb4598de81265abe0760d9ea722945f5bfff5415bc272e95a",
835
+ "detectors/planner_plan_integrity/fixtures/dirty/plan/orders/E001.yaml": "cc800a145aa136328d0e28dfc46d3911e841b47cf69e2f785cacd1f54c2ed3f6",
797
836
  "detectors/planner_schema_validation/atdd.implementation.yaml": "2daeff9f85558ad6d246ecdd3d7eb7a172dd1bde646b3cf3b64f21a162da721f",
798
837
  "detectors/planner_schema_validation/detect.mjs": "b208e1483e9bae74d3dcff12a824e6dfd0dcb8009affa3c3f58b2a55fe7ae8bf",
799
838
  "detectors/planner_schema_validation/fixtures/clean/contracts/_contracts.yaml": "967f4f0aac0be000cb6107dc735ca21b73a3a21870e9ada1396df445584cad41",
@@ -803,6 +842,7 @@
803
842
  "detectors/planner_schema_validation/fixtures/clean/plan/orders/_orders.yaml": "77d92ee0c9abae5ef7a407d5e0ed5baabf38391d75b91d47b598777ecc6b87ec",
804
843
  "detectors/planner_schema_validation/fixtures/dirty/contracts/_contracts.yaml": "6460d5b8c73bb5f91ae356b29935c0a377cfef2d79ad6180e8cbb8a31fe2e882",
805
844
  "detectors/planner_schema_validation/fixtures/dirty/plan/_themes.yaml": "c3e8fb1939d83fdde56405ddfee68e266a16c4a7ed8439b6f7906d47372df473",
845
+ "detectors/planner_schema_validation/fixtures/dirty/plan/_trains/missing-description.yaml": "34052c4d46487751814cdb65e90beb4964493a3a64331b27e1927a5efb8949c5",
806
846
  "detectors/planner_schema_validation/fixtures/dirty/plan/_trains/orders.yaml": "ae2fdb750fd5a78c0baddd54fada48522671ae2a9a6538c50ab41ca32a90f682",
807
847
  "detectors/planner_static_validators/atdd.implementation.yaml": "030d9999473bd488590a608b6f60f97f2b2c484a183574581edaa262a2e24a10",
808
848
  "detectors/planner_static_validators/detect.mjs": "efbff2e8cd3f1b7d8e3240f132e90f09cc081b9352511f3ade67ec6fe06d124b",
@@ -827,7 +867,7 @@
827
867
  "lib/frontend.mjs": "d6d9b29c3d7f2d162cda03bb34b20a3224a82887b6be3db7cab375510913c9a3",
828
868
  "lib/imports.mjs": "3db4979269488fa26f6e7aefded6ece9c646be6587a10e249821a5a208109962",
829
869
  "lib/scan.mjs": "f232a6178f9b6d3d63ba4056709664b1700d4292c49bad1dec18e9560a7c0461",
830
- "planner-nodes/ENFORCEMENT_SCOPE.yaml": "b9429fb63a31799589461df342bf5fc0bfce5d1739e6ed54fff6b21db04bf775",
870
+ "planner-nodes/ENFORCEMENT_SCOPE.yaml": "d8ec7039c219857f3d77af5d4d84612b533b69c1a5fcef935fbf46470adafed4",
831
871
  "planner-nodes/nodes/planner.acceptance.abstract-fields-required.convention.yaml": "bd565693f0ae861f0561ad2f7a91a8c55f9a209c3acd59c5750cfcffd96a85d8",
832
872
  "planner-nodes/nodes/planner.acceptance.authoring-guidelines.convention.yaml": "16348dceed5868041b832bde766e9c8d4a950d4032f1f3066b357644081a3b17",
833
873
  "planner-nodes/nodes/planner.acceptance.boundary-kind-vocabulary.convention.yaml": "c5645225399568c2d4fe632442f9c597b2c59e4f4239880df7db2cbdc0353c9c",
@@ -1045,22 +1085,23 @@
1045
1085
  "planner-schemas/train.schema.json": "d6fbac9067c1bffeb84eb79a71228441055af6e6e7ba141dd4e0bcb079345ec0",
1046
1086
  "planner-schemas/wagon.schema.json": "57b98f1ade998d745538eb3d72fb3014a50042006870f90bce47028eea336eb4",
1047
1087
  "planner-schemas/wmbt.schema.json": "7a3a5693bfcf01340667c2be4a3c48e74f34b1af7e8dc13372c0de06b7f4fe12",
1048
- "relationships.yaml": "157fd93f9cb9d900944aff7f7f0d3f6e96b2c5b9c5359c4dc9bae75d721ae238",
1088
+ "relationships.yaml": "3a3b4987dacbc6ae566e607183f60503c934bf8c60925943566e6887726d8bbf",
1049
1089
  "src/agent.ts": "38a14f0f2ccce357efb1b2927e59bf55c20ff0050374367f15da36db20c46e77",
1050
1090
  "src/ci.ts": "899125ec76d14f7d0126a5db2249913e373e3a325cbc98d7f053e1351bdf47af",
1051
1091
  "src/cli.ts": "bb2047cee60f48bfe3eaee4c1b3dcd3538a0e1edc170cf58e87686117bea07a7",
1052
- "src/docs-capability.ts": "65ef91658664b41b78184b395e57e5d28bda16128caa9e314f26e63568abc6cd",
1053
- "src/enforce.ts": "828aa0ba0422e565fb99908d70ed1769f606dcfacee63900c9602e57471172c3",
1054
- "src/hooks.ts": "88f78d9aa7b8182a3d7080cb94dab2a17a934c7437b5dd861dd428694908e72c",
1055
- "src/index.ts": "67ea1a791b3a625882d3ff6b981092f3764b694e660194736ecf53dac0890563",
1092
+ "src/docs-capability.ts": "0feae94b7697dd53d8a457b24765e81fcf804c774f0cc4b6035cb3da822e486a",
1093
+ "src/enforce.ts": "d8a2fc2e458fde464365152df376859939bd5c5a4f7d69f88f53b1601bb1f857",
1094
+ "src/hooks.ts": "54d70d7d6923f1e39b259e3b9f377c43609aecdc64ff4d1232da595950d7b1aa",
1095
+ "src/index.ts": "2743b7969526d0aaf21179048e9896141e97d89c45c4a503b795f41fed57f6cc",
1056
1096
  "src/integrity.ts": "48d7adce486ece1885a95aac6867d286bb972d7a97bdbc32222fd6d75c2e2b49",
1057
1097
  "src/journey-docs.ts": "994d229376244c84212cff951032823068a76565dd2fd427b9d44e341bd14853",
1058
- "src/planner-kernel.ts": "b201fe5a76e5298a3a3fcd11adbf0f47bfd8a565246c84d23db5d4d7bf0a3356",
1059
- "src/planner-schema-validator.ts": "881ee4eb39db13471684854f9d1a667a5ef4451b104af2f6574ff0c237922217",
1060
- "src/planner-validators.ts": "882c12c7ce4f8bf98eda71cd33c23ac8c224c28703e10ebef63288c1017757d5",
1098
+ "src/planner-kernel.ts": "5d3f5305fb59becb2cc97d8a03aca6b104f385805d91cc0410856e289dd6fbb1",
1099
+ "src/planner-schema-validator.ts": "ce529c0936171075e93c7539b3655fe895a98dd2973ebda5775958e6ebc316d9",
1100
+ "src/planner-validators.ts": "99adeb65f579af923c11f21a8f55cfb9993b007fd8df59c5f764696b55379cfc",
1061
1101
  "src/register.ts": "6a2f1c6b8df0dc9c8f45df8ec9fac2be29044e048b08c8ffe423410e94dadedd",
1062
1102
  "src/release.ts": "7b0fe444ee81f476f53b9c21b6c347ef588ee616c60211419cf984132be768ba",
1063
1103
  "src/setup.ts": "0a6f1a9aeff31dcf17f6bd036168b909c1841c11bbbb452105d8debf64a6bc78",
1104
+ "src/topology.ts": "ff86fc7923793c727196e6f8459db4f071fcaa6844268c2e3b232bb18801c43d",
1064
1105
  "templates/agents/AGENTS.block.md": "bfd8769bc42b8c4c91a70777e056624e37acb1037c7fd1497fcb59f007567336",
1065
1106
  "templates/agents/atdd-bun.integrity.test.ts": "dec6f6e5f65a08d9512fc703b367c163f8c9da1f6aa7fd466835c1ec30348a41",
1066
1107
  "templates/agents/atdd/SKILL.md": "b621abe22851a75b30fc0e6c339a2c0a3ed6bbf78b8c17000a4ce301e05df96d",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@afokapu/atdd-bun",
3
- "version": "0.5.0",
3
+ "version": "0.6.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/afokapu/atdd-bun.git"
@@ -117,8 +117,18 @@ canonical_bun_enforcement:
117
117
  coverage: partial
118
118
  predicates:
119
119
  - duplicate feature references are reported
120
+ - a wagon with WMBTs declares a feature decomposition (atdd_topology)
121
+ - every feature a wagon lists is declared by a feature document (atdd_topology)
122
+ - every WMBT belongs to exactly one feature (atdd_topology)
120
123
  unported:
121
124
  - complete feature-manifest coverage
125
+ - rule_id: planner.feature.wagon-link
126
+ disposition: strict
127
+ origin: bun-custom-validator
128
+ coverage: partial
129
+ predicates:
130
+ - every feature is listed by exactly one wagon and belongs to it
131
+ - source and test URNs name a declared feature
122
132
  - rule_id: planner.wagon.telemetry-filesystem
123
133
  disposition: strict
124
134
  origin: bun-custom-validator
@@ -130,7 +140,7 @@ canonical_bun_enforcement:
130
140
 
131
141
  reference_only:
132
142
  selection: "every canonical planner node not named in canonical_bun_enforcement"
133
- count: 181
143
+ count: 180
134
144
 
135
145
  package_integrity_guard:
136
146
  implementation_id: planner.plan-integrity.bun
@@ -8,6 +8,20 @@
8
8
  schema_version: 1.0.0
9
9
  graph_id: "@afokapu/atdd-bun"
10
10
  nodes:
11
+ - atdd-bun.planner.acceptance-identity
12
+ - atdd-bun.planner.identity-required
13
+ - atdd-bun.planner.identity-unique
14
+ - atdd-bun.planner.interlocking-participant-resolves
15
+ - atdd-bun.planner.parse
16
+ - atdd-bun.planner.reference-resolves
17
+ - atdd-bun.planner.schema
18
+ - atdd-bun.planner.train-wagon-resolves
19
+ - atdd-bun.topology.e2e-location
20
+ - atdd-bun.topology.feature-source-coverage
21
+ - atdd-bun.topology.feature-test-coverage
22
+ - atdd-bun.topology.plan-location
23
+ - atdd-bun.topology.source-location
24
+ - atdd-bun.topology.test-location
11
25
  - coder.bun.boundaries-http-client
12
26
  - coder.bun.commons-application-no-integration
13
27
  - coder.bun.commons-cross-feature-imports-in
@@ -4788,3 +4802,213 @@ edges:
4788
4802
  target_ref: tester.htmx.a11y-harness
4789
4803
  type: runs_alongside
4790
4804
  origin: "@afokapu/atdd-bun"
4805
+ - confidence: 1
4806
+ constraint: mandatory
4807
+ control: internal
4808
+ foundation: finish_to_start
4809
+ reason: an artifact is only identified once it parses
4810
+ source_ref: atdd-bun.planner.parse
4811
+ strength: critical
4812
+ target_ref: atdd-bun.planner.identity-unique
4813
+ type: enables
4814
+ origin: "@afokapu/atdd-bun"
4815
+ - confidence: 1
4816
+ constraint: mandatory
4817
+ control: internal
4818
+ foundation: finish_to_start
4819
+ reason: a reference resolves to exactly one target only when identities are unique
4820
+ source_ref: atdd-bun.planner.identity-unique
4821
+ strength: critical
4822
+ target_ref: atdd-bun.planner.reference-resolves
4823
+ type: enables
4824
+ origin: "@afokapu/atdd-bun"
4825
+ - confidence: 1
4826
+ constraint: mandatory
4827
+ control: internal
4828
+ foundation: start_to_start
4829
+ reason: wagon membership of a train is the train-specific case of reference resolution
4830
+ source_ref: atdd-bun.planner.train-wagon-resolves
4831
+ strength: important
4832
+ target_ref: atdd-bun.planner.reference-resolves
4833
+ type: runs_alongside
4834
+ origin: "@afokapu/atdd-bun"
4835
+ - confidence: 1
4836
+ constraint: mandatory
4837
+ control: internal
4838
+ foundation: start_to_start
4839
+ reason: interlocking participants are the interlocking-specific case of reference resolution
4840
+ source_ref: atdd-bun.planner.interlocking-participant-resolves
4841
+ strength: important
4842
+ target_ref: atdd-bun.planner.reference-resolves
4843
+ type: runs_alongside
4844
+ origin: "@afokapu/atdd-bun"
4845
+ - confidence: 1
4846
+ constraint: mandatory
4847
+ control: internal
4848
+ foundation: finish_to_start
4849
+ reason: "a test can bind an acceptance only through the acc: identity the WMBT gives it"
4850
+ source_ref: atdd-bun.planner.acceptance-identity
4851
+ strength: critical
4852
+ target_ref: traceability.test.binding-resolves
4853
+ type: enables
4854
+ origin: "@afokapu/atdd-bun"
4855
+ - confidence: 1
4856
+ constraint: mandatory
4857
+ control: internal
4858
+ foundation: finish_to_start
4859
+ reason: a document is validated against its schema only after it parses
4860
+ source_ref: atdd-bun.planner.schema
4861
+ strength: critical
4862
+ target_ref: atdd-bun.planner.parse
4863
+ type: requires
4864
+ origin: "@afokapu/atdd-bun"
4865
+ - confidence: 1
4866
+ constraint: mandatory
4867
+ control: internal
4868
+ foundation: start_to_start
4869
+ reason: the schema catch-all beside the canonical rules its violations are routed to
4870
+ source_ref: atdd-bun.planner.schema
4871
+ strength: important
4872
+ target_ref: planner.train.naming
4873
+ type: runs_alongside
4874
+ origin: "@afokapu/atdd-bun"
4875
+ - confidence: 1
4876
+ constraint: mandatory
4877
+ control: internal
4878
+ foundation: finish_to_start
4879
+ reason: "features are placed by path once the wagon's feature decomposition is declared"
4880
+ source_ref: atdd-bun.topology.plan-location
4881
+ strength: critical
4882
+ target_ref: planner.wagon.features
4883
+ type: requires
4884
+ origin: "@afokapu/atdd-bun"
4885
+ - confidence: 1
4886
+ constraint: mandatory
4887
+ control: internal
4888
+ foundation: start_to_start
4889
+ reason: "where a feature lives and which wagon owns it: the same ownership, by path and by link"
4890
+ source_ref: atdd-bun.topology.plan-location
4891
+ strength: important
4892
+ target_ref: planner.feature.wagon-link
4893
+ type: runs_alongside
4894
+ origin: "@afokapu/atdd-bun"
4895
+ - confidence: 1
4896
+ constraint: mandatory
4897
+ control: internal
4898
+ foundation: finish_to_start
4899
+ reason: source is placed beneath a feature the plan declares at its canonical path
4900
+ source_ref: atdd-bun.topology.source-location
4901
+ strength: critical
4902
+ target_ref: atdd-bun.topology.plan-location
4903
+ type: requires
4904
+ origin: "@afokapu/atdd-bun"
4905
+ - confidence: 1
4906
+ constraint: mandatory
4907
+ control: internal
4908
+ foundation: start_to_start
4909
+ reason: "the same component URN, read for its grammar and for where the file must live"
4910
+ source_ref: atdd-bun.topology.source-location
4911
+ strength: important
4912
+ target_ref: coder.bun.green-urn-pattern
4913
+ type: runs_alongside
4914
+ origin: "@afokapu/atdd-bun"
4915
+ - confidence: 1
4916
+ constraint: mandatory
4917
+ control: internal
4918
+ foundation: finish_to_start
4919
+ reason: tests are placed beneath a feature the plan declares
4920
+ source_ref: atdd-bun.topology.test-location
4921
+ strength: critical
4922
+ target_ref: atdd-bun.topology.plan-location
4923
+ type: requires
4924
+ origin: "@afokapu/atdd-bun"
4925
+ - confidence: 1
4926
+ constraint: mandatory
4927
+ control: internal
4928
+ foundation: start_to_start
4929
+ reason: "the acceptance a test binds, read for presence and for whether a WMBT declares it"
4930
+ source_ref: atdd-bun.topology.test-location
4931
+ strength: important
4932
+ target_ref: tester.bun.acceptance-binding-declared
4933
+ type: runs_alongside
4934
+ origin: "@afokapu/atdd-bun"
4935
+ - confidence: 1
4936
+ constraint: mandatory
4937
+ control: internal
4938
+ foundation: finish_to_start
4939
+ reason: journey E2E paths are derived from the journeys the plan declares
4940
+ source_ref: atdd-bun.topology.e2e-location
4941
+ strength: critical
4942
+ target_ref: planner.journey.definition
4943
+ type: requires
4944
+ origin: "@afokapu/atdd-bun"
4945
+ - confidence: 1
4946
+ constraint: mandatory
4947
+ control: internal
4948
+ foundation: start_to_start
4949
+ reason: "every route has an end-to-end proof: at its canonical path, and exercising the production runner"
4950
+ source_ref: atdd-bun.topology.e2e-location
4951
+ strength: important
4952
+ target_ref: tester.bun.interlocking-route-coverage
4953
+ type: runs_alongside
4954
+ origin: "@afokapu/atdd-bun"
4955
+ - confidence: 1
4956
+ constraint: mandatory
4957
+ control: internal
4958
+ foundation: start_to_start
4959
+ reason: "on a frontend journey a browser spec is the route's end-to-end proof"
4960
+ source_ref: atdd-bun.topology.e2e-location
4961
+ strength: important
4962
+ target_ref: tester.htmx.train-e2e-coverage
4963
+ type: runs_alongside
4964
+ origin: "@afokapu/atdd-bun"
4965
+ - confidence: 1
4966
+ constraint: mandatory
4967
+ control: internal
4968
+ foundation: finish_to_start
4969
+ reason: coverage counts only source placed beneath its feature
4970
+ source_ref: atdd-bun.topology.feature-source-coverage
4971
+ strength: critical
4972
+ target_ref: atdd-bun.topology.source-location
4973
+ type: requires
4974
+ origin: "@afokapu/atdd-bun"
4975
+ - confidence: 1
4976
+ constraint: mandatory
4977
+ control: internal
4978
+ foundation: finish_to_start
4979
+ reason: coverage counts only tests placed beneath their feature and bound to its acceptances
4980
+ source_ref: atdd-bun.topology.feature-test-coverage
4981
+ strength: critical
4982
+ target_ref: atdd-bun.topology.test-location
4983
+ type: requires
4984
+ origin: "@afokapu/atdd-bun"
4985
+ - confidence: 1
4986
+ constraint: mandatory
4987
+ control: internal
4988
+ foundation: start_to_start
4989
+ reason: a feature with WMBTs is implemented and tested
4990
+ source_ref: atdd-bun.topology.feature-test-coverage
4991
+ strength: important
4992
+ target_ref: atdd-bun.topology.feature-source-coverage
4993
+ type: runs_alongside
4994
+ origin: "@afokapu/atdd-bun"
4995
+ - confidence: 1
4996
+ constraint: mandatory
4997
+ control: internal
4998
+ foundation: finish_to_start
4999
+ reason: identities can only be compared once every artifact carries one
5000
+ source_ref: atdd-bun.planner.identity-required
5001
+ strength: critical
5002
+ target_ref: atdd-bun.planner.identity-unique
5003
+ type: enables
5004
+ origin: "@afokapu/atdd-bun"
5005
+ - confidence: 1
5006
+ constraint: mandatory
5007
+ control: internal
5008
+ foundation: finish_to_start
5009
+ reason: an artifact is read for its identity only once it parses
5010
+ source_ref: atdd-bun.planner.parse
5011
+ strength: critical
5012
+ target_ref: atdd-bun.planner.identity-required
5013
+ type: enables
5014
+ origin: "@afokapu/atdd-bun"
@@ -155,6 +155,9 @@ async function checkDocumentationInner(input: { root: string; declaration: Docum
155
155
  if (input.declaration) { const declarationFindings = declarationViolations(input.declaration, input.changeSet ?? undefined); findings.push(...declarationFindings); definite ||= declarationFindings.length > 0; checked.push("<declaration>"); if (input.declaration.impact === "change") for (const artifact of input.declaration.artifacts ?? []) if (["create", "modify"].includes(artifact.action ?? "") && artifact.path && !existsSync(join(input.root, artifact.path))) { findings.push(violation("planner.docs.artifact-path-shape", artifact.path, 1, `declared artifact ${JSON.stringify(artifact.path)} (action: ${artifact.action}) is not in the tree, so it was never examined; a declared document that was never written has not discharged the obligation.`)); definite = true; } } else findings.push({ rule_id: null, where: "<declaration>", message: "core supplied no documentation declaration, so no declaration-dependent rule could be evaluated. This is COULD_NOT_CHECK and it BLOCKS." });
156
156
  if (input.declaration && input.changeSet === null) findings.push({ rule_id: null, where: "<change_set>", message: "core supplied no change set, so whether this diff touches docs/ without declaring it could not be established. This is COULD_NOT_CHECK and it BLOCKS." });
157
157
  const rendered = await (input.render ?? (() => renderDocumentation(input.root)))(); findings.push(...rendered.findings); definite ||= rendered.findings.length > 0; if (rendered.couldNotCheck) findings.push({ rule_id: "planner.docs.reference-integrity", file: "docs/", line: 1, col: 1, evidence: rendered.couldNotCheck, source_line: "" }); else checked.push("<render:asciidoctor>");
158
+ // Fail closed on any rule id this capability does not declare, however it was built (a renderer can return anything).
159
+ const undeclared = [...new Set(findings.map(f => f.rule_id).filter((id): id is string => id !== null && !(DOC_RULE_IDS as readonly string[]).includes(id)))];
160
+ if (undeclared.length) throw new Error(`documentation capability produced undeclared rule id(s): ${undeclared.join(", ")}. Declare them in DOC_RULE_IDS and the manifest, each with a convention.`);
158
161
  return { verdict: definite ? "FAIL" : input.declaration === null || input.changeSet === null || Boolean(rendered.couldNotCheck) ? "COULD_NOT_CHECK" : "PASS", findings, checked };
159
162
  }
160
163
 
package/src/enforce.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import { mkdtemp, readFile, rm } from "node:fs/promises";
2
2
  import { tmpdir } from "node:os";
3
3
  import { join, resolve } from "node:path";
4
+ import { topologyFor } from "./topology";
4
5
 
5
- export type Profile = "traceability" | "docs" | "planner" | "coder" | "tester" | "security" | "architecture" | "metrics" | "runtime" | "interlocking" | "htmx" | "design" | "all";
6
+ export type Profile = "traceability" | "topology" | "docs" | "planner" | "coder" | "tester" | "security" | "architecture" | "metrics" | "runtime" | "interlocking" | "htmx" | "design" | "all";
6
7
 
7
8
  export type Violation = {
8
9
  rule_id: string;
@@ -22,10 +23,11 @@ export type EnforcementConfig = {
22
23
 
23
24
  const profiles: Record<Exclude<Profile, "all">, string[]> = {
24
25
  traceability: ["atdd_traceability_closure"],
26
+ topology: ["atdd_topology"],
25
27
  docs: ["planner_docs_capability"],
26
- planner: ["planner_plan_integrity", "planner_schema_validation", "planner_static_validators"],
27
- coder: ["bun_green_traceability_detector", "bun_clean_architecture_detector", "bun_ts_metrics_detector", "bun_fullstack_detector", "bun_design_system_detector", "bun_responsive_detector"],
28
- tester: ["bun_tester_discipline_detector", "htmx_e2e_detector"],
28
+ planner: ["planner_plan_integrity", "planner_schema_validation", "planner_static_validators", "atdd_topology"],
29
+ coder: ["bun_green_traceability_detector", "bun_clean_architecture_detector", "bun_ts_metrics_detector", "bun_fullstack_detector", "bun_design_system_detector", "bun_responsive_detector", "atdd_topology"],
30
+ tester: ["bun_tester_discipline_detector", "htmx_e2e_detector", "atdd_topology"],
29
31
  security: ["bun_security_hygiene_detector"],
30
32
  architecture: ["bun_clean_architecture_detector"],
31
33
  metrics: ["bun_ts_metrics_detector"],
@@ -55,6 +57,26 @@ export function implementationsFor(requested: Profile[] = ["all"]): string[] {
55
57
  return [...selected].sort();
56
58
  }
57
59
 
60
+ /** The rule ids a detector's manifest declares it emits (emits_rule_ids and api_emits_rule_ids). */
61
+ export async function declaredRuleIds(implementation: string): Promise<Set<string>> {
62
+ const ids = new Set<string>();
63
+ let inList = false;
64
+ for (const line of (await readFile(join(detectorRoot, implementation, "atdd.implementation.yaml"), "utf8")).split("\n")) {
65
+ if (line === "emits_rule_ids:" || line === "api_emits_rule_ids:") { inList = true; continue; }
66
+ if (/^[A-Za-z_][\w-]*:/.test(line)) { inList = false; continue; }
67
+ const match = inList && line.match(/^\s*-\s+([^#\s]+)/);
68
+ if (match) ids.add(match[1]);
69
+ }
70
+ return ids;
71
+ }
72
+
73
+ /** Rule ids a detector actually emitted without declaring them. Checked at run time, so an id built at run
74
+ * time (a template string, a concatenation, a value read from YAML) cannot escape the per-rule checks. */
75
+ export async function undeclaredEmissions(implementation: string, violations: Pick<Violation, "rule_id">[]): Promise<string[]> {
76
+ const declared = await declaredRuleIds(implementation);
77
+ return [...new Set(violations.map(v => v.rule_id).filter(id => !declared.has(id)))].sort();
78
+ }
79
+
58
80
  export async function runImplementation(
59
81
  implementation: string,
60
82
  config: Required<Pick<EnforcementConfig, "scanRoots" | "excludes">>,
@@ -63,7 +85,7 @@ export async function runImplementation(
63
85
  const scratch = await mkdtemp(join(tmpdir(), "atdd-bun-"));
64
86
  const report = join(scratch, "violations.json");
65
87
  try {
66
- const bun = Bun.which("bun") ?? process.execPath;
88
+ const bun = Bun.which("bun") ?? process.execPath, topology = await topologyFor(config.scanRoots[0] ?? process.cwd());
67
89
  const child = Bun.spawn({
68
90
  cmd: [bun, detector],
69
91
  cwd: config.scanRoots[0] ?? process.cwd(),
@@ -73,6 +95,7 @@ export async function runImplementation(
73
95
  ...process.env,
74
96
  ATDD_SCAN_ROOTS: JSON.stringify(config.scanRoots),
75
97
  ATDD_SCAN_EXCLUDES: JSON.stringify(config.excludes),
98
+ ATDD_PLAN_ROOT: topology.planRoot,
76
99
  ATDD_VIOLATIONS_REPORT: report,
77
100
  },
78
101
  });
@@ -85,6 +108,8 @@ export async function runImplementation(
85
108
  if (!raw || !Array.isArray(raw.violations)) {
86
109
  throw new Error(`${implementation} emitted no structured violation report`);
87
110
  }
111
+ const undeclared = await undeclaredEmissions(implementation, raw.violations as Violation[]);
112
+ if (undeclared.length) throw new Error(`${implementation} emitted rule id(s) its manifest does not declare: ${undeclared.join(", ")}. Declare them in emits_rule_ids, each with a convention.`);
88
113
  return raw.violations as Violation[];
89
114
  } finally {
90
115
  await rm(scratch, { recursive: true, force: true });