@afokapu/atdd-bun 0.3.1 → 0.4.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.
Files changed (41) hide show
  1. package/PLANNER_PORT.md +1 -1
  2. package/README.md +56 -1
  3. package/conventions/planner.docs/planner.docs.journey-view-current.convention.yaml +53 -0
  4. package/detectors/planner_docs_capability/atdd.implementation.yaml +2 -0
  5. package/detectors/planner_docs_capability/fixtures/clean/docs/purpose/journeys/index.adoc +170 -0
  6. package/detectors/planner_docs_capability/fixtures/clean/docs/purpose/journeys/svg/journey-buy.svg +61 -0
  7. package/detectors/planner_docs_capability/fixtures/clean/docs/purpose/journeys/svg/path-buy-nominal.svg +81 -0
  8. package/detectors/planner_docs_capability/fixtures/clean/docs/purpose/journeys/svg/train-orders-archive-order.svg +13 -0
  9. package/detectors/planner_docs_capability/fixtures/clean/docs/purpose/journeys/svg/train-orders-place-order.svg +31 -0
  10. package/detectors/planner_docs_capability/fixtures/clean/docs/purpose/journeys/svg/train-orders-reject-empty-cart.svg +22 -0
  11. package/detectors/planner_docs_capability/fixtures/clean/docs/purpose/journeys/svg/train-orders-retry-payment.svg +22 -0
  12. package/detectors/planner_docs_capability/fixtures/clean/docs/purpose/journeys/svg/train-orders-ship-order.svg +35 -0
  13. package/detectors/planner_docs_capability/fixtures/clean/docs/purpose/journeys/svg/train-orders-take-payment.svg +27 -0
  14. package/detectors/planner_docs_capability/fixtures/clean/plan/_journeys/buy.yaml +24 -0
  15. package/detectors/planner_docs_capability/fixtures/clean/plan/_themes.yaml +3 -0
  16. package/detectors/planner_docs_capability/fixtures/clean/plan/_trains/_interlockings/checkout.yaml +43 -0
  17. package/detectors/planner_docs_capability/fixtures/clean/plan/_trains/_interlockings/fulfilment.yaml +33 -0
  18. package/detectors/planner_docs_capability/fixtures/clean/plan/_trains/_interlockings/payment.yaml +43 -0
  19. package/detectors/planner_docs_capability/fixtures/clean/plan/_trains/_interlockings/returns.yaml +33 -0
  20. package/detectors/planner_docs_capability/fixtures/clean/plan/_trains/orders/archive-order.yaml +11 -0
  21. package/detectors/planner_docs_capability/fixtures/clean/plan/_trains/orders/place-order.yaml +21 -0
  22. package/detectors/planner_docs_capability/fixtures/clean/plan/_trains/orders/reject-empty-cart.yaml +16 -0
  23. package/detectors/planner_docs_capability/fixtures/clean/plan/_trains/orders/retry-payment.yaml +16 -0
  24. package/detectors/planner_docs_capability/fixtures/clean/plan/_trains/orders/ship-order.yaml +21 -0
  25. package/detectors/planner_docs_capability/fixtures/clean/plan/_trains/orders/take-payment.yaml +21 -0
  26. package/detectors/planner_docs_capability/fixtures/clean/plan/_trains/orders/unrouted-refund.yaml +11 -0
  27. package/detectors/planner_docs_capability/fixtures/dirty_journey_view/docs/index.adoc +3 -0
  28. package/detectors/planner_docs_capability/fixtures/dirty_journey_view/plan/_trains/_interlockings/fulfilment.yaml +33 -0
  29. package/detectors/planner_static_validators/atdd.implementation.yaml +2 -0
  30. package/detectors/planner_static_validators/fixtures/dirty/plan/_trains/_interlockings/uncomposed.yaml +4 -0
  31. package/integrity.json +40 -11
  32. package/package.json +3 -2
  33. package/planner-nodes/ENFORCEMENT_SCOPE.yaml +7 -1
  34. package/planner-nodes/nodes/planner.journey.interlocking-composed.convention.yaml +43 -0
  35. package/relationships.yaml +4514 -0
  36. package/src/cli.ts +9 -0
  37. package/src/docs-capability.ts +10 -1
  38. package/src/hooks.ts +1 -1
  39. package/src/index.ts +2 -0
  40. package/src/journey-docs.ts +355 -0
  41. package/src/planner-validators.ts +29 -0
@@ -0,0 +1,35 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" class="atdd-diagram" width="586" height="229" viewBox="0 0 586 229" role="img" aria-labelledby="t-seq-orders-ship-order d-seq-orders-ship-order">
2
+ <title id="t-seq-orders-ship-order">Ship the order</title><desc id="d-seq-orders-ship-order">1. checkout to fulfilment, orders:paid: Hand the paid order to fulfilment 2. fulfilment to carrier, orders:shipment: Book the shipment with the carrier 3. fulfilment to buyer, orders:tracking: Send tracking to the buyer</desc>
3
+ <defs><marker id="seq-orders-ship-order-wagon" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M0,0 L10,5 L0,10 z" style="fill: var(--atdd-ink-3, #64748b)"/></marker><marker id="seq-orders-ship-order-person" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M0,0 L10,5 L0,10 z" style="fill: var(--atdd-person, #b45309)"/></marker><marker id="seq-orders-ship-order-system" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M0,0 L10,5 L0,10 z" style="fill: var(--atdd-system, #7c3aed)"/></marker></defs>
4
+ <line x1="100" y1="54" x2="100" y2="223" style="stroke: var(--atdd-line, #cbd5e1); stroke-width: 1.4; stroke-dasharray: 3 4"/>
5
+ <rect x="41" y="10" width="118" height="44" rx="8" style="fill: var(--atdd-paper, #ffffff); stroke: var(--atdd-wagon, #2563eb); stroke-width: 1.8"/>
6
+ <text x="100" y="32" text-anchor="middle" style="font-family: var(--atdd-sans, system-ui, sans-serif); font-size: 10.5px; font-weight: 600; fill: var(--atdd-ink, #1f2937)">checkout</text>
7
+ <text x="100" y="47" text-anchor="middle" style="font-family: var(--atdd-mono, ui-monospace, monospace); font-size: 8px; letter-spacing: .1em; fill: var(--atdd-ink-3, #64748b)">WAGON</text>
8
+ <line x1="232" y1="54" x2="232" y2="223" style="stroke: var(--atdd-line, #cbd5e1); stroke-width: 1.4; stroke-dasharray: 3 4"/>
9
+ <rect x="173" y="10" width="118" height="44" rx="8" style="fill: var(--atdd-paper, #ffffff); stroke: var(--atdd-wagon, #2563eb); stroke-width: 1.8"/>
10
+ <text x="232" y="32" text-anchor="middle" style="font-family: var(--atdd-sans, system-ui, sans-serif); font-size: 10.5px; font-weight: 600; fill: var(--atdd-ink, #1f2937)">fulfilment</text>
11
+ <text x="232" y="47" text-anchor="middle" style="font-family: var(--atdd-mono, ui-monospace, monospace); font-size: 8px; letter-spacing: .1em; fill: var(--atdd-ink-3, #64748b)">WAGON</text>
12
+ <line x1="364" y1="54" x2="364" y2="223" style="stroke: var(--atdd-line, #cbd5e1); stroke-width: 1.4; stroke-dasharray: 3 4"/>
13
+ <rect x="305" y="10" width="118" height="44" rx="8" style="fill: var(--atdd-paper, #ffffff); stroke: var(--atdd-system, #7c3aed); stroke-width: 1.8"/>
14
+ <text x="364" y="32" text-anchor="middle" style="font-family: var(--atdd-sans, system-ui, sans-serif); font-size: 10.5px; font-weight: 600; fill: var(--atdd-ink, #1f2937)">carrier</text>
15
+ <text x="364" y="47" text-anchor="middle" style="font-family: var(--atdd-mono, ui-monospace, monospace); font-size: 8px; letter-spacing: .1em; fill: var(--atdd-ink-3, #64748b)">SYSTEM</text>
16
+ <line x1="496" y1="54" x2="496" y2="223" style="stroke: var(--atdd-line, #cbd5e1); stroke-width: 1.4; stroke-dasharray: 3 4"/>
17
+ <rect x="437" y="10" width="118" height="44" rx="8" style="fill: var(--atdd-paper, #ffffff); stroke: var(--atdd-person, #b45309); stroke-width: 1.8"/>
18
+ <text x="496" y="32" text-anchor="middle" style="font-family: var(--atdd-sans, system-ui, sans-serif); font-size: 10.5px; font-weight: 600; fill: var(--atdd-ink, #1f2937)">buyer</text>
19
+ <text x="496" y="47" text-anchor="middle" style="font-family: var(--atdd-mono, ui-monospace, monospace); font-size: 8px; letter-spacing: .1em; fill: var(--atdd-ink-3, #64748b)">PERSON</text>
20
+ <text x="20" y="111" text-anchor="middle" style="font-family: var(--atdd-mono, ui-monospace, monospace); font-size: 9.5px; fill: var(--atdd-ink-3, #64748b)">1</text>
21
+ <text x="96" y="84" text-anchor="start" style="font-family: var(--atdd-sans, system-ui, sans-serif); font-size: 11px; fill: var(--atdd-ink-2, #475569)">Hand the paid order to fulfilment</text>
22
+ <text x="96" y="97" text-anchor="start" style="font-family: var(--atdd-mono, ui-monospace, monospace); font-size: 9px; fill: var(--atdd-accent, #0f766e)">orders:paid</text>
23
+ <circle cx="100" cy="107" r="3" style="fill: var(--atdd-ink-3, #64748b)"/>
24
+ <line x1="103" y1="107" x2="227" y2="107" style="stroke: var(--atdd-ink-3, #64748b); stroke-width: 1.7" marker-end="url(#seq-orders-ship-order-wagon)"/>
25
+ <text x="20" y="160" text-anchor="middle" style="font-family: var(--atdd-mono, ui-monospace, monospace); font-size: 9.5px; fill: var(--atdd-ink-3, #64748b)">2</text>
26
+ <text x="228" y="133" text-anchor="start" style="font-family: var(--atdd-sans, system-ui, sans-serif); font-size: 11px; fill: var(--atdd-ink-2, #475569)">Book the shipment with the carrier</text>
27
+ <text x="228" y="146" text-anchor="start" style="font-family: var(--atdd-mono, ui-monospace, monospace); font-size: 9px; fill: var(--atdd-accent, #0f766e)">orders:shipment</text>
28
+ <circle cx="232" cy="156" r="3" style="fill: var(--atdd-system, #7c3aed)"/>
29
+ <line x1="235" y1="156" x2="359" y2="156" style="stroke: var(--atdd-system, #7c3aed); stroke-width: 1.7" marker-end="url(#seq-orders-ship-order-system)"/>
30
+ <text x="20" y="209" text-anchor="middle" style="font-family: var(--atdd-mono, ui-monospace, monospace); font-size: 9.5px; fill: var(--atdd-ink-3, #64748b)">3</text>
31
+ <text x="228" y="182" text-anchor="start" style="font-family: var(--atdd-sans, system-ui, sans-serif); font-size: 11px; fill: var(--atdd-ink-2, #475569)">Send tracking to the buyer</text>
32
+ <text x="228" y="195" text-anchor="start" style="font-family: var(--atdd-mono, ui-monospace, monospace); font-size: 9px; fill: var(--atdd-accent, #0f766e)">orders:tracking</text>
33
+ <circle cx="232" cy="205" r="3" style="fill: var(--atdd-person, #b45309)"/>
34
+ <line x1="235" y1="205" x2="491" y2="205" style="stroke: var(--atdd-person, #b45309); stroke-width: 1.7" marker-end="url(#seq-orders-ship-order-person)"/>
35
+ </svg>
@@ -0,0 +1,27 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" class="atdd-diagram" width="360" height="247" viewBox="0 0 360 247" role="img" aria-labelledby="t-seq-orders-take-payment d-seq-orders-take-payment">
2
+ <title id="t-seq-orders-take-payment">Take payment</title><desc id="d-seq-orders-take-payment">1. checkout to payment-gateway, orders:charge: Request the charge from the payment gateway 2. payment-gateway to checkout, orders:charge-result: Report whether the charge succeeded 3. checkout to checkout, orders:paid: Record the order as paid</desc>
3
+ <defs><marker id="seq-orders-take-payment-wagon" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M0,0 L10,5 L0,10 z" style="fill: var(--atdd-ink-3, #64748b)"/></marker><marker id="seq-orders-take-payment-person" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M0,0 L10,5 L0,10 z" style="fill: var(--atdd-person, #b45309)"/></marker><marker id="seq-orders-take-payment-system" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M0,0 L10,5 L0,10 z" style="fill: var(--atdd-system, #7c3aed)"/></marker></defs>
4
+ <line x1="100" y1="54" x2="100" y2="241" style="stroke: var(--atdd-line, #cbd5e1); stroke-width: 1.4; stroke-dasharray: 3 4"/>
5
+ <rect x="41" y="10" width="118" height="44" rx="8" style="fill: var(--atdd-paper, #ffffff); stroke: var(--atdd-wagon, #2563eb); stroke-width: 1.8"/>
6
+ <text x="100" y="32" text-anchor="middle" style="font-family: var(--atdd-sans, system-ui, sans-serif); font-size: 10.5px; font-weight: 600; fill: var(--atdd-ink, #1f2937)">checkout</text>
7
+ <text x="100" y="47" text-anchor="middle" style="font-family: var(--atdd-mono, ui-monospace, monospace); font-size: 8px; letter-spacing: .1em; fill: var(--atdd-ink-3, #64748b)">WAGON</text>
8
+ <line x1="232" y1="54" x2="232" y2="241" style="stroke: var(--atdd-line, #cbd5e1); stroke-width: 1.4; stroke-dasharray: 3 4"/>
9
+ <rect x="173" y="10" width="118" height="44" rx="8" style="fill: var(--atdd-paper, #ffffff); stroke: var(--atdd-system, #7c3aed); stroke-width: 1.8"/>
10
+ <text x="232" y="32" text-anchor="middle" style="font-family: var(--atdd-sans, system-ui, sans-serif); font-size: 10.5px; font-weight: 600; fill: var(--atdd-ink, #1f2937)">payment-gateway</text>
11
+ <text x="232" y="47" text-anchor="middle" style="font-family: var(--atdd-mono, ui-monospace, monospace); font-size: 8px; letter-spacing: .1em; fill: var(--atdd-ink-3, #64748b)">SYSTEM</text>
12
+ <text x="20" y="111" text-anchor="middle" style="font-family: var(--atdd-mono, ui-monospace, monospace); font-size: 9.5px; fill: var(--atdd-ink-3, #64748b)">1</text>
13
+ <text x="96" y="84" text-anchor="start" style="font-family: var(--atdd-sans, system-ui, sans-serif); font-size: 11px; fill: var(--atdd-ink-2, #475569)">Request the charge from the payment gateway</text>
14
+ <text x="96" y="97" text-anchor="start" style="font-family: var(--atdd-mono, ui-monospace, monospace); font-size: 9px; fill: var(--atdd-accent, #0f766e)">orders:charge</text>
15
+ <circle cx="100" cy="107" r="3" style="fill: var(--atdd-system, #7c3aed)"/>
16
+ <line x1="103" y1="107" x2="227" y2="107" style="stroke: var(--atdd-system, #7c3aed); stroke-width: 1.7" marker-end="url(#seq-orders-take-payment-system)"/>
17
+ <text x="20" y="160" text-anchor="middle" style="font-family: var(--atdd-mono, ui-monospace, monospace); font-size: 9.5px; fill: var(--atdd-ink-3, #64748b)">2</text>
18
+ <text x="96" y="133" text-anchor="start" style="font-family: var(--atdd-sans, system-ui, sans-serif); font-size: 11px; fill: var(--atdd-ink-2, #475569)">Report whether the charge succeeded</text>
19
+ <text x="96" y="146" text-anchor="start" style="font-family: var(--atdd-mono, ui-monospace, monospace); font-size: 9px; fill: var(--atdd-accent, #0f766e)">orders:charge-result</text>
20
+ <circle cx="232" cy="156" r="3" style="fill: var(--atdd-system, #7c3aed)"/>
21
+ <line x1="229" y1="156" x2="105" y2="156" style="stroke: var(--atdd-system, #7c3aed); stroke-width: 1.7" marker-end="url(#seq-orders-take-payment-system)"/>
22
+ <text x="20" y="209" text-anchor="middle" style="font-family: var(--atdd-mono, ui-monospace, monospace); font-size: 9.5px; fill: var(--atdd-ink-3, #64748b)">3</text>
23
+ <text x="96" y="182" text-anchor="start" style="font-family: var(--atdd-sans, system-ui, sans-serif); font-size: 11px; fill: var(--atdd-ink-2, #475569)">Record the order as paid</text>
24
+ <text x="96" y="195" text-anchor="start" style="font-family: var(--atdd-mono, ui-monospace, monospace); font-size: 9px; fill: var(--atdd-accent, #0f766e)">orders:paid</text>
25
+ <circle cx="100" cy="205" r="3" style="fill: var(--atdd-ink-3, #64748b)"/>
26
+ <path d="M 100 205 h 32 v 18 h -26" style="fill: none; stroke: var(--atdd-ink-3, #64748b); stroke-width: 1.7" marker-end="url(#seq-orders-take-payment-wagon)"/>
27
+ </svg>
@@ -0,0 +1,24 @@
1
+ schema_version: 1.0.0
2
+ journey_id: journey:buy
3
+ title: Buy a product
4
+ status: checked
5
+ entrypoint:
6
+ interlocking_id: interlocking:checkout
7
+ exposed: true
8
+ actions: [place-order]
9
+ reason: null
10
+ surfaces: [frontend]
11
+ continuations:
12
+ - from: { interlocking_id: interlocking:checkout, route_id: nominal }
13
+ artifact: orders:quote
14
+ to: { interlocking_id: interlocking:payment }
15
+ - from: { interlocking_id: interlocking:payment, route_id: charged }
16
+ artifact: orders:paid
17
+ to: { interlocking_id: interlocking:fulfilment }
18
+ terminals:
19
+ - from: { interlocking_id: interlocking:checkout, route_id: empty-cart }
20
+ outcome: rejected
21
+ - from: { interlocking_id: interlocking:payment, route_id: declined }
22
+ outcome: declined
23
+ - from: { interlocking_id: interlocking:fulfilment, route_id: ship }
24
+ outcome: shipped
@@ -0,0 +1,3 @@
1
+ themes:
2
+ "0": commons
3
+ "1": orders
@@ -0,0 +1,43 @@
1
+ schema_version: 1.0.0
2
+ interlocking_id: interlocking:checkout
3
+ title: Checkout decision
4
+ theme: orders
5
+ status: checked
6
+ source:
7
+ path: plan/_trains/_interlockings/checkout.yaml
8
+ content_digest: fixture
9
+ entrypoint:
10
+ exposed: true
11
+ actions: [place-order]
12
+ reason: null
13
+ surfaces: [frontend]
14
+ route_resolution:
15
+ strategy: fail_on_multiple_match
16
+ lifelines:
17
+ - ref: wagon:checkout
18
+ messages: []
19
+ fragments:
20
+ - id: fragment:checkout
21
+ kind: alt
22
+ guards:
23
+ - id: guard:nominal
24
+ expression: cart.items > 0
25
+ - id: guard:empty-cart
26
+ expression: cart.items == 0
27
+ routes:
28
+ - route_id: nominal
29
+ category: nominal
30
+ priority: 1
31
+ guard_ref: guard:nominal
32
+ train_id: train:orders:place-order
33
+ train_path: plan/_trains/orders/place-order.yaml
34
+ projection:
35
+ expected_sequence_digest: fixture
36
+ - route_id: empty-cart
37
+ category: error
38
+ priority: 2
39
+ guard_ref: guard:empty-cart
40
+ train_id: train:orders:reject-empty-cart
41
+ train_path: plan/_trains/orders/reject-empty-cart.yaml
42
+ projection:
43
+ expected_sequence_digest: fixture
@@ -0,0 +1,33 @@
1
+ schema_version: 1.0.0
2
+ interlocking_id: interlocking:fulfilment
3
+ title: Fulfilment decision
4
+ theme: orders
5
+ status: checked
6
+ source:
7
+ path: plan/_trains/_interlockings/fulfilment.yaml
8
+ content_digest: fixture
9
+ entrypoint:
10
+ exposed: false
11
+ actions: []
12
+ reason: internal-transition-only
13
+ surfaces: [backend]
14
+ route_resolution:
15
+ strategy: fail_on_multiple_match
16
+ lifelines:
17
+ - ref: wagon:checkout
18
+ messages: []
19
+ fragments:
20
+ - id: fragment:fulfilment
21
+ kind: alt
22
+ guards:
23
+ - id: guard:ship
24
+ expression: order.paid
25
+ routes:
26
+ - route_id: ship
27
+ category: nominal
28
+ priority: 1
29
+ guard_ref: guard:ship
30
+ train_id: train:orders:ship-order
31
+ train_path: plan/_trains/orders/ship-order.yaml
32
+ projection:
33
+ expected_sequence_digest: fixture
@@ -0,0 +1,43 @@
1
+ schema_version: 1.0.0
2
+ interlocking_id: interlocking:payment
3
+ title: Payment decision
4
+ theme: orders
5
+ status: checked
6
+ source:
7
+ path: plan/_trains/_interlockings/payment.yaml
8
+ content_digest: fixture
9
+ entrypoint:
10
+ exposed: false
11
+ actions: []
12
+ reason: internal-transition-only
13
+ surfaces: [backend]
14
+ route_resolution:
15
+ strategy: fail_on_multiple_match
16
+ lifelines:
17
+ - ref: wagon:checkout
18
+ messages: []
19
+ fragments:
20
+ - id: fragment:payment
21
+ kind: alt
22
+ guards:
23
+ - id: guard:charged
24
+ expression: quote.accepted and card.valid
25
+ - id: guard:declined
26
+ expression: card.declined
27
+ routes:
28
+ - route_id: charged
29
+ category: nominal
30
+ priority: 1
31
+ guard_ref: guard:charged
32
+ train_id: train:orders:take-payment
33
+ train_path: plan/_trains/orders/take-payment.yaml
34
+ projection:
35
+ expected_sequence_digest: fixture
36
+ - route_id: declined
37
+ category: alternate
38
+ priority: 2
39
+ guard_ref: guard:declined
40
+ train_id: train:orders:retry-payment
41
+ train_path: plan/_trains/orders/retry-payment.yaml
42
+ projection:
43
+ expected_sequence_digest: fixture
@@ -0,0 +1,33 @@
1
+ schema_version: 1.0.0
2
+ interlocking_id: interlocking:returns
3
+ title: Returns decision
4
+ theme: orders
5
+ status: checked
6
+ source:
7
+ path: plan/_trains/_interlockings/returns.yaml
8
+ content_digest: fixture
9
+ entrypoint:
10
+ exposed: false
11
+ actions: []
12
+ reason: internal-transition-only
13
+ surfaces: [backend]
14
+ route_resolution:
15
+ strategy: fail_on_multiple_match
16
+ lifelines:
17
+ - ref: wagon:checkout
18
+ messages: []
19
+ fragments:
20
+ - id: fragment:returns
21
+ kind: alt
22
+ guards:
23
+ - id: guard:archive
24
+ expression: order.cancelled
25
+ routes:
26
+ - route_id: archive
27
+ category: nominal
28
+ priority: 1
29
+ guard_ref: guard:archive
30
+ train_id: train:orders:archive-order
31
+ train_path: plan/_trains/orders/archive-order.yaml
32
+ projection:
33
+ expected_sequence_digest: fixture
@@ -0,0 +1,11 @@
1
+ train_id: train:orders:archive-order
2
+ title: Archive a cancelled order
3
+ description: Archive a cancelled order.
4
+ themes: [orders]
5
+ participants: [wagon:checkout]
6
+ sequence:
7
+ - step: 1
8
+ intent: Archive the cancelled order
9
+ from: wagon:checkout
10
+ to: wagon:checkout
11
+ artifact: orders:archived
@@ -0,0 +1,21 @@
1
+ train_id: train:orders:place-order
2
+ title: Place an order
3
+ description: Place an order.
4
+ themes: [orders]
5
+ participants: [user:buyer, wagon:checkout, wagon:pricing]
6
+ sequence:
7
+ - step: 1
8
+ intent: Submit the cart for checkout
9
+ from: user:buyer
10
+ to: wagon:checkout
11
+ artifact: orders:cart
12
+ - step: 2
13
+ intent: Price the cart with current promotions
14
+ from: wagon:checkout
15
+ to: wagon:pricing
16
+ artifact: orders:priced-cart
17
+ - step: 3
18
+ intent: Return the priced quote
19
+ from: wagon:pricing
20
+ to: wagon:checkout
21
+ artifact: orders:quote
@@ -0,0 +1,16 @@
1
+ train_id: train:orders:reject-empty-cart
2
+ title: Reject an empty cart
3
+ description: Reject an empty cart.
4
+ themes: [orders]
5
+ participants: [user:buyer, wagon:checkout]
6
+ sequence:
7
+ - step: 1
8
+ intent: Submit an empty cart
9
+ from: user:buyer
10
+ to: wagon:checkout
11
+ artifact: orders:cart
12
+ - step: 2
13
+ intent: Refuse the empty cart and say why
14
+ from: wagon:checkout
15
+ to: user:buyer
16
+ artifact: orders:rejection
@@ -0,0 +1,16 @@
1
+ train_id: train:orders:retry-payment
2
+ title: Retry a declined payment
3
+ description: Retry a declined payment.
4
+ themes: [orders]
5
+ participants: [user:buyer, wagon:checkout]
6
+ sequence:
7
+ - step: 1
8
+ intent: Ask the buyer for another payment method
9
+ from: wagon:checkout
10
+ to: user:buyer
11
+ artifact: orders:decline
12
+ - step: 2
13
+ intent: Provide a new payment method
14
+ from: user:buyer
15
+ to: wagon:checkout
16
+ artifact: orders:payment-method
@@ -0,0 +1,21 @@
1
+ train_id: train:orders:ship-order
2
+ title: Ship the order
3
+ description: Ship the order.
4
+ themes: [orders]
5
+ participants: [system:carrier, user:buyer, wagon:checkout, wagon:fulfilment]
6
+ sequence:
7
+ - step: 1
8
+ intent: Hand the paid order to fulfilment
9
+ from: wagon:checkout
10
+ to: wagon:fulfilment
11
+ artifact: orders:paid
12
+ - step: 2
13
+ intent: Book the shipment with the carrier
14
+ from: wagon:fulfilment
15
+ to: system:carrier
16
+ artifact: orders:shipment
17
+ - step: 3
18
+ intent: Send tracking to the buyer
19
+ from: wagon:fulfilment
20
+ to: user:buyer
21
+ artifact: orders:tracking
@@ -0,0 +1,21 @@
1
+ train_id: train:orders:take-payment
2
+ title: Take payment
3
+ description: Take payment.
4
+ themes: [orders]
5
+ participants: [system:payment-gateway, wagon:checkout]
6
+ sequence:
7
+ - step: 1
8
+ intent: Request the charge from the payment gateway
9
+ from: wagon:checkout
10
+ to: system:payment-gateway
11
+ artifact: orders:charge
12
+ - step: 2
13
+ intent: Report whether the charge succeeded
14
+ from: system:payment-gateway
15
+ to: wagon:checkout
16
+ artifact: orders:charge-result
17
+ - step: 3
18
+ intent: Record the order as paid
19
+ from: wagon:checkout
20
+ to: wagon:checkout
21
+ artifact: orders:paid
@@ -0,0 +1,11 @@
1
+ train_id: train:orders:unrouted-refund
2
+ title: Refund an order
3
+ description: Refund an order.
4
+ themes: [orders]
5
+ participants: [user:buyer, wagon:checkout]
6
+ sequence:
7
+ - step: 1
8
+ intent: Ask for a refund
9
+ from: user:buyer
10
+ to: wagon:checkout
11
+ artifact: orders:refund-request
@@ -0,0 +1,3 @@
1
+ = Docs
2
+ :doc-id: root
3
+ :status: current
@@ -0,0 +1,33 @@
1
+ schema_version: 1.0.0
2
+ interlocking_id: interlocking:fulfilment
3
+ title: Fulfilment decision
4
+ theme: orders
5
+ status: checked
6
+ source:
7
+ path: plan/_trains/_interlockings/fulfilment.yaml
8
+ content_digest: fixture
9
+ entrypoint:
10
+ exposed: false
11
+ actions: []
12
+ reason: internal-transition-only
13
+ surfaces: [backend]
14
+ route_resolution:
15
+ strategy: fail_on_multiple_match
16
+ lifelines:
17
+ - ref: wagon:checkout
18
+ messages: []
19
+ fragments:
20
+ - id: fragment:fulfilment
21
+ kind: alt
22
+ guards:
23
+ - id: guard:ship
24
+ expression: order.paid
25
+ routes:
26
+ - route_id: ship
27
+ category: nominal
28
+ priority: 1
29
+ guard_ref: guard:ship
30
+ train_id: train:orders:ship-order
31
+ train_path: plan/_trains/orders/ship-order.yaml
32
+ projection:
33
+ expected_sequence_digest: fixture
@@ -18,6 +18,7 @@ emits_rule_ids:
18
18
  - planner.wagon.telemetry-filesystem
19
19
  - planner.train.registry-coherence
20
20
  - planner.journey.continuation-closure
21
+ - planner.journey.interlocking-composed
21
22
  realizes_convention:
22
23
  - planner.wagon.urn
23
24
  - planner.wagon.urn-naming
@@ -32,5 +33,6 @@ realizes_convention:
32
33
  - planner.wagon.telemetry-filesystem
33
34
  - planner.train.registry-coherence
34
35
  - planner.journey.continuation-closure
36
+ - planner.journey.interlocking-composed
35
37
  entrypoint: detect.mjs
36
38
  report: detect.mjs
@@ -0,0 +1,4 @@
1
+ interlocking_id: interlocking:uncomposed
2
+ routes:
3
+ - route_id: nominal
4
+ train_id: train:journey:a
package/integrity.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
- "version": "0.3.1",
2
+ "version": "0.4.0",
3
3
  "files": {
4
4
  "HOOK_AUDIT.md": "5329d840db37671b1918f688ead26865473b87db73dbc75f7c8b2a8bbe8d6d43",
5
- "PLANNER_PORT.md": "54ba452eb39cb5afb7c225363fddfd1bf9272ca1c12e7cbf6815a1dd464ff2b3",
6
- "README.md": "506272551a4ad748537a2ade2a66219429eebba6e38fcd74c88e602bd94e0dbd",
5
+ "PLANNER_PORT.md": "fb5935bac8b7ac18994de21e43ace3a5ef8cd55f85b0e3349fca261280054f11",
6
+ "README.md": "2586b8a08916cc343f565f9986cffaff7f4a255460ad2f5a1f60538eaced707b",
7
7
  "bunfig.toml": "b9fc65eca9014c5179380259d70e76385a6a80788fa9a2df5fb3eaa5554fd2fe",
8
8
  "conventions/coder.bun/coder.bun.boundaries-http-client.convention.yaml": "b846bb6ced2c4c967466520d52b00ff1ca802dafcdbb2ec2adbd0ce19e752a28",
9
9
  "conventions/coder.bun/coder.bun.commons-application-no-integration.convention.yaml": "f63e7f6442bcdf5cf79f58a091547a1a990d0ee7c006b797fd5187d6f8bf8712",
@@ -76,6 +76,7 @@
76
76
  "conventions/planner.docs/planner.docs.doc-id-unique.convention.yaml": "eedfd745ff591591b2d50eabc65452f2a66759980c70a20690e208bd91f87c22",
77
77
  "conventions/planner.docs/planner.docs.graph-target-resolves.convention.yaml": "c7922b5c23a2e794a53a3ebebc5eeea9b54d8a0fe4bd2c418ac5a1758defaedc",
78
78
  "conventions/planner.docs/planner.docs.identity-required.convention.yaml": "d3826a9bc43187749627a97d679356e96b444163de6a3c6a3452b220f267d86e",
79
+ "conventions/planner.docs/planner.docs.journey-view-current.convention.yaml": "5892d4213d72342dc568c37f13942139bbdce4c0d5716075de579dc8060fc969",
79
80
  "conventions/planner.docs/planner.docs.reference-integrity.convention.yaml": "e3eb6e76807165a539d3fe1caa9c6f1cd0867a1cd13f44d986eb9f96cd26eff7",
80
81
  "conventions/planner.docs/planner.docs.undeclared-change.convention.yaml": "b3bfb9a738303567d295d5623d55289586bcca1926f923dcc0238cdb5cce1dae",
81
82
  "conventions/tester.bun/tester.bun.acceptance-binding-declared.convention.yaml": "aeaf824793b3a66db4d7fa7736f0bfb0d0f3dcb4ebce33d07a254d06d989ff1e",
@@ -555,7 +556,7 @@
555
556
  "detectors/htmx_tester_detector/fixtures/dirty/statusonly.test.ts": "a2daf2874bf68c6221374ac05619642a42d56b5d1f76e30fa3d2a1826adaf51b",
556
557
  "detectors/htmx_tester_detector/test_header.mjs": "a22221fe9ef6d10297ec777c5d0c6e7b84010ccf41e90db30c036206790ea198",
557
558
  "detectors/planner_docs_capability/README.md": "1e1f8ee258242c05293447fcde124543447ba375306e8a7e5f665881b038bcd1",
558
- "detectors/planner_docs_capability/atdd.implementation.yaml": "d080cd4c80cf327c530d5ba724023c22c76f874831ab0b94af6589f5a3984588",
559
+ "detectors/planner_docs_capability/atdd.implementation.yaml": "7e88a43ee43f5131d25debcc8f02f7381c3b356b6d8ea14357a89ead8e83342e",
559
560
  "detectors/planner_docs_capability/detect.mjs": "d10773fa5b2d8f65ce351804694171a6eb75e05eb4c80fa1edce4a5d56b72c5d",
560
561
  "detectors/planner_docs_capability/fixtures/clean/docs/architecture/decisions/adr-20260906-001-shared-control-root.adoc": "6d30e5545e7b051c80605c3dbee50286f71e344ab2e71a987db945941de42523",
561
562
  "detectors/planner_docs_capability/fixtures/clean/docs/architecture/decisions/index.adoc": "4a6cb87e249d587c85bb6389ff5fecae7a96194af8677b588eed0c791099123b",
@@ -568,7 +569,29 @@
568
569
  "detectors/planner_docs_capability/fixtures/clean/docs/dist/index.md": "eac4d8fe653f45c959731cc08218d898e5123d685a1017191c4cffb626777f13",
569
570
  "detectors/planner_docs_capability/fixtures/clean/docs/index.adoc": "8aabcd7a4ecfc6ef565a604c1172364f761bef7d3fc4f2c96c07dce4e0ebe19b",
570
571
  "detectors/planner_docs_capability/fixtures/clean/docs/purpose/index.adoc": "e10193ea48f3c77b67ca8ed7221c53f23ce699e63f651cc340cea9ef6b44cffb",
572
+ "detectors/planner_docs_capability/fixtures/clean/docs/purpose/journeys/index.adoc": "9fcb12b48c936fe3f09fbacd7580d436c4919624aa0765cf7edfdc0ce1c77a9c",
573
+ "detectors/planner_docs_capability/fixtures/clean/docs/purpose/journeys/svg/journey-buy.svg": "ee965093b5691093548b0b5f33a329fc294140a14a032561fb010b27e2f849d6",
574
+ "detectors/planner_docs_capability/fixtures/clean/docs/purpose/journeys/svg/path-buy-nominal.svg": "f745c3d2713399f34326a6f75bce548d77d28c8453953611cd10db0c23e0b6a9",
575
+ "detectors/planner_docs_capability/fixtures/clean/docs/purpose/journeys/svg/train-orders-archive-order.svg": "149034cbed4598361aaf1a19dbc7964b728faf7fa1adc8419bbcf6aa7ff188d4",
576
+ "detectors/planner_docs_capability/fixtures/clean/docs/purpose/journeys/svg/train-orders-place-order.svg": "6bc482fa2c0d811b707ff5d166f0bb308eeac2a8b022d89e203d19b286843d59",
577
+ "detectors/planner_docs_capability/fixtures/clean/docs/purpose/journeys/svg/train-orders-reject-empty-cart.svg": "3129aaf3ea62f3643d095a3d4f653c849e8ee4473e655edd6d949e47df9c300b",
578
+ "detectors/planner_docs_capability/fixtures/clean/docs/purpose/journeys/svg/train-orders-retry-payment.svg": "6c936c4e0e7ede6bb2e7bb447b7782f7ed9db87c921293f43a3954bfae6d693e",
579
+ "detectors/planner_docs_capability/fixtures/clean/docs/purpose/journeys/svg/train-orders-ship-order.svg": "bf0b1e3a7cd40f66b9bc9ad91ae6302472f4bbdfb46c36cce84008ef493d6ce4",
580
+ "detectors/planner_docs_capability/fixtures/clean/docs/purpose/journeys/svg/train-orders-take-payment.svg": "8b6f705055c4b24e9e3070447073923f46cd968bc6fd2e1eca239f21d2499d3a",
571
581
  "detectors/planner_docs_capability/fixtures/clean/docs/purpose/worktrees.adoc": "de957bd8aec411c930fa9785d793c3345c82f5d7cb7f28f40f73f1c53a436440",
582
+ "detectors/planner_docs_capability/fixtures/clean/plan/_journeys/buy.yaml": "37a4e56cd44f1a7e33b7d3794ab2f178d5a6290574d5ead13ebd524356b5166c",
583
+ "detectors/planner_docs_capability/fixtures/clean/plan/_themes.yaml": "a8a4848d0df8c21eaad5563800e368330a0857593b9113db6a9608b08a7aa932",
584
+ "detectors/planner_docs_capability/fixtures/clean/plan/_trains/_interlockings/checkout.yaml": "ceb4414f8603b2357a4492d99132252e6024ff98d60b353c297b1ad421c9393e",
585
+ "detectors/planner_docs_capability/fixtures/clean/plan/_trains/_interlockings/fulfilment.yaml": "cbcb39a663952b583ba8b54bfd713a3faf68f86c9964d4bd45b60305d4416754",
586
+ "detectors/planner_docs_capability/fixtures/clean/plan/_trains/_interlockings/payment.yaml": "011fc6b445db43b71c06593ba15266dcb714ce557fa33391a736efb762816c8a",
587
+ "detectors/planner_docs_capability/fixtures/clean/plan/_trains/_interlockings/returns.yaml": "649fba5d83818342eecb7aa3cfb28494f631fc6239260359b7da665a4ccc0010",
588
+ "detectors/planner_docs_capability/fixtures/clean/plan/_trains/orders/archive-order.yaml": "951239c3492d668f46c9582032308b95fe5bd44b59f187c5f33f431e9f15e649",
589
+ "detectors/planner_docs_capability/fixtures/clean/plan/_trains/orders/place-order.yaml": "5563e0cd12856673c516c097597251c2d4e106f0de6727d3dad8aac45ec9bde6",
590
+ "detectors/planner_docs_capability/fixtures/clean/plan/_trains/orders/reject-empty-cart.yaml": "915d319db67d786c3c88a0d53d406e67cfdae343ae2e0529d5519c6649f33ace",
591
+ "detectors/planner_docs_capability/fixtures/clean/plan/_trains/orders/retry-payment.yaml": "2499a2706f9c8401f301997c86c6ce1b021050d78c050ce487b8d43ae555f855",
592
+ "detectors/planner_docs_capability/fixtures/clean/plan/_trains/orders/ship-order.yaml": "9f96d421caa225d2c62985b5a56e36dc5819369b222f6a7207c06e54e6f9866d",
593
+ "detectors/planner_docs_capability/fixtures/clean/plan/_trains/orders/take-payment.yaml": "4f3ef2cbb81e460032e48e11a9afb408c2aa8ab5c387c3c9a75a031136294ec2",
594
+ "detectors/planner_docs_capability/fixtures/clean/plan/_trains/orders/unrouted-refund.yaml": "e4f3094fe78e94cb2f40f4351a65e2bd12f56cc09fdf32af76b80a12c2530049",
572
595
  "detectors/planner_docs_capability/fixtures/dirty/docs/architecture/decisions/adr-20260906-001-shared-control-root.adoc": "6d30e5545e7b051c80605c3dbee50286f71e344ab2e71a987db945941de42523",
573
596
  "detectors/planner_docs_capability/fixtures/dirty/docs/architecture/decisions/index.adoc": "4a6cb87e249d587c85bb6389ff5fecae7a96194af8677b588eed0c791099123b",
574
597
  "detectors/planner_docs_capability/fixtures/dirty/docs/architecture/index.adoc": "d411bfc5e54c3a252c7f9549a2c62dd539e64f961f58b73b07c76b86708dc798",
@@ -621,6 +644,8 @@
621
644
  "detectors/planner_docs_capability/fixtures/dirty_identity/docs/index.adoc": "8aabcd7a4ecfc6ef565a604c1172364f761bef7d3fc4f2c96c07dce4e0ebe19b",
622
645
  "detectors/planner_docs_capability/fixtures/dirty_identity/docs/purpose/index.adoc": "e10193ea48f3c77b67ca8ed7221c53f23ce699e63f651cc340cea9ef6b44cffb",
623
646
  "detectors/planner_docs_capability/fixtures/dirty_identity/docs/purpose/worktrees.adoc": "de957bd8aec411c930fa9785d793c3345c82f5d7cb7f28f40f73f1c53a436440",
647
+ "detectors/planner_docs_capability/fixtures/dirty_journey_view/docs/index.adoc": "67b2010dc8b87ff55e500873dfb8ffad39e923c730adab0c92cb512b6d703edf",
648
+ "detectors/planner_docs_capability/fixtures/dirty_journey_view/plan/_trains/_interlockings/fulfilment.yaml": "cbcb39a663952b583ba8b54bfd713a3faf68f86c9964d4bd45b60305d4416754",
624
649
  "detectors/planner_docs_capability/fixtures/dirty_markdown/docs/architecture/decisions/adr-20260906-001-shared-control-root.adoc": "6d30e5545e7b051c80605c3dbee50286f71e344ab2e71a987db945941de42523",
625
650
  "detectors/planner_docs_capability/fixtures/dirty_markdown/docs/architecture/decisions/index.adoc": "4a6cb87e249d587c85bb6389ff5fecae7a96194af8677b588eed0c791099123b",
626
651
  "detectors/planner_docs_capability/fixtures/dirty_markdown/docs/architecture/index.adoc": "d411bfc5e54c3a252c7f9549a2c62dd539e64f961f58b73b07c76b86708dc798",
@@ -672,7 +697,7 @@
672
697
  "detectors/planner_schema_validation/fixtures/dirty/contracts/_contracts.yaml": "6460d5b8c73bb5f91ae356b29935c0a377cfef2d79ad6180e8cbb8a31fe2e882",
673
698
  "detectors/planner_schema_validation/fixtures/dirty/plan/_themes.yaml": "c3e8fb1939d83fdde56405ddfee68e266a16c4a7ed8439b6f7906d47372df473",
674
699
  "detectors/planner_schema_validation/fixtures/dirty/plan/_trains/orders.yaml": "ae2fdb750fd5a78c0baddd54fada48522671ae2a9a6538c50ab41ca32a90f682",
675
- "detectors/planner_static_validators/atdd.implementation.yaml": "32a2069b412adc76c256090f74ee36d31e4aac15e93a388c601203f75fa5e68b",
700
+ "detectors/planner_static_validators/atdd.implementation.yaml": "030d9999473bd488590a608b6f60f97f2b2c484a183574581edaa262a2e24a10",
676
701
  "detectors/planner_static_validators/detect.mjs": "efbff2e8cd3f1b7d8e3240f132e90f09cc081b9352511f3ade67ec6fe06d124b",
677
702
  "detectors/planner_static_validators/fixtures/clean/contracts/_contracts.yaml": "967f4f0aac0be000cb6107dc735ca21b73a3a21870e9ada1396df445584cad41",
678
703
  "detectors/planner_static_validators/fixtures/clean/contracts/orders/placed.schema.json": "0b6380fb315749dc14f178b7320acfc2a6f025ee6acd118d7a99c3d190890816",
@@ -684,6 +709,7 @@
684
709
  "detectors/planner_static_validators/fixtures/dirty/plan/_themes.yaml": "0bbebb0019c7b9e161916d1690eaf334712cf889d91339204f90aab1cf57f434",
685
710
  "detectors/planner_static_validators/fixtures/dirty/plan/_trains.yaml": "13227735d3ac236794bf0b3c908bae1f017cffb6c172c384b402a3740c4519db",
686
711
  "detectors/planner_static_validators/fixtures/dirty/plan/_trains/_interlockings/journey-a.yaml": "be82f5e215a68661b2bdccb472c388afaa0a28a28e4bd9131617a2c600eb1254",
712
+ "detectors/planner_static_validators/fixtures/dirty/plan/_trains/_interlockings/uncomposed.yaml": "087f2f510a7eb51acb0ac69079f6e2406adab0119339e14ed0ff0e798d2b1354",
687
713
  "detectors/planner_static_validators/fixtures/dirty/plan/_trains/journey-a.yaml": "9d2d941030f0cce37ed6c5064c1511047e14bf1b22f68aba5c1c9dc96fe8adf0",
688
714
  "detectors/planner_static_validators/fixtures/dirty/plan/_trains/probe/legacy.yaml": "a75bbc5075dd705b3dc4900dc7d724b877ad12a97062ac5598365b1ce4f06657",
689
715
  "detectors/planner_static_validators/fixtures/dirty/plan/_trains/probe/orphan.yaml": "2f11ecabc73d4fe4a18cd732376f653291d6ba8aacd4678e191949a2583c3e96",
@@ -693,7 +719,7 @@
693
719
  "detectors/planner_static_validators/fixtures/dirty/plan/dup/features/bad.yaml": "2a78ee5d50e119e2b1ab400ac5606a6625c0ebab60391f51a7bc294d8649d3ec",
694
720
  "lib/imports.mjs": "3db4979269488fa26f6e7aefded6ece9c646be6587a10e249821a5a208109962",
695
721
  "lib/scan.mjs": "8e090f131baca95cda6ad4ca4ff6e836fda9c9673547ad1d5b971ec0e7d89abf",
696
- "planner-nodes/ENFORCEMENT_SCOPE.yaml": "8b7748438343220ac37a422471faf60888e811fe1ec5192adad14e6e0d2543e0",
722
+ "planner-nodes/ENFORCEMENT_SCOPE.yaml": "1a77eea0ec17bc937ce538ab5d3eb31a87c420752d4657e57969048dd4fb60a2",
697
723
  "planner-nodes/nodes/planner.acceptance.abstract-fields-required.convention.yaml": "bd565693f0ae861f0561ad2f7a91a8c55f9a209c3acd59c5750cfcffd96a85d8",
698
724
  "planner-nodes/nodes/planner.acceptance.authoring-guidelines.convention.yaml": "16348dceed5868041b832bde766e9c8d4a950d4032f1f3066b357644081a3b17",
699
725
  "planner-nodes/nodes/planner.acceptance.boundary-kind-vocabulary.convention.yaml": "c5645225399568c2d4fe632442f9c597b2c59e4f4239880df7db2cbdc0353c9c",
@@ -800,6 +826,7 @@
800
826
  "planner-nodes/nodes/planner.issue-body.graph-context-required.convention.yaml": "6292ab37efda9fbdd1e028283bed7c594baa4e070266795180a3bcded2760621",
801
827
  "planner-nodes/nodes/planner.journey.continuation-closure.convention.yaml": "56c447b05cfe98804ea53bdde68ad940138093a4341620872e9b5c61be08869c",
802
828
  "planner-nodes/nodes/planner.journey.definition.convention.yaml": "a163bb9d5140d17a0dac996d84a8efc9f833592407dbebaec94db25006e88e28",
829
+ "planner-nodes/nodes/planner.journey.interlocking-composed.convention.yaml": "91d3f1a9061a1fccaeeb52a07f1459f93f665d310dc453fecbd5db23c603a7ec",
803
830
  "planner-nodes/nodes/planner.plan.confirm-before-author.convention.yaml": "23116f68ce81ff78ab57d362cf7195c4bf637781d74df4aece4d61eafbf0a49b",
804
831
  "planner-nodes/nodes/planner.plan.confirm-binds-an-issue.convention.yaml": "27de0e84fb7181a6768c65c30865fecdf94a3beddc3a47a4d6de226aaf014767",
805
832
  "planner-nodes/nodes/planner.plan.confirm-requires-interlocking-sanity.convention.yaml": "7ae7d9c6c70d0f4d3e50ae81f1d9f18ee1f70f348bee33147ee99d2d3d4a4de4",
@@ -910,17 +937,19 @@
910
937
  "planner-schemas/train.schema.json": "d6fbac9067c1bffeb84eb79a71228441055af6e6e7ba141dd4e0bcb079345ec0",
911
938
  "planner-schemas/wagon.schema.json": "57b98f1ade998d745538eb3d72fb3014a50042006870f90bce47028eea336eb4",
912
939
  "planner-schemas/wmbt.schema.json": "7a3a5693bfcf01340667c2be4a3c48e74f34b1af7e8dc13372c0de06b7f4fe12",
940
+ "relationships.yaml": "6e1888d37b56cc6a092137c0e0949bddf3a47560945ad09b20d30580dfb318e8",
913
941
  "src/agent.ts": "38a14f0f2ccce357efb1b2927e59bf55c20ff0050374367f15da36db20c46e77",
914
942
  "src/ci.ts": "899125ec76d14f7d0126a5db2249913e373e3a325cbc98d7f053e1351bdf47af",
915
- "src/cli.ts": "326ecd3b29ee08078df39982214909322cc96ca7d7e4739523152d0baf4bb535",
916
- "src/docs-capability.ts": "5e24ac316e7543782ccc8d8ec6e23f01161295aeb4e874a9c5ff0a8181f79475",
943
+ "src/cli.ts": "bb2047cee60f48bfe3eaee4c1b3dcd3538a0e1edc170cf58e87686117bea07a7",
944
+ "src/docs-capability.ts": "65ef91658664b41b78184b395e57e5d28bda16128caa9e314f26e63568abc6cd",
917
945
  "src/enforce.ts": "b7c7eae54c6aa2ba58ecf9dfa7c751c64328263b7241ac6c1a68210e2b7df313",
918
- "src/hooks.ts": "5e9a6a80cbb90d9d2ac19a3fbaf3f818265ca92227442231ab142fc6d5ce9570",
919
- "src/index.ts": "5b93f3df3cce6366c7f3975969f8dc69b3fe43bc2898257f8781f789f83687e7",
946
+ "src/hooks.ts": "88f78d9aa7b8182a3d7080cb94dab2a17a934c7437b5dd861dd428694908e72c",
947
+ "src/index.ts": "67ea1a791b3a625882d3ff6b981092f3764b694e660194736ecf53dac0890563",
920
948
  "src/integrity.ts": "48d7adce486ece1885a95aac6867d286bb972d7a97bdbc32222fd6d75c2e2b49",
949
+ "src/journey-docs.ts": "994d229376244c84212cff951032823068a76565dd2fd427b9d44e341bd14853",
921
950
  "src/planner-kernel.ts": "b201fe5a76e5298a3a3fcd11adbf0f47bfd8a565246c84d23db5d4d7bf0a3356",
922
951
  "src/planner-schema-validator.ts": "881ee4eb39db13471684854f9d1a667a5ef4451b104af2f6574ff0c237922217",
923
- "src/planner-validators.ts": "e584486617c5f7d799c2d9d1be8356157ea0a80c72de2fa714f5689cee001d9e",
952
+ "src/planner-validators.ts": "882c12c7ce4f8bf98eda71cd33c23ac8c224c28703e10ebef63288c1017757d5",
924
953
  "src/register.ts": "6a2f1c6b8df0dc9c8f45df8ec9fac2be29044e048b08c8ffe423410e94dadedd",
925
954
  "src/release.ts": "7b0fe444ee81f476f53b9c21b6c347ef588ee616c60211419cf984132be768ba",
926
955
  "src/setup.ts": "0a6f1a9aeff31dcf17f6bd036168b909c1841c11bbbb452105d8debf64a6bc78",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@afokapu/atdd-bun",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/afokapu/atdd-bun.git"
@@ -24,7 +24,8 @@
24
24
  "PLANNER_PORT.md",
25
25
  "HOOK_AUDIT.md",
26
26
  "templates",
27
- "integrity.json"
27
+ "integrity.json",
28
+ "relationships.yaml"
28
29
  ],
29
30
  "scripts": {
30
31
  "test": "bun test",
@@ -2,7 +2,7 @@ schema_version: "1.0.0"
2
2
  package: "@afokapu/atdd-bun"
3
3
  node_corpus:
4
4
  source: "src/atdd/planner/conventions/nodes/"
5
- count: 195
5
+ count: 196
6
6
  policy: >-
7
7
  Every node is shipped as canonical planner reference material. A node is not
8
8
  represented as enforced merely because it is present in this corpus.
@@ -31,6 +31,12 @@ canonical_bun_enforcement:
31
31
  - continuation artifacts occur in the selected train sequence
32
32
  - continuation destinations resolve to interlockings
33
33
  - disconnected continuation or terminal sources are rejected
34
+ - rule_id: planner.journey.interlocking-composed
35
+ origin: bun-custom-validator
36
+ coverage: complete
37
+ predicates:
38
+ - a plan that declares interlockings declares at least one journey
39
+ - every interlocking is a journey entrypoint or the destination of a continuation reachable from one
34
40
  - rule_id: planner.wagon.no-consume-cycle
35
41
  origin: core-validator-port
36
42
  coverage: partial