@afokapu/atdd-bun 0.10.40 → 0.10.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/conventions/_profiles/coder.yaml +72 -0
- package/conventions/_profiles/metrics.yaml +70 -0
- package/conventions/coder.bun/coder.bun.boundaries-http-client.convention.yaml +17 -1
- package/conventions/coder.bun/coder.bun.commons-application-no-integration.convention.yaml +17 -1
- package/conventions/coder.bun/coder.bun.commons-cross-feature-imports-in.convention.yaml +16 -1
- package/conventions/coder.bun/coder.bun.commons-domain-no-framework-import.convention.yaml +17 -1
- package/conventions/coder.bun/coder.bun.commons-domain-no-outbound.convention.yaml +17 -1
- package/conventions/coder.bun/coder.bun.composition-consumer.convention.yaml +16 -1
- package/conventions/coder.bun/coder.bun.composition-root.convention.yaml +17 -1
- package/conventions/coder.bun/coder.bun.design-connected.convention.yaml +17 -1
- package/conventions/coder.bun/coder.bun.design-dependency-flow.convention.yaml +17 -2
- package/conventions/coder.bun/coder.bun.design-hierarchy-import.convention.yaml +17 -1
- package/conventions/coder.bun/coder.bun.design-orphan-export.convention.yaml +17 -2
- package/conventions/coder.bun/coder.bun.design-primitives.convention.yaml +17 -2
- package/conventions/coder.bun/coder.bun.design-token-color.convention.yaml +17 -1
- package/conventions/coder.bun/coder.bun.design-token-hardcoded.convention.yaml +17 -2
- package/conventions/coder.bun/coder.bun.design-tokens-pure.convention.yaml +18 -2
- package/conventions/coder.bun/coder.bun.design-wagons-import.convention.yaml +18 -2
- package/conventions/coder.bun/coder.bun.dto-mapper.convention.yaml +16 -1
- package/conventions/coder.bun/coder.bun.dto-placement.convention.yaml +16 -1
- package/conventions/coder.bun/coder.bun.dto-purity.convention.yaml +17 -1
- package/conventions/coder.bun/coder.bun.green-header-order.convention.yaml +15 -7
- package/conventions/coder.bun/coder.bun.green-header-purpose.convention.yaml +16 -5
- package/conventions/coder.bun/coder.bun.green-header-runtime.convention.yaml +15 -6
- package/conventions/coder.bun/coder.bun.green-header-tested-by.convention.yaml +16 -11
- package/conventions/coder.bun/coder.bun.green-urn-layer.convention.yaml +16 -4
- package/conventions/coder.bun/coder.bun.green-urn-marker.convention.yaml +16 -9
- package/conventions/coder.bun/coder.bun.green-urn-name-matches.convention.yaml +16 -5
- package/conventions/coder.bun/coder.bun.green-urn-pattern.convention.yaml +16 -4
- package/conventions/coder.bun/coder.bun.green-urn-side.convention.yaml +15 -6
- package/conventions/coder.bun/coder.bun.green-urn-wagon-feature.convention.yaml +15 -6
- package/conventions/coder.bun/coder.bun.layer-naming.convention.yaml +16 -1
- package/conventions/coder.bun/coder.bun.phase-discipline.convention.yaml +111 -0
- package/conventions/coder.bun/coder.bun.responsive-breakpoints-declared.convention.yaml +17 -2
- package/conventions/coder.bun/coder.bun.responsive-no-fixed-width.convention.yaml +17 -1
- package/conventions/coder.bun/coder.bun.responsive-viewport-meta.convention.yaml +16 -1
- package/conventions/coder.bun/coder.bun.runtime-server-is-bun-serve.convention.yaml +16 -13
- package/conventions/coder.bun/coder.bun.runtime-single-lockfile.convention.yaml +16 -6
- package/conventions/coder.bun/coder.bun.runtime-typecheck-enforced.convention.yaml +16 -9
- package/conventions/tester.bun/tester.bun.acceptance-binding-declared.convention.yaml +20 -4
- package/conventions/tester.bun/tester.bun.acceptance-covers-tag-well-formed.convention.yaml +11 -5
- package/conventions/tester.bun/tester.bun.acceptance-resolves-to-declared.convention.yaml +23 -20
- package/conventions/tester.bun/tester.bun.interlocking-production-runner-used.convention.yaml +29 -7
- package/conventions/tester.bun/tester.bun.interlocking-route-coverage.convention.yaml +35 -10
- package/conventions/tester.bun/tester.bun.red-behavioral-assertion.convention.yaml +39 -5
- package/conventions/tester.bun/tester.bun.red-fails-first.convention.yaml +24 -7
- package/conventions/tester.bun/tester.bun.security-auth.convention.yaml +19 -1
- package/conventions/tester.bun/tester.bun.security-input.convention.yaml +19 -1
- package/conventions/tester.bun/tester.bun.smoke-no-collaborator-substitution.convention.yaml +21 -1
- package/conventions/tester.bun/tester.bun.smoke-observable-assertion.convention.yaml +23 -6
- package/conventions/tester.bun/tester.bun.test-phase-declared.convention.yaml +9 -3
- package/conventions/tester.htmx/tester.htmx.e2e-binds-declared-subject.convention.yaml +20 -3
- package/conventions/tester.htmx/tester.htmx.train-e2e-coverage.convention.yaml +24 -3
- package/integrity.json +58 -57
- package/package.json +1 -1
- package/relationships.yaml +71 -0
- package/src/enforce.ts +2 -2
- package/src/profile-registry.ts +4 -2
- package/templates/agents/AGENTS.block.md +2 -0
|
@@ -91,6 +91,8 @@ conventions:
|
|
|
91
91
|
path: "conventions/coder.bun/coder.bun.green-urn-wagon-feature.convention.yaml"
|
|
92
92
|
- rule_id: "coder.bun.layer-naming"
|
|
93
93
|
path: "conventions/coder.bun/coder.bun.layer-naming.convention.yaml"
|
|
94
|
+
- rule_id: "coder.bun.phase-discipline"
|
|
95
|
+
path: "conventions/coder.bun/coder.bun.phase-discipline.convention.yaml"
|
|
94
96
|
- rule_id: "coder.bun.quality-comments"
|
|
95
97
|
path: "conventions/coder.bun/coder.bun.quality-comments.convention.yaml"
|
|
96
98
|
- rule_id: "coder.bun.quality-mi"
|
|
@@ -602,6 +604,76 @@ relationships:
|
|
|
602
604
|
strength: "critical"
|
|
603
605
|
target_ref: "coder.bun.design-hierarchy-import"
|
|
604
606
|
type: "enables"
|
|
607
|
+
- confidence: 1
|
|
608
|
+
constraint: "mandatory"
|
|
609
|
+
control: "internal"
|
|
610
|
+
foundation: "start_to_start"
|
|
611
|
+
origin: "@afokapu/atdd-bun"
|
|
612
|
+
reason: "phase discipline directs the response to each refactor sensor without weakening its enforcement"
|
|
613
|
+
source_ref: "coder.bun.phase-discipline"
|
|
614
|
+
strength: "important"
|
|
615
|
+
target_ref: "coder.bun.complexity-cyclomatic"
|
|
616
|
+
type: "runs_alongside"
|
|
617
|
+
- confidence: 1
|
|
618
|
+
constraint: "mandatory"
|
|
619
|
+
control: "internal"
|
|
620
|
+
foundation: "start_to_start"
|
|
621
|
+
origin: "@afokapu/atdd-bun"
|
|
622
|
+
reason: "phase discipline directs the response to each refactor sensor without weakening its enforcement"
|
|
623
|
+
source_ref: "coder.bun.phase-discipline"
|
|
624
|
+
strength: "important"
|
|
625
|
+
target_ref: "coder.bun.complexity-length"
|
|
626
|
+
type: "runs_alongside"
|
|
627
|
+
- confidence: 1
|
|
628
|
+
constraint: "mandatory"
|
|
629
|
+
control: "internal"
|
|
630
|
+
foundation: "start_to_start"
|
|
631
|
+
origin: "@afokapu/atdd-bun"
|
|
632
|
+
reason: "phase discipline directs the response to each refactor sensor without weakening its enforcement"
|
|
633
|
+
source_ref: "coder.bun.phase-discipline"
|
|
634
|
+
strength: "important"
|
|
635
|
+
target_ref: "coder.bun.complexity-nesting"
|
|
636
|
+
type: "runs_alongside"
|
|
637
|
+
- confidence: 1
|
|
638
|
+
constraint: "mandatory"
|
|
639
|
+
control: "internal"
|
|
640
|
+
foundation: "start_to_start"
|
|
641
|
+
origin: "@afokapu/atdd-bun"
|
|
642
|
+
reason: "phase discipline directs the response to each refactor sensor without weakening its enforcement"
|
|
643
|
+
source_ref: "coder.bun.phase-discipline"
|
|
644
|
+
strength: "important"
|
|
645
|
+
target_ref: "coder.bun.dead-code-reachability"
|
|
646
|
+
type: "runs_alongside"
|
|
647
|
+
- confidence: 1
|
|
648
|
+
constraint: "mandatory"
|
|
649
|
+
control: "internal"
|
|
650
|
+
foundation: "start_to_start"
|
|
651
|
+
origin: "@afokapu/atdd-bun"
|
|
652
|
+
reason: "phase discipline directs the response to each refactor sensor without weakening its enforcement"
|
|
653
|
+
source_ref: "coder.bun.phase-discipline"
|
|
654
|
+
strength: "important"
|
|
655
|
+
target_ref: "coder.bun.duplication-intra-layer"
|
|
656
|
+
type: "runs_alongside"
|
|
657
|
+
- confidence: 1
|
|
658
|
+
constraint: "mandatory"
|
|
659
|
+
control: "internal"
|
|
660
|
+
foundation: "start_to_start"
|
|
661
|
+
origin: "@afokapu/atdd-bun"
|
|
662
|
+
reason: "phase discipline directs the response to each refactor sensor without weakening its enforcement"
|
|
663
|
+
source_ref: "coder.bun.phase-discipline"
|
|
664
|
+
strength: "important"
|
|
665
|
+
target_ref: "coder.bun.quality-comments"
|
|
666
|
+
type: "runs_alongside"
|
|
667
|
+
- confidence: 1
|
|
668
|
+
constraint: "mandatory"
|
|
669
|
+
control: "internal"
|
|
670
|
+
foundation: "start_to_start"
|
|
671
|
+
origin: "@afokapu/atdd-bun"
|
|
672
|
+
reason: "phase discipline directs the response to each refactor sensor without weakening its enforcement"
|
|
673
|
+
source_ref: "coder.bun.phase-discipline"
|
|
674
|
+
strength: "important"
|
|
675
|
+
target_ref: "coder.bun.quality-mi"
|
|
676
|
+
type: "runs_alongside"
|
|
605
677
|
- confidence: 1
|
|
606
678
|
constraint: "mandatory"
|
|
607
679
|
control: "internal"
|
|
@@ -58,6 +58,76 @@ relationships:
|
|
|
58
58
|
strength: "minor"
|
|
59
59
|
target_ref: "coder.bun.dead-code-reachability"
|
|
60
60
|
type: "runs_alongside"
|
|
61
|
+
- confidence: 1
|
|
62
|
+
constraint: "mandatory"
|
|
63
|
+
control: "internal"
|
|
64
|
+
foundation: "start_to_start"
|
|
65
|
+
origin: "@afokapu/atdd-bun"
|
|
66
|
+
reason: "phase discipline directs the response to each refactor sensor without weakening its enforcement"
|
|
67
|
+
source_ref: "coder.bun.phase-discipline"
|
|
68
|
+
strength: "important"
|
|
69
|
+
target_ref: "coder.bun.complexity-cyclomatic"
|
|
70
|
+
type: "runs_alongside"
|
|
71
|
+
- confidence: 1
|
|
72
|
+
constraint: "mandatory"
|
|
73
|
+
control: "internal"
|
|
74
|
+
foundation: "start_to_start"
|
|
75
|
+
origin: "@afokapu/atdd-bun"
|
|
76
|
+
reason: "phase discipline directs the response to each refactor sensor without weakening its enforcement"
|
|
77
|
+
source_ref: "coder.bun.phase-discipline"
|
|
78
|
+
strength: "important"
|
|
79
|
+
target_ref: "coder.bun.complexity-length"
|
|
80
|
+
type: "runs_alongside"
|
|
81
|
+
- confidence: 1
|
|
82
|
+
constraint: "mandatory"
|
|
83
|
+
control: "internal"
|
|
84
|
+
foundation: "start_to_start"
|
|
85
|
+
origin: "@afokapu/atdd-bun"
|
|
86
|
+
reason: "phase discipline directs the response to each refactor sensor without weakening its enforcement"
|
|
87
|
+
source_ref: "coder.bun.phase-discipline"
|
|
88
|
+
strength: "important"
|
|
89
|
+
target_ref: "coder.bun.complexity-nesting"
|
|
90
|
+
type: "runs_alongside"
|
|
91
|
+
- confidence: 1
|
|
92
|
+
constraint: "mandatory"
|
|
93
|
+
control: "internal"
|
|
94
|
+
foundation: "start_to_start"
|
|
95
|
+
origin: "@afokapu/atdd-bun"
|
|
96
|
+
reason: "phase discipline directs the response to each refactor sensor without weakening its enforcement"
|
|
97
|
+
source_ref: "coder.bun.phase-discipline"
|
|
98
|
+
strength: "important"
|
|
99
|
+
target_ref: "coder.bun.dead-code-reachability"
|
|
100
|
+
type: "runs_alongside"
|
|
101
|
+
- confidence: 1
|
|
102
|
+
constraint: "mandatory"
|
|
103
|
+
control: "internal"
|
|
104
|
+
foundation: "start_to_start"
|
|
105
|
+
origin: "@afokapu/atdd-bun"
|
|
106
|
+
reason: "phase discipline directs the response to each refactor sensor without weakening its enforcement"
|
|
107
|
+
source_ref: "coder.bun.phase-discipline"
|
|
108
|
+
strength: "important"
|
|
109
|
+
target_ref: "coder.bun.duplication-intra-layer"
|
|
110
|
+
type: "runs_alongside"
|
|
111
|
+
- confidence: 1
|
|
112
|
+
constraint: "mandatory"
|
|
113
|
+
control: "internal"
|
|
114
|
+
foundation: "start_to_start"
|
|
115
|
+
origin: "@afokapu/atdd-bun"
|
|
116
|
+
reason: "phase discipline directs the response to each refactor sensor without weakening its enforcement"
|
|
117
|
+
source_ref: "coder.bun.phase-discipline"
|
|
118
|
+
strength: "important"
|
|
119
|
+
target_ref: "coder.bun.quality-comments"
|
|
120
|
+
type: "runs_alongside"
|
|
121
|
+
- confidence: 1
|
|
122
|
+
constraint: "mandatory"
|
|
123
|
+
control: "internal"
|
|
124
|
+
foundation: "start_to_start"
|
|
125
|
+
origin: "@afokapu/atdd-bun"
|
|
126
|
+
reason: "phase discipline directs the response to each refactor sensor without weakening its enforcement"
|
|
127
|
+
source_ref: "coder.bun.phase-discipline"
|
|
128
|
+
strength: "important"
|
|
129
|
+
target_ref: "coder.bun.quality-mi"
|
|
130
|
+
type: "runs_alongside"
|
|
61
131
|
- confidence: 1
|
|
62
132
|
constraint: "mandatory"
|
|
63
133
|
control: "internal"
|
|
@@ -25,7 +25,23 @@ content:
|
|
|
25
25
|
A centralized client is where retries, timeouts, auth headers, tracing and error translation live. Every bare `fetch` is a call site that has none of them and will not acquire them, because nobody remembers it exists.
|
|
26
26
|
In an htmx app this matters on the SERVER side particularly: the fragments a handler renders often depend on an upstream call, and a bare fetch there fails in a way the user sees as a blank swap.
|
|
27
27
|
fix_hint: |
|
|
28
|
-
|
|
28
|
+
Canonical path:
|
|
29
|
+
* use the existing integration-layer HTTP client or adapter,
|
|
30
|
+
* let that boundary own transport concerns such as headers, retries, decoding, and error translation.
|
|
31
|
+
|
|
32
|
+
During GREEN:
|
|
33
|
+
* make only the outbound call and mapping required by the current acceptance,
|
|
34
|
+
* reuse an existing client or port before introducing another abstraction,
|
|
35
|
+
* if no compliant boundary exists, add the smallest integration adapter the behavior requires.
|
|
36
|
+
|
|
37
|
+
Do not broaden:
|
|
38
|
+
* do not migrate unrelated callers,
|
|
39
|
+
* do not create a generalized HTTP framework for hypothetical endpoints,
|
|
40
|
+
* do not call `fetch()` or `axios` directly just to make the test pass.
|
|
41
|
+
|
|
42
|
+
Prove:
|
|
43
|
+
* the current behavioral acceptance passes,
|
|
44
|
+
* the affected source satisfies this boundary rule.
|
|
29
45
|
exceptions:
|
|
30
46
|
- Test files and vendored/build directories are never scanned.
|
|
31
47
|
- Bare npm specifiers resolve outside the project graph and are not layer-checked.
|
|
@@ -22,7 +22,23 @@ content:
|
|
|
22
22
|
normative_text: |
|
|
23
23
|
The application layer orchestrates through ports it defines. Reaching into integration inverts the dependency and welds orchestration to a specific transport, so changing the transport changes the orchestration.
|
|
24
24
|
fix_hint: |
|
|
25
|
-
|
|
25
|
+
Canonical path:
|
|
26
|
+
* keep commons application code dependent on an application-facing port,
|
|
27
|
+
* let integration implement that port and let the composition root supply it.
|
|
28
|
+
|
|
29
|
+
During GREEN:
|
|
30
|
+
* first reuse an existing port that already represents the required capability,
|
|
31
|
+
* add the smallest missing port only when the current behavior genuinely needs an outer capability,
|
|
32
|
+
* pass only the data or collaborator required by the acceptance.
|
|
33
|
+
|
|
34
|
+
Do not broaden:
|
|
35
|
+
* do not reorganize unrelated commons modules,
|
|
36
|
+
* do not introduce a generalized service layer for future callers,
|
|
37
|
+
* do not import integration directly as a shortcut to GREEN.
|
|
38
|
+
|
|
39
|
+
Prove:
|
|
40
|
+
* the current behavioral acceptance passes,
|
|
41
|
+
* commons application has no integration dependency.
|
|
26
42
|
exceptions:
|
|
27
43
|
- Test files and vendored/build directories are never scanned.
|
|
28
44
|
- Bare npm specifiers resolve outside the project graph and are not layer-checked.
|
|
@@ -21,7 +21,22 @@ content:
|
|
|
21
21
|
normative_text: |
|
|
22
22
|
A feature's internals are its own. The layer root is the surface it deliberately exposes, and reaching past it couples two features through a path that neither of them chose to publish — which is how a shared module quietly becomes unsplittable.
|
|
23
23
|
fix_hint: |
|
|
24
|
-
|
|
24
|
+
Canonical path:
|
|
25
|
+
* consume another commons feature through the layer root, never through that sibling's internals.
|
|
26
|
+
|
|
27
|
+
During GREEN:
|
|
28
|
+
* reuse an export that already represents the required capability,
|
|
29
|
+
* if the capability is intentionally shared, expose the smallest stable surface from the layer root,
|
|
30
|
+
* if it is not a shared responsibility, keep the implementation local instead of reaching across.
|
|
31
|
+
|
|
32
|
+
Do not broaden:
|
|
33
|
+
* do not export a sibling's internals wholesale,
|
|
34
|
+
* do not create a generic shared module merely to make the import legal,
|
|
35
|
+
* do not move unrelated code between features.
|
|
36
|
+
|
|
37
|
+
Prove:
|
|
38
|
+
* the current behavioral acceptance passes,
|
|
39
|
+
* the cross-feature dependency goes through the intended public boundary.
|
|
25
40
|
exceptions:
|
|
26
41
|
- Test files and vendored/build directories are never scanned.
|
|
27
42
|
- Bare npm specifiers resolve outside the project graph and are not layer-checked.
|
|
@@ -22,7 +22,23 @@ content:
|
|
|
22
22
|
The Vite sibling forbids react/preact/@tanstack/gsap because those are ITS frameworks. The obligation is identical — the domain expresses rules, not machinery — and only the list of machinery changes with the stack. For a full-stack Bun app the machinery is the server and transport primitives.
|
|
23
23
|
The practical test: the domain must be runnable with no server started. `Bun.` in a domain module means it is not.
|
|
24
24
|
fix_hint: |
|
|
25
|
-
|
|
25
|
+
Canonical path:
|
|
26
|
+
* keep domain code as data-in / data-out logic,
|
|
27
|
+
* move Bun, Node, htmx, server, or framework machinery to an outer layer and pass the needed value inward.
|
|
28
|
+
|
|
29
|
+
During GREEN:
|
|
30
|
+
* adapt at the nearest existing integration or presentation boundary,
|
|
31
|
+
* pass the smallest value or domain-facing collaborator the behavior needs,
|
|
32
|
+
* add a new boundary only when no existing one can express the current behavior correctly.
|
|
33
|
+
|
|
34
|
+
Do not broaden:
|
|
35
|
+
* do not wrap a framework API in a domain-named helper and keep the coupling,
|
|
36
|
+
* do not redesign adjacent layers,
|
|
37
|
+
* do not import runtime machinery just to satisfy the acceptance quickly.
|
|
38
|
+
|
|
39
|
+
Prove:
|
|
40
|
+
* the current behavioral acceptance passes,
|
|
41
|
+
* the domain remains executable without runtime machinery.
|
|
26
42
|
exceptions:
|
|
27
43
|
- Test files and vendored/build directories are never scanned.
|
|
28
44
|
- Bare npm specifiers resolve outside the project graph and are not layer-checked.
|
|
@@ -23,7 +23,23 @@ content:
|
|
|
23
23
|
Dependencies point INWARD only. The domain is the centre: it holds the rules, and it must not know what orchestrates them or what transports them.
|
|
24
24
|
An outward import inverts that and makes the rules unusable without the machinery — which shows up first as a domain test that needs a database.
|
|
25
25
|
fix_hint: |
|
|
26
|
-
|
|
26
|
+
Canonical path:
|
|
27
|
+
* keep commons domain dependencies inward,
|
|
28
|
+
* move genuinely domain-owned data or behavior into domain, or invert an outer capability behind a domain-facing port.
|
|
29
|
+
|
|
30
|
+
During GREEN:
|
|
31
|
+
* prefer existing domain types, functions, and ports,
|
|
32
|
+
* introduce a new port only when the current behavior requires the domain to request an outer capability,
|
|
33
|
+
* keep the port as narrow as the acceptance requires.
|
|
34
|
+
|
|
35
|
+
Do not broaden:
|
|
36
|
+
* do not move unrelated application or integration behavior into domain,
|
|
37
|
+
* do not invent a future-proof abstraction,
|
|
38
|
+
* do not import outward as a temporary shortcut.
|
|
39
|
+
|
|
40
|
+
Prove:
|
|
41
|
+
* the current behavioral acceptance passes,
|
|
42
|
+
* commons domain imports no application or integration code.
|
|
27
43
|
exceptions:
|
|
28
44
|
- Test files and vendored/build directories are never scanned.
|
|
29
45
|
- Bare npm specifiers resolve outside the project graph and are not layer-checked.
|
|
@@ -22,7 +22,22 @@ content:
|
|
|
22
22
|
The sibling of `composition-root`, and the half that makes the discipline pay. That rule says where wiring MAY happen; this one says consumers must accept what they are given.
|
|
23
23
|
A consumer that builds its own collaborators cannot be tested without them — which is exactly how a unit test acquires a database.
|
|
24
24
|
fix_hint: |
|
|
25
|
-
|
|
25
|
+
Canonical path:
|
|
26
|
+
* receive collaborators through parameters or already-wired construction,
|
|
27
|
+
* let the composition root decide which concrete collaborator is supplied.
|
|
28
|
+
|
|
29
|
+
During GREEN:
|
|
30
|
+
* reuse the consumer's existing injection shape when one exists,
|
|
31
|
+
* add only the collaborator required by the current behavior,
|
|
32
|
+
* prefer the narrowest existing contract over a new generalized interface.
|
|
33
|
+
|
|
34
|
+
Do not broaden:
|
|
35
|
+
* do not instantiate a repository, client, service, adapter, gateway, store, provider, or factory inside the consumer,
|
|
36
|
+
* do not redesign unrelated constructor or function signatures.
|
|
37
|
+
|
|
38
|
+
Prove:
|
|
39
|
+
* the current behavioral acceptance passes,
|
|
40
|
+
* the consumer can be exercised with its collaborator supplied from outside.
|
|
26
41
|
exceptions:
|
|
27
42
|
- Test files and vendored/build directories are never scanned.
|
|
28
43
|
- Bare npm specifiers resolve outside the project graph and are not layer-checked.
|
|
@@ -24,7 +24,23 @@ content:
|
|
|
24
24
|
`server.ts` is a root in this stack specifically because `Bun.serve` IS the assembly point of a full-stack Bun app — the place routes and their dependencies are wired. The Convex sibling has no equivalent because its function tree has no single entry.
|
|
25
25
|
Wiring scattered across a codebase is not a style problem: it is why a test cannot substitute anything, and why a second deployment shape becomes a rewrite.
|
|
26
26
|
fix_hint: |
|
|
27
|
-
|
|
27
|
+
Canonical path:
|
|
28
|
+
* construct collaborators in `composition.ts`, `wagon.ts`, `server.ts`, or `index.ts`,
|
|
29
|
+
* pass the constructed collaborator to the consumer that needs it.
|
|
30
|
+
|
|
31
|
+
During GREEN:
|
|
32
|
+
* add only the wiring required by the current behavior,
|
|
33
|
+
* reuse existing factories, instances, and composition patterns before creating new ones,
|
|
34
|
+
* keep construction separate from application or presentation behavior.
|
|
35
|
+
|
|
36
|
+
Do not broaden:
|
|
37
|
+
* do not centralize unrelated wiring merely because the root is being edited,
|
|
38
|
+
* do not add speculative factories or service locators,
|
|
39
|
+
* do not instantiate the collaborator in the consumer as a shortcut.
|
|
40
|
+
|
|
41
|
+
Prove:
|
|
42
|
+
* the current behavioral acceptance passes through the real wiring,
|
|
43
|
+
* collaborator construction remains confined to a composition root.
|
|
28
44
|
exceptions:
|
|
29
45
|
- Test files and vendored/build directories are never scanned.
|
|
30
46
|
- Bare npm specifiers resolve outside the project graph and are not layer-checked.
|
|
@@ -18,7 +18,23 @@ content:
|
|
|
18
18
|
summary: Flags rendering component files outside the design root that import nothing from it.
|
|
19
19
|
normative_text: A screen built without the system is where the next one-off style lands. Requiring one design
|
|
20
20
|
import makes the connection explicit and reviewable.
|
|
21
|
-
fix_hint:
|
|
21
|
+
fix_hint: |
|
|
22
|
+
Canonical path:
|
|
23
|
+
* compose application UI from the existing design-system template, component, or primitive that owns the required role.
|
|
24
|
+
|
|
25
|
+
During GREEN:
|
|
26
|
+
* reuse the nearest existing design-system surface before creating a new one,
|
|
27
|
+
* add only the connection required by the current rendered behavior,
|
|
28
|
+
* if no suitable surface exists, introduce the smallest design-system component that expresses the current need.
|
|
29
|
+
|
|
30
|
+
Do not broaden:
|
|
31
|
+
* do not redesign the screen or migrate unrelated markup,
|
|
32
|
+
* do not create a generic component library for hypothetical callers,
|
|
33
|
+
* do not add a meaningless import merely to satisfy connectivity.
|
|
34
|
+
|
|
35
|
+
Prove:
|
|
36
|
+
* the current behavioral or rendering acceptance passes,
|
|
37
|
+
* the rendered app component is genuinely composed from the design system.
|
|
22
38
|
exceptions:
|
|
23
39
|
- Test files (`*.test.*`, `*.spec.*`) and vendored/build directories are never scanned.
|
|
24
40
|
- Non-rendering modules (routes, handlers, data) are not judged.
|
|
@@ -19,8 +19,23 @@ content:
|
|
|
19
19
|
summary: Resolves each import of a design-system file to its target layer and flags any edge that points upward.
|
|
20
20
|
normative_text: A hierarchy is only a hierarchy if dependencies flow one way. A primitive that imports a component
|
|
21
21
|
can no longer be reused without dragging that component along, and the layers collapse into one tangle.
|
|
22
|
-
fix_hint:
|
|
23
|
-
|
|
22
|
+
fix_hint: |
|
|
23
|
+
Canonical path:
|
|
24
|
+
* keep design-system imports at the same layer or pointing downward through tokens -> foundations -> primitives -> components -> templates.
|
|
25
|
+
|
|
26
|
+
During GREEN:
|
|
27
|
+
* reuse an existing lower-layer value or component when possible,
|
|
28
|
+
* move a genuinely shared piece only to the lowest layer that actually owns it,
|
|
29
|
+
* compose upward rather than importing upward.
|
|
30
|
+
|
|
31
|
+
Do not broaden:
|
|
32
|
+
* do not reshuffle unrelated design-system files,
|
|
33
|
+
* do not create a new layer or generic abstraction for one dependency,
|
|
34
|
+
* do not hide an upward dependency behind a barrel.
|
|
35
|
+
|
|
36
|
+
Prove:
|
|
37
|
+
* the current behavioral or rendering acceptance passes,
|
|
38
|
+
* all affected design-system imports follow the declared direction.
|
|
24
39
|
exceptions:
|
|
25
40
|
- Test files (`*.test.*`, `*.spec.*`) and vendored/build directories are never scanned.
|
|
26
41
|
- Imports within the same layer are allowed.
|
|
@@ -24,7 +24,23 @@ content:
|
|
|
24
24
|
This is the general rule the commons rules apply to one tree. It is stated separately because it governs FEATURE code as well, where most layering damage actually happens.
|
|
25
25
|
The assembly exemption is what makes the rest workable: something must be allowed to know about everything, and confining that to the composition root is the whole point of having one.
|
|
26
26
|
fix_hint: |
|
|
27
|
-
|
|
27
|
+
Canonical path:
|
|
28
|
+
* depend inward through presentation -> application -> domain, with integration depending on application/domain and assembly allowed to wire all layers,
|
|
29
|
+
* when an inner layer needs an outer capability, use an existing inward-facing port.
|
|
30
|
+
|
|
31
|
+
During GREEN:
|
|
32
|
+
* reuse the nearest existing compliant dependency path,
|
|
33
|
+
* introduce the smallest missing port only when the current behavior cannot otherwise be implemented correctly,
|
|
34
|
+
* keep the new contract limited to what the acceptance requires.
|
|
35
|
+
|
|
36
|
+
Do not broaden:
|
|
37
|
+
* do not reclassify or merge layers merely to make one import legal,
|
|
38
|
+
* do not redesign adjacent modules,
|
|
39
|
+
* do not add a dependency that points outward as a temporary step.
|
|
40
|
+
|
|
41
|
+
Prove:
|
|
42
|
+
* the current behavioral acceptance passes,
|
|
43
|
+
* every affected import still points in an allowed direction.
|
|
28
44
|
exceptions:
|
|
29
45
|
- Test files and vendored/build directories are never scanned.
|
|
30
46
|
- Bare npm specifiers resolve outside the project graph and are not layer-checked.
|
|
@@ -18,8 +18,23 @@ content:
|
|
|
18
18
|
summary: Collects capitalized exports of primitives/components/templates and flags those no other file imports.
|
|
19
19
|
normative_text: Unused components still have to be maintained, themed, and migrated. A design system grows by
|
|
20
20
|
adjudication, not by accretion of pieces nobody uses.
|
|
21
|
-
fix_hint:
|
|
22
|
-
|
|
21
|
+
fix_hint: |
|
|
22
|
+
Canonical path:
|
|
23
|
+
* export a design-system component only when a real consumer uses it; otherwise remove the unused export.
|
|
24
|
+
|
|
25
|
+
During GREEN:
|
|
26
|
+
* if the current acceptance needs the component, wire that actual consumer to it,
|
|
27
|
+
* if the export was introduced speculatively and has no required consumer, delete it,
|
|
28
|
+
* keep only the smallest export surface the current behavior needs.
|
|
29
|
+
|
|
30
|
+
Do not broaden:
|
|
31
|
+
* do not add a dummy consumer or synthetic import,
|
|
32
|
+
* do not keep speculative components "for later",
|
|
33
|
+
* do not expose unrelated internals from a barrel to make the graph look connected.
|
|
34
|
+
|
|
35
|
+
Prove:
|
|
36
|
+
* the current behavioral or rendering acceptance passes,
|
|
37
|
+
* every affected export has a genuine consumer.
|
|
23
38
|
exceptions:
|
|
24
39
|
- Test files (`*.test.*`, `*.spec.*`) and vendored/build directories are never scanned.
|
|
25
40
|
- Token/foundation values and `index.*` barrels are not judged.
|
|
@@ -17,8 +17,23 @@ content:
|
|
|
17
17
|
summary: Flags raw interactive platform elements in component source outside the design root.
|
|
18
18
|
normative_text: Controls are where focus, disabled, error, and loading states live. Each raw control re-implements
|
|
19
19
|
them, and each re-implementation diverges.
|
|
20
|
-
fix_hint:
|
|
21
|
-
|
|
20
|
+
fix_hint: |
|
|
21
|
+
Canonical path:
|
|
22
|
+
* render interactive controls through the existing design-system primitive and pass required htmx or DOM attributes through it.
|
|
23
|
+
|
|
24
|
+
During GREEN:
|
|
25
|
+
* reuse the primitive that already represents the control,
|
|
26
|
+
* extend only the smallest prop or attribute surface required by the current interaction,
|
|
27
|
+
* create a new primitive only when no existing primitive represents the control correctly.
|
|
28
|
+
|
|
29
|
+
Do not broaden:
|
|
30
|
+
* do not restyle or migrate unrelated controls,
|
|
31
|
+
* do not bypass the primitive with raw interactive markup just to pass the acceptance,
|
|
32
|
+
* do not add generic props that the current behavior does not need.
|
|
33
|
+
|
|
34
|
+
Prove:
|
|
35
|
+
* the interaction acceptance passes,
|
|
36
|
+
* the rendered interactive control comes through the design-system primitive.
|
|
22
37
|
exceptions:
|
|
23
38
|
- Test files (`*.test.*`, `*.spec.*`) and vendored/build directories are never scanned.
|
|
24
39
|
- The design system's own primitives render the raw elements and are not scanned.
|
|
@@ -20,7 +20,23 @@ content:
|
|
|
20
20
|
raw color literals in their values.
|
|
21
21
|
normative_text: A raw color is a theme decision made in one place. It does not follow dark mode, it drifts from
|
|
22
22
|
the palette, and nobody can find it when the palette changes.
|
|
23
|
-
fix_hint:
|
|
23
|
+
fix_hint: |
|
|
24
|
+
Canonical path:
|
|
25
|
+
* define the required color once in the tokens layer and reference that token from UI code.
|
|
26
|
+
|
|
27
|
+
During GREEN:
|
|
28
|
+
* reuse an existing semantic color token when it already expresses the required role,
|
|
29
|
+
* add the smallest new semantic token only when the current visual behavior needs a distinct value,
|
|
30
|
+
* change only the affected UI reference.
|
|
31
|
+
|
|
32
|
+
Do not broaden:
|
|
33
|
+
* do not retheme unrelated components,
|
|
34
|
+
* do not duplicate an existing token under a new name,
|
|
35
|
+
* do not use a raw literal as a temporary shortcut.
|
|
36
|
+
|
|
37
|
+
Prove:
|
|
38
|
+
* the current visual or behavioral acceptance passes,
|
|
39
|
+
* affected UI files contain no raw color literal outside the tokens layer.
|
|
24
40
|
exceptions:
|
|
25
41
|
- Test files (`*.test.*`, `*.spec.*`) and vendored/build directories are never scanned.
|
|
26
42
|
- 'Custom property definitions (`--danger: #b91c1c`) define tokens wherever they live and are not flagged.'
|
|
@@ -20,8 +20,23 @@ content:
|
|
|
20
20
|
the design system's own primitives and components.
|
|
21
21
|
normative_text: Spacing and motion are the rhythm of an interface. Each hardcoded `13px` is a new step on a scale
|
|
22
22
|
nobody chose, and the rhythm erodes one component at a time.
|
|
23
|
-
fix_hint:
|
|
24
|
-
|
|
23
|
+
fix_hint: |
|
|
24
|
+
Canonical path:
|
|
25
|
+
* take spacing, inset, radius, and duration values from the existing foundations scale.
|
|
26
|
+
|
|
27
|
+
During GREEN:
|
|
28
|
+
* reuse the nearest existing semantic or scale token,
|
|
29
|
+
* add a new foundation value only when the current design genuinely requires a distinct value,
|
|
30
|
+
* change only the declaration needed by the acceptance.
|
|
31
|
+
|
|
32
|
+
Do not broaden:
|
|
33
|
+
* do not normalize unrelated styling,
|
|
34
|
+
* do not create one-off tokens that merely rename a hardcoded literal,
|
|
35
|
+
* do not bypass the scale for speed.
|
|
36
|
+
|
|
37
|
+
Prove:
|
|
38
|
+
* the current visual or behavioral acceptance passes,
|
|
39
|
+
* affected UI values come from the declared foundations.
|
|
25
40
|
exceptions:
|
|
26
41
|
- Test files (`*.test.*`, `*.spec.*`) and vendored/build directories are never scanned.
|
|
27
42
|
- 0 and 1px (hairline borders) are not design decisions and are allowed.
|
|
@@ -18,8 +18,24 @@ content:
|
|
|
18
18
|
summary: Scans token/foundation code files for renderer imports, rendered markup, and control flow.
|
|
19
19
|
normative_text: Tokens are what every other layer depends on. Once they render or decide, the bottom of the hierarchy
|
|
20
20
|
has behaviour, and every primitive inherits it.
|
|
21
|
-
fix_hint:
|
|
22
|
-
|
|
21
|
+
fix_hint: |
|
|
22
|
+
Canonical path:
|
|
23
|
+
* keep tokens and foundations as values only,
|
|
24
|
+
* move markup to primitives/components and behavior to the layer that owns it.
|
|
25
|
+
|
|
26
|
+
During GREEN:
|
|
27
|
+
* leave the value in the token or foundation file,
|
|
28
|
+
* move only the markup or logic required by the current behavior to the nearest existing owning layer,
|
|
29
|
+
* reuse an existing primitive or component before creating a new one.
|
|
30
|
+
|
|
31
|
+
Do not broaden:
|
|
32
|
+
* do not reorganize unrelated tokens,
|
|
33
|
+
* do not move behavior into a different layer merely to silence the rule,
|
|
34
|
+
* do not create a generalized component unrelated to the current acceptance.
|
|
35
|
+
|
|
36
|
+
Prove:
|
|
37
|
+
* the current behavioral or rendering acceptance passes,
|
|
38
|
+
* token and foundation files remain value-only.
|
|
23
39
|
exceptions:
|
|
24
40
|
- Test files (`*.test.*`, `*.spec.*`) and vendored/build directories are never scanned.
|
|
25
41
|
- '`.css` token files are values by construction and are not scanned by this rule.'
|
|
@@ -17,8 +17,24 @@ content:
|
|
|
17
17
|
summary: Flags relative imports from a design-system file that leave the design root.
|
|
18
18
|
normative_text: 'A design system that reaches into a wagon has become part of that wagon: it cannot be reused
|
|
19
19
|
by the next one, and a change to the wagon breaks the system.'
|
|
20
|
-
fix_hint:
|
|
21
|
-
|
|
20
|
+
fix_hint: |
|
|
21
|
+
Canonical path:
|
|
22
|
+
* keep the design system independent of application and wagon code,
|
|
23
|
+
* pass app-specific values into design components or move genuinely shared, design-owned types/constants inward.
|
|
24
|
+
|
|
25
|
+
During GREEN:
|
|
26
|
+
* prefer props or existing design-system contracts for the current value,
|
|
27
|
+
* add only the smallest input surface required by the acceptance,
|
|
28
|
+
* move a type or constant only when it is truly owned by the design system.
|
|
29
|
+
|
|
30
|
+
Do not broaden:
|
|
31
|
+
* do not import a wagon through a barrel or alias,
|
|
32
|
+
* do not relocate app-specific concepts into design code just to make the import legal,
|
|
33
|
+
* do not generalize unrelated design APIs.
|
|
34
|
+
|
|
35
|
+
Prove:
|
|
36
|
+
* the current behavioral or rendering acceptance passes,
|
|
37
|
+
* design-system files import nothing from app or wagon code.
|
|
22
38
|
exceptions:
|
|
23
39
|
- Test files (`*.test.*`, `*.spec.*`) and vendored/build directories are never scanned.
|
|
24
40
|
- Bare package specifiers (`hono/jsx`) are outside the project graph and are not judged.
|
|
@@ -20,7 +20,22 @@ content:
|
|
|
20
20
|
normative_text: |
|
|
21
21
|
Mapping is translation across a boundary, which is precisely what the integration layer is for. A mapper in the domain drags the wire format inward; a mapper in presentation duplicates itself once a second caller appears.
|
|
22
22
|
fix_hint: |
|
|
23
|
-
|
|
23
|
+
Canonical path:
|
|
24
|
+
* keep DTO-to-domain and domain-to-DTO translation in the integration layer where both shapes are legitimately visible.
|
|
25
|
+
|
|
26
|
+
During GREEN:
|
|
27
|
+
* reuse an existing mapper for the same boundary when one exists,
|
|
28
|
+
* add only the field mapping required by the current acceptance,
|
|
29
|
+
* create a new mapper only for a genuinely new boundary translation.
|
|
30
|
+
|
|
31
|
+
Do not broaden:
|
|
32
|
+
* do not move domain behavior into the mapper,
|
|
33
|
+
* do not migrate unrelated mappings,
|
|
34
|
+
* do not place translation in presentation or domain as a shortcut.
|
|
35
|
+
|
|
36
|
+
Prove:
|
|
37
|
+
* the current behavioral acceptance passes,
|
|
38
|
+
* the mapper lives in integration and preserves the intended boundary.
|
|
24
39
|
exceptions:
|
|
25
40
|
- Test files and vendored/build directories are never scanned.
|
|
26
41
|
- Bare npm specifiers resolve outside the project graph and are not layer-checked.
|
|
@@ -21,7 +21,22 @@ content:
|
|
|
21
21
|
normative_text: |
|
|
22
22
|
A DTO belongs to the contract, not to either side of it. Declared inside one feature's layer it becomes that feature's private type that another feature imports anyway — and the boundary it was meant to define now runs through somebody's internals.
|
|
23
23
|
fix_hint: |
|
|
24
|
-
|
|
24
|
+
Canonical path:
|
|
25
|
+
* declare a DTO in `contracts/` and import that shared boundary shape from both sides.
|
|
26
|
+
|
|
27
|
+
During GREEN:
|
|
28
|
+
* reuse an existing contract type when it already represents the required payload,
|
|
29
|
+
* add only the fields required by the current acceptance,
|
|
30
|
+
* create a new DTO only when the behavior introduces a genuinely distinct boundary shape.
|
|
31
|
+
|
|
32
|
+
Do not broaden:
|
|
33
|
+
* do not move unrelated internal types into contracts,
|
|
34
|
+
* do not add speculative fields for future callers,
|
|
35
|
+
* do not declare the DTO inside a feature layer as a temporary shortcut.
|
|
36
|
+
|
|
37
|
+
Prove:
|
|
38
|
+
* the current behavioral acceptance passes,
|
|
39
|
+
* every affected DTO declaration lives under `contracts/`.
|
|
25
40
|
exceptions:
|
|
26
41
|
- Test files and vendored/build directories are never scanned.
|
|
27
42
|
- Bare npm specifiers resolve outside the project graph and are not layer-checked.
|