@afokapu/atdd-bun 0.10.39 → 0.10.41
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.complexity-cyclomatic.convention.yaml +25 -4
- package/conventions/coder.bun/coder.bun.complexity-length.convention.yaml +26 -1
- package/conventions/coder.bun/coder.bun.complexity-nesting.convention.yaml +24 -4
- 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.dead-code-reachability.convention.yaml +25 -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.duplication-intra-layer.convention.yaml +25 -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.quality-comments.convention.yaml +25 -1
- package/conventions/coder.bun/coder.bun.quality-mi.convention.yaml +25 -1
- 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/integrity.json +51 -50
- 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.
|
|
@@ -26,12 +26,33 @@ content:
|
|
|
26
26
|
normative_text: |
|
|
27
27
|
The obligation and its arithmetic are unchanged from the Python realization — deliberately, because a repo that switches providers must not see its numbers move. What changes is only WHO runs the count.
|
|
28
28
|
Cyclomatic complexity is a proxy for how many test cases a function needs before its behaviour is pinned. Above roughly ten paths, complete coverage stops being written, and the untested paths are where defects settle.
|
|
29
|
+
Treat the score as a sensor for too many independent decisions inside one responsibility, not as an invitation to disguise branching. A useful refactor makes the decision structure easier to name, test, and reason about; moving the same decision tree behind another call or encoding it opaquely only hides the signal.
|
|
29
30
|
fix_hint: |
|
|
30
|
-
|
|
31
|
+
Diagnose which decisions belong together before reducing the score.
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
*
|
|
34
|
-
*
|
|
33
|
+
Diagnose:
|
|
34
|
+
* group branches by the policy or responsibility they implement,
|
|
35
|
+
* distinguish validation and guard conditions from the core operation,
|
|
36
|
+
* identify repeated compound conditions that represent a domain predicate.
|
|
37
|
+
|
|
38
|
+
Prefer:
|
|
39
|
+
* extract a coherent decision or policy into an intention-revealing function,
|
|
40
|
+
* replace repeated compound conditions with well-named predicates,
|
|
41
|
+
* use a dispatch table or strategy only when the domain genuinely represents a stable mapping from a key to behavior,
|
|
42
|
+
* keep the caller's control flow readable enough to reveal the important choices.
|
|
43
|
+
|
|
44
|
+
Avoid:
|
|
45
|
+
* moving the same branch tree unchanged into a generically named helper,
|
|
46
|
+
* replacing readable control flow with indirect data structures solely to lower the measured score,
|
|
47
|
+
* scattering one policy across many tiny functions whose interaction is harder to follow than the original,
|
|
48
|
+
* changing boolean semantics, branch order, or fallback behavior while refactoring.
|
|
49
|
+
|
|
50
|
+
Verify:
|
|
51
|
+
* existing behavior and path-focused tests remain green,
|
|
52
|
+
* the triggering complexity violation is gone,
|
|
53
|
+
* extracted code does not create a new nesting, duplication, or length violation,
|
|
54
|
+
* the resulting decision boundaries correspond to meaningful responsibilities,
|
|
55
|
+
* the refactor introduces no new ATDD Bun violations.
|
|
35
56
|
exceptions:
|
|
36
57
|
- Functions with fewer than 3 code lines are not scored.
|
|
37
58
|
- Test files and vendored/build directories are outside the scan.
|
|
@@ -23,8 +23,33 @@ content:
|
|
|
23
23
|
normative_text: |
|
|
24
24
|
Length is the crudest of the three per-function metrics and the hardest to argue with: a function longer than a screen cannot be read as one unit, so it is read in fragments and its invariants are reconstructed from memory each time.
|
|
25
25
|
It catches a different fault from complexity. A long function may be perfectly linear — fifty sequential assignments score 1 on cyclomatic complexity — and still be doing five things that wanted names.
|
|
26
|
+
Treat the threshold as a sensor for weak cohesion or multiple responsibilities, not as the design objective. A successful refactor identifies a responsibility or cohesive operation that deserves its own name and boundary. Merely moving enough contiguous lines elsewhere to cross the threshold removes the signal without repairing the smell.
|
|
26
27
|
fix_hint: |
|
|
27
|
-
|
|
28
|
+
Diagnose the design problem before changing the code.
|
|
29
|
+
|
|
30
|
+
Diagnose:
|
|
31
|
+
* identify the distinct responsibilities, stages, or invariants managed by the function,
|
|
32
|
+
* look for semantic seams: blocks that can be described by one intention-revealing name,
|
|
33
|
+
* identify the data each candidate responsibility actually needs.
|
|
34
|
+
|
|
35
|
+
Prefer:
|
|
36
|
+
* extract one cohesive responsibility at a time,
|
|
37
|
+
* name helpers after the purpose they perform rather than the mechanics they contain,
|
|
38
|
+
* keep related state and decisions together,
|
|
39
|
+
* leave the original function as a readable description of the top-level flow.
|
|
40
|
+
|
|
41
|
+
Avoid:
|
|
42
|
+
* splitting at an arbitrary line boundary merely to satisfy the 50-line limit,
|
|
43
|
+
* helpers such as `part1`, `processRest`, `buildLinesAndTotal`, or equivalent names that expose extraction mechanics rather than responsibility,
|
|
44
|
+
* moving a long or complex block unchanged into another function,
|
|
45
|
+
* introducing a generalized abstraction unrelated to the responsibility being extracted.
|
|
46
|
+
|
|
47
|
+
Verify:
|
|
48
|
+
* existing behavior and tests remain green,
|
|
49
|
+
* the triggering length violation is gone,
|
|
50
|
+
* extracted functions satisfy the applicable complexity and nesting conventions,
|
|
51
|
+
* the resulting names and boundaries make the responsibilities easier to understand,
|
|
52
|
+
* the refactor introduces no new ATDD Bun violations.
|
|
28
53
|
exceptions:
|
|
29
54
|
- Blank lines and comment lines are not counted.
|
|
30
55
|
- Test files and vendored/build directories are outside the scan.
|
|
@@ -24,12 +24,32 @@ content:
|
|
|
24
24
|
normative_text: |
|
|
25
25
|
Nesting is the metric readers feel most directly: at depth five a reader must hold five simultaneous conditions to know whether a line executes, which is past what working memory does reliably.
|
|
26
26
|
It is also the most mechanically fixable — a guard clause or an extracted helper usually removes a level without changing behaviour, which is why the threshold is enforced rather than advised.
|
|
27
|
+
Treat excessive depth as a sensor for too much conditional context being carried at once. The objective is to make the execution conditions easier to understand, not merely to remove braces or encode the same nesting in expressions the metric counts differently.
|
|
27
28
|
fix_hint: |
|
|
28
|
-
Flatten the control flow
|
|
29
|
+
Flatten the control flow by removing unnecessary conditional context.
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
*
|
|
32
|
-
*
|
|
31
|
+
Diagnose:
|
|
32
|
+
* identify conditions that reject work early and can become guards,
|
|
33
|
+
* identify an inner block that performs one cohesive operation,
|
|
34
|
+
* identify nested iteration that can be expressed as preparation followed by one clear pass.
|
|
35
|
+
|
|
36
|
+
Prefer:
|
|
37
|
+
* invert conditions into early-return guard clauses when doing so preserves cleanup, error, and ordering semantics,
|
|
38
|
+
* extract a cohesive inner operation into a named function with a small, meaningful input,
|
|
39
|
+
* prepare or filter a collection before iterating when that makes the algorithm clearer.
|
|
40
|
+
|
|
41
|
+
Avoid:
|
|
42
|
+
* converting statements into clever boolean or ternary expressions solely to evade the depth count,
|
|
43
|
+
* extracting an inner block that requires a long parameter list or still depends on the caller's hidden conditional context,
|
|
44
|
+
* duplicating cleanup, logging, or error handling across new guard clauses,
|
|
45
|
+
* changing evaluation order or exception behavior while flattening the function.
|
|
46
|
+
|
|
47
|
+
Verify:
|
|
48
|
+
* existing behavior and tests remain green, including error and boundary paths,
|
|
49
|
+
* the triggering nesting violation is gone,
|
|
50
|
+
* the flattened flow reads with fewer simultaneous preconditions,
|
|
51
|
+
* extracted functions satisfy the applicable length and complexity conventions,
|
|
52
|
+
* the refactor introduces no new ATDD Bun violations.
|
|
33
53
|
exceptions:
|
|
34
54
|
- Functions with fewer than 3 code lines are not scored.
|
|
35
55
|
- Comment lines are ignored when measuring brace balance.
|
|
@@ -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.
|
|
@@ -28,8 +28,32 @@ content:
|
|
|
28
28
|
This rule is MORE ACCURATE than its Python sibling, and the difference is worth stating because it is the one place the port is not a transcription.
|
|
29
29
|
The Python detector reads imports with five regexes — the best a Python process can do without a TypeScript parser. A regex cannot distinguish `import type { T } from "./t"` from a value import, so a module whose only referrer is a TYPE import is counted as reachable. But a type-only import is erased at compile time and creates no runtime edge, so that module is dead and the regex reports it alive.
|
|
30
30
|
Bun ships a real TypeScript parser in-process, which returns the actual import records and omits type-only ones. Same obligation, measured correctly — and available only because the runtime is Bun. Verified on a fixture where the Python detector finds one dead file and this one finds two.
|
|
31
|
+
Treat an unreachable file as a sensor for unclear ownership or incomplete integration, not as a request to manufacture an import edge. A meaningful repair either removes code that has no runtime responsibility or connects code through the module that genuinely owns and uses it.
|
|
31
32
|
fix_hint: |
|
|
32
|
-
|
|
33
|
+
Decide first whether the reported file should exist at runtime.
|
|
34
|
+
|
|
35
|
+
Diagnose:
|
|
36
|
+
* identify the responsibility the file claims to own,
|
|
37
|
+
* find the module that would naturally call or import it if that responsibility is required,
|
|
38
|
+
* determine whether the file is obsolete, incompletely integrated, or only carrying types.
|
|
39
|
+
|
|
40
|
+
Prefer:
|
|
41
|
+
* delete code that is genuinely unused,
|
|
42
|
+
* wire required runtime behavior through the module that owns that behavior,
|
|
43
|
+
* move a type into the module that uses it when the remaining file has no runtime values.
|
|
44
|
+
|
|
45
|
+
Avoid:
|
|
46
|
+
* adding a dummy import, barrel export, or other synthetic edge solely to make the file reachable,
|
|
47
|
+
* introducing a side-effect import unless the side effect is itself required runtime behavior,
|
|
48
|
+
* renaming or relocating a file merely to exploit structural-root detection,
|
|
49
|
+
* preserving obsolete code "just in case" instead of removing it.
|
|
50
|
+
|
|
51
|
+
Verify:
|
|
52
|
+
* existing behavior and tests remain green,
|
|
53
|
+
* any new import represents a real runtime dependency,
|
|
54
|
+
* deleted code has no required caller or entry point,
|
|
55
|
+
* the reachability finding is gone without creating a new architecture or dependency-flow violation,
|
|
56
|
+
* the refactor introduces no new ATDD Bun violations.
|
|
33
57
|
exceptions:
|
|
34
58
|
- "`index.ts` / `index.tsx` are structural (like `__init__.py`) and are never reported."
|
|
35
59
|
- Test files are entrypoints, not dead code, and are excluded.
|
|
@@ -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.
|