@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.
Files changed (59) hide show
  1. package/conventions/_profiles/coder.yaml +72 -0
  2. package/conventions/_profiles/metrics.yaml +70 -0
  3. package/conventions/coder.bun/coder.bun.boundaries-http-client.convention.yaml +17 -1
  4. package/conventions/coder.bun/coder.bun.commons-application-no-integration.convention.yaml +17 -1
  5. package/conventions/coder.bun/coder.bun.commons-cross-feature-imports-in.convention.yaml +16 -1
  6. package/conventions/coder.bun/coder.bun.commons-domain-no-framework-import.convention.yaml +17 -1
  7. package/conventions/coder.bun/coder.bun.commons-domain-no-outbound.convention.yaml +17 -1
  8. package/conventions/coder.bun/coder.bun.composition-consumer.convention.yaml +16 -1
  9. package/conventions/coder.bun/coder.bun.composition-root.convention.yaml +17 -1
  10. package/conventions/coder.bun/coder.bun.design-connected.convention.yaml +17 -1
  11. package/conventions/coder.bun/coder.bun.design-dependency-flow.convention.yaml +17 -2
  12. package/conventions/coder.bun/coder.bun.design-hierarchy-import.convention.yaml +17 -1
  13. package/conventions/coder.bun/coder.bun.design-orphan-export.convention.yaml +17 -2
  14. package/conventions/coder.bun/coder.bun.design-primitives.convention.yaml +17 -2
  15. package/conventions/coder.bun/coder.bun.design-token-color.convention.yaml +17 -1
  16. package/conventions/coder.bun/coder.bun.design-token-hardcoded.convention.yaml +17 -2
  17. package/conventions/coder.bun/coder.bun.design-tokens-pure.convention.yaml +18 -2
  18. package/conventions/coder.bun/coder.bun.design-wagons-import.convention.yaml +18 -2
  19. package/conventions/coder.bun/coder.bun.dto-mapper.convention.yaml +16 -1
  20. package/conventions/coder.bun/coder.bun.dto-placement.convention.yaml +16 -1
  21. package/conventions/coder.bun/coder.bun.dto-purity.convention.yaml +17 -1
  22. package/conventions/coder.bun/coder.bun.green-header-order.convention.yaml +15 -7
  23. package/conventions/coder.bun/coder.bun.green-header-purpose.convention.yaml +16 -5
  24. package/conventions/coder.bun/coder.bun.green-header-runtime.convention.yaml +15 -6
  25. package/conventions/coder.bun/coder.bun.green-header-tested-by.convention.yaml +16 -11
  26. package/conventions/coder.bun/coder.bun.green-urn-layer.convention.yaml +16 -4
  27. package/conventions/coder.bun/coder.bun.green-urn-marker.convention.yaml +16 -9
  28. package/conventions/coder.bun/coder.bun.green-urn-name-matches.convention.yaml +16 -5
  29. package/conventions/coder.bun/coder.bun.green-urn-pattern.convention.yaml +16 -4
  30. package/conventions/coder.bun/coder.bun.green-urn-side.convention.yaml +15 -6
  31. package/conventions/coder.bun/coder.bun.green-urn-wagon-feature.convention.yaml +15 -6
  32. package/conventions/coder.bun/coder.bun.layer-naming.convention.yaml +16 -1
  33. package/conventions/coder.bun/coder.bun.phase-discipline.convention.yaml +111 -0
  34. package/conventions/coder.bun/coder.bun.responsive-breakpoints-declared.convention.yaml +17 -2
  35. package/conventions/coder.bun/coder.bun.responsive-no-fixed-width.convention.yaml +17 -1
  36. package/conventions/coder.bun/coder.bun.responsive-viewport-meta.convention.yaml +16 -1
  37. package/conventions/coder.bun/coder.bun.runtime-server-is-bun-serve.convention.yaml +16 -13
  38. package/conventions/coder.bun/coder.bun.runtime-single-lockfile.convention.yaml +16 -6
  39. package/conventions/coder.bun/coder.bun.runtime-typecheck-enforced.convention.yaml +16 -9
  40. package/conventions/tester.bun/tester.bun.acceptance-binding-declared.convention.yaml +20 -4
  41. package/conventions/tester.bun/tester.bun.acceptance-covers-tag-well-formed.convention.yaml +11 -5
  42. package/conventions/tester.bun/tester.bun.acceptance-resolves-to-declared.convention.yaml +23 -20
  43. package/conventions/tester.bun/tester.bun.interlocking-production-runner-used.convention.yaml +29 -7
  44. package/conventions/tester.bun/tester.bun.interlocking-route-coverage.convention.yaml +35 -10
  45. package/conventions/tester.bun/tester.bun.red-behavioral-assertion.convention.yaml +39 -5
  46. package/conventions/tester.bun/tester.bun.red-fails-first.convention.yaml +24 -7
  47. package/conventions/tester.bun/tester.bun.security-auth.convention.yaml +19 -1
  48. package/conventions/tester.bun/tester.bun.security-input.convention.yaml +19 -1
  49. package/conventions/tester.bun/tester.bun.smoke-no-collaborator-substitution.convention.yaml +21 -1
  50. package/conventions/tester.bun/tester.bun.smoke-observable-assertion.convention.yaml +23 -6
  51. package/conventions/tester.bun/tester.bun.test-phase-declared.convention.yaml +9 -3
  52. package/conventions/tester.htmx/tester.htmx.e2e-binds-declared-subject.convention.yaml +20 -3
  53. package/conventions/tester.htmx/tester.htmx.train-e2e-coverage.convention.yaml +24 -3
  54. package/integrity.json +58 -57
  55. package/package.json +1 -1
  56. package/relationships.yaml +71 -0
  57. package/src/enforce.ts +2 -2
  58. package/src/profile-registry.ts +4 -2
  59. package/templates/agents/AGENTS.block.md +2 -0
@@ -22,7 +22,23 @@ content:
22
22
  A DTO is the shape crossing a boundary. A method on it means behaviour crossed too, and the two sides are now coupled to an implementation rather than to data. A mutable field means the receiver can change what the sender said.
23
23
  Both faults look harmless in one file and become impossible to unpick once a second consumer exists.
24
24
  fix_hint: |
25
- Strip methods to free functions in the layer that needs them, and mark every field `readonly`.
25
+ Canonical path:
26
+ * keep DTOs as immutable data: readonly fields and no methods,
27
+ * put behavior in the layer that consumes or produces the DTO.
28
+
29
+ During GREEN:
30
+ * add only the readonly data fields required by the current boundary behavior,
31
+ * reuse existing functions for transformation or behavior when available,
32
+ * add a small free function only when the current acceptance needs it.
33
+
34
+ Do not broaden:
35
+ * do not attach convenience methods to the DTO,
36
+ * do not make fields mutable to simplify implementation,
37
+ * do not introduce unrelated helpers or abstractions.
38
+
39
+ Prove:
40
+ * the current behavioral acceptance passes,
41
+ * the affected DTO remains pure immutable data.
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.
@@ -25,13 +25,21 @@ content:
25
25
  The order is the same in Python, Vite and here, and its value is that a reader — human or tool — knows where to look without parsing. Identity first, then proof, then execution context, then intent: each field answers the question the previous one raises.
26
26
  The rule judges only fields that are present, so it never double-reports a missing field that another rule already owns.
27
27
  fix_hint: |
28
- Order the fields URN -> Tested-By -> Runtime -> Purpose:
29
-
30
- // URN: component:orders:checkout:OrderRow:backend:presentation
31
- // Tested-By:
32
- // - test:orders:checkout:E001-SMOKE-001-renders-row
33
- // Runtime: bun
34
- // Purpose: render one order row fragment for htmx to swap
28
+ Canonical path:
29
+ * order present traceability fields as URN -> Tested-By -> Runtime -> Purpose.
30
+
31
+ During GREEN:
32
+ * keep the existing field values unless another convention proves one is wrong,
33
+ * reorder only the header lines needed to restore the canonical sequence,
34
+ * preserve unrelated comments.
35
+
36
+ Do not broaden:
37
+ * do not rewrite identifiers, acceptance bindings, runtime, or purpose merely while fixing order,
38
+ * do not move implementation code to satisfy a header-order finding.
39
+
40
+ Prove:
41
+ * the current behavioral acceptance still passes,
42
+ * the present header fields appear in canonical order.
35
43
  exceptions:
36
44
  - Files with no URN are skipped — there is nothing to order against.
37
45
  - Fields that are absent are not considered; presence is each field's own rule.
@@ -21,11 +21,22 @@ content:
21
21
  normative_text: |
22
22
  The 80-character cap is the whole rule. An unbounded field becomes a paragraph, a paragraph goes stale, and a stale paragraph is worse than no description because it is believed. A single line that must fit forces the author to name the file's one job — and a file whose job will not fit in 80 characters is usually a file doing more than one thing, which makes this a design signal as much as a documentation rule.
23
23
  fix_hint: |
24
- State the one job in a single line:
25
-
26
- // Purpose: render one order row fragment for htmx to swap
27
-
28
- If it will not fit, that is evidence the file has more than one responsibility; split it rather than expanding the line.
24
+ Canonical path:
25
+ * state the file's one actual job in a single `Purpose:` line of at most 80 characters.
26
+
27
+ During GREEN:
28
+ * derive the purpose from the responsibility introduced for the current acceptance,
29
+ * use concrete responsibility language rather than implementation mechanics,
30
+ * if the purpose genuinely cannot fit because the new file owns multiple jobs, split only the responsibilities required by the current behavior.
31
+
32
+ Do not broaden:
33
+ * do not invent a vague purpose just to meet the length cap,
34
+ * do not perform unrelated decomposition,
35
+ * do not describe hypothetical future responsibilities.
36
+
37
+ Prove:
38
+ * the current behavioral acceptance passes,
39
+ * the purpose truthfully names one job and fits the limit.
29
40
  exceptions:
30
41
  - Exactly 80 characters passes; 81 does not.
31
42
  - A missing description is reported at the URN line.
@@ -22,12 +22,21 @@ content:
22
22
  normative_text: |
23
23
  `isomorphic` has no Vite counterpart and is the substantive addition. A bundler stack decides at BUILD time which code reaches the browser, so a file is server or client by where the bundler puts it. Bun decides at RUN time, and a full-stack Bun app routinely runs one module in both places — a fragment renderer used server-side and again after a client-side swap. Without a value for that, authors would be forced to pick a wrong one, and every downstream reader would inherit the error.
24
24
  fix_hint: |
25
- Declare the runtime the file actually executes in:
26
-
27
- // Runtime: deno // ✗ not this stack
28
- // Runtime: bun // ✓ server-side
29
- // Runtime: browser // ✓ ships to the client
30
- // Runtime: isomorphic // ✓ genuinely runs in both
25
+ Canonical path:
26
+ * declare the runtime where the file actually executes: `bun`, `browser`, or `isomorphic`.
27
+
28
+ During GREEN:
29
+ * derive the value from the real execution path created or used by the current acceptance,
30
+ * keep an existing correct runtime declaration,
31
+ * change only the header when the implementation already executes in the correct place.
32
+
33
+ Do not broaden:
34
+ * do not move code between server and browser merely to fit a preferred label,
35
+ * do not guess `isomorphic` because the file could theoretically run in both places.
36
+
37
+ Prove:
38
+ * the current behavioral acceptance passes in its real runtime,
39
+ * the declaration matches where the file actually executes.
31
40
  exceptions:
32
41
  - A missing declaration is reported at the URN line (or the first meaningful line when there is no URN).
33
42
  - Test files are excluded.
@@ -23,17 +23,22 @@ content:
23
23
  This is the rule that makes the whole header load-bearing rather than decorative. The URN says what the file IS; `Tested-By:` says what PROVES it. Together they close the loop from acceptance to implementation that ATDD exists to keep closed — which is exactly the loop that a stack migration breaks silently, because the new files are written without headers and nothing notices.
24
24
  An empty block is treated as absent deliberately: it is the shape a half-finished backfill leaves behind, and accepting it would let a repo report full header coverage with zero acceptance bindings.
25
25
  fix_hint: |
26
- Name at least one acceptance:
27
-
28
- // Tested-By:
29
- // - test:orders:checkout:E001-SMOKE-001-renders-row
30
-
31
- and in a template:
32
-
33
- <!-- Tested-By: -->
34
- <!-- - test:orders:checkout:E001-SMOKE-002-panel-loads -->
35
-
36
- Whether the named acceptances EXIST is a plan-graph question this rule cannot answer; it enforces that the binding is declared.
26
+ Canonical path:
27
+ * bind the implementation file to at least one real acceptance URN in its `Tested-By:` block.
28
+
29
+ During GREEN:
30
+ * derive the binding from the acceptance currently being implemented,
31
+ * keep existing valid bindings and add only the acceptance that genuinely covers this file,
32
+ * use the exact declared acceptance URN.
33
+
34
+ Do not broaden:
35
+ * do not invent acceptance IDs,
36
+ * do not add unrelated tests merely to make the block non-empty,
37
+ * do not claim coverage from an acceptance that does not exercise the implementation.
38
+
39
+ Prove:
40
+ * the named behavioral acceptance passes,
41
+ * the file's `Tested-By:` block names the acceptance that actually proves it.
37
42
  exceptions:
38
43
  - Test files are excluded — they are the other end of this binding.
39
44
  - One entry satisfies the rule; more are encouraged.
@@ -21,10 +21,22 @@ content:
21
21
  normative_text: |
22
22
  The layer segment is what the boundary and dependency-flow rules read to decide whether an import is legal. A file declaring a layer outside the vocabulary is not merely mislabelled — it is unreachable by every layering rule, so it becomes a hole through which any dependency may pass unchallenged.
23
23
  fix_hint: |
24
- Use a layer from the vocabulary:
25
-
26
- // URN: component:orders:checkout:OrderRow:backend:widgets // ✗
27
- // URN: component:orders:checkout:OrderRow:backend:presentation // ✓
24
+ Canonical path:
25
+ * declare one of `domain`, `application`, `integration`, `presentation`, or `assembly` according to the file's real responsibility.
26
+
27
+ During GREEN:
28
+ * derive the layer from the existing architecture and the responsibility required by the current acceptance,
29
+ * follow the nearest existing compliant feature pattern,
30
+ * if the file is actually misplaced, move only the affected implementation to its proper layer.
31
+
32
+ Do not broaden:
33
+ * do not invent a new layer,
34
+ * do not relabel a misplaced module to make dependency checks disappear,
35
+ * do not reorganize adjacent features.
36
+
37
+ Prove:
38
+ * the current behavioral acceptance passes,
39
+ * the URN layer matches the implementation's actual architectural layer.
28
40
  exceptions:
29
41
  - URNs that are not six segments are skipped.
30
42
  - The vocabulary is fixed by core, not by this extension; a new layer is a core change.
@@ -28,15 +28,22 @@ content:
28
28
  The URN is the only edge between a source file and the plan graph. Without it a file is invisible to traceability: no acceptance can claim it, no wagon owns it, and coverage reporting cannot see it exists.
29
29
  "First meaningful line" excludes a shebang (`#!/usr/bin/env bun`) and an HTML doctype, because neither is content and neither should be able to displace the marker. The Vite sibling counts a shebang as the first non-empty line and so reports a header it actually has as missing; this realization does not.
30
30
  fix_hint: |
31
- Put the marker on the first meaningful line:
32
-
33
- // URN: component:orders:checkout:OrderRow:backend:presentation
34
-
35
- and in a template:
36
-
37
- <!doctype html>
38
- <!-- URN: component:orders:checkout:OrderPanel:frontend:presentation -->
39
-
31
+ Canonical path:
32
+ * put the component URN on the first meaningful line, after only an allowed shebang or HTML doctype.
33
+
34
+ During GREEN:
35
+ * derive the URN from the plan ownership of the implementation being added,
36
+ * use source-comment syntax for code and HTML-comment syntax for templates,
37
+ * add only the marker; do not restructure the file when the implementation is otherwise correctly placed.
38
+
39
+ Do not broaden:
40
+ * do not invent a wagon, feature, component, side, or layer,
41
+ * do not copy a nearby file's URN without verifying ownership,
42
+ * do not move code merely to make the marker easier to write.
43
+
44
+ Prove:
45
+ * the current behavioral acceptance passes,
46
+ * the file is traceable from its real component URN.
40
47
  exceptions:
41
48
  - Test files (`*.test.*`, `*.spec.*`) are excluded — they are bound by their acceptance URNs instead.
42
49
  - Vendored and generated trees (`node_modules`, `dist`, `build`, `_generated`) are never scanned.
@@ -23,11 +23,22 @@ content:
23
23
  A URN naming a different component than the file it sits in is worse than a missing one: it binds the file's evidence to somebody else's component, so both are wrong and neither is obviously wrong. This is the failure a copy-pasted header produces, which is how it usually arises.
24
24
  The exempt set is the Vite set plus this stack's idioms — `server`, `routes`, `layout`, `partial`, `fragment`, `middleware` — because a full-stack Bun app's entrypoint is `server.ts` and its htmx fragments are named for their role, not for a component.
25
25
  fix_hint: |
26
- Make the name segment agree with the filename, or use a structural role name:
27
-
28
- // in OrderRow.ts
29
- // URN: component:orders:checkout:SomethingElse:backend:presentation // ✗
30
- // URN: component:orders:checkout:OrderRow:backend:presentation // ✓
26
+ Canonical path:
27
+ * make the URN `{Name}` identify the component implemented by the file and match its basename under the rule's normalization, unless the file has an exempt structural role.
28
+
29
+ During GREEN:
30
+ * derive the name from the actual file/component being implemented,
31
+ * correct a copied or stale header before considering a file rename,
32
+ * keep structural-role filenames as structural roles when that is their real responsibility.
33
+
34
+ Do not broaden:
35
+ * do not rename a correctly named component merely to preserve a wrong URN,
36
+ * do not use an exempt structural name to evade component identity,
37
+ * do not change unrelated identity segments.
38
+
39
+ Prove:
40
+ * the current behavioral acceptance passes,
41
+ * the URN name and implementation identity agree.
31
42
  exceptions:
32
43
  - 'Structural names are exempt: composition, wagon, entrypoint, http, index, schema, router, routes, server, layout, partial, fragment, middleware.'
33
44
  - Comparison ignores case and non-alphanumerics, so `order-row.ts` matches `OrderRow`.
@@ -24,10 +24,22 @@ content:
24
24
  normative_text: |
25
25
  Each segment is a join key. Wagon and feature locate the work item, name identifies the component, side and layer place it in the architecture. A URN missing a segment does not degrade gracefully — it resolves to nothing, and the file is as unbound as one with no marker at all, while LOOKING traceable in review.
26
26
  fix_hint: |
27
- Supply every segment:
28
-
29
- // URN: component:orders:checkout:OrderRow // ✗ four segments
30
- // URN: component:orders:checkout:OrderRow:backend:presentation // ✓
27
+ Canonical path:
28
+ * use exactly `component:{wagon}:{feature}:{Name}:{side}:{layer}` with every segment present.
29
+
30
+ During GREEN:
31
+ * derive each segment from the plan, filename, execution side, and architectural responsibility,
32
+ * fix only the malformed or missing segment,
33
+ * keep already-correct identity segments unchanged.
34
+
35
+ Do not broaden:
36
+ * do not invent placeholder segments,
37
+ * do not rename implementation artifacts solely to make a guessed URN fit,
38
+ * do not alter plan ownership while fixing URN grammar.
39
+
40
+ Prove:
41
+ * the current behavioral acceptance passes,
42
+ * the URN has the canonical six-segment shape.
31
43
  exceptions:
32
44
  - A file with no `URN:` marker is skipped (owned by `green-urn-marker`).
33
45
  - Segment CONTENT is validated by the wagon-feature, name, side and layer rules; this rule checks shape only.
@@ -20,12 +20,21 @@ content:
20
20
  normative_text: |
21
21
  The vocabulary is unchanged from the Python and Vite realizations, and it matters MORE in a full-stack Bun app than in either. A Vite repo is frontend by construction and a python-pytest service is backend by construction, so the segment is close to redundant there. Here one repo, one language and one runtime span both halves, and the only thing that says which side a module belongs to is this segment — so it must be declared per file and cannot be inferred from the stack.
22
22
  fix_hint: |
23
- Declare the side explicitly:
24
-
25
- // URN: component:orders:checkout:OrderRow:server:presentation // ✗ not a side
26
- // URN: component:orders:checkout:OrderRow:backend:presentation // ✓
27
-
28
- Server-rendered htmx fragments are `backend` (they are produced by the server); markup and behaviour that live in the browser are `frontend`.
23
+ Canonical path:
24
+ * declare `frontend` for browser-owned implementation and `backend` for server-owned implementation.
25
+
26
+ During GREEN:
27
+ * derive side from where responsibility lives, not merely from file syntax,
28
+ * treat server-rendered htmx fragments as backend and browser-resident behavior as frontend,
29
+ * change only the side segment when the rest of the URN is correct.
30
+
31
+ Do not broaden:
32
+ * do not move implementation between client and server just to fix a header,
33
+ * do not use `Runtime:` as a substitute for the side decision.
34
+
35
+ Prove:
36
+ * the current behavioral acceptance passes,
37
+ * the side segment matches the implementation's real ownership.
29
38
  exceptions:
30
39
  - URNs that are not six segments are skipped.
31
40
  - "`Runtime:` is a different axis — a `backend` file may declare `Runtime: isomorphic`."
@@ -22,12 +22,21 @@ content:
22
22
  normative_text: |
23
23
  Wagon and feature are join keys into `plan/`, and a join key that is case- or separator-sensitive fails silently: `Orders` and `orders` are two different wagons to a string match, so a header with the wrong casing binds to nothing while reading correctly to a human. Kebab-case is the plan's own grammar, so the header must use it exactly.
24
24
  fix_hint: |
25
- Lower-case and hyphenate:
26
-
27
- // URN: component:Orders:Check_Out:OrderRow:backend:presentation // ✗
28
- // URN: component:orders:check-out:OrderRow:backend:presentation // ✓
29
-
30
- The `{Name}` segment is deliberately NOT kebab — it mirrors the filename and keeps its own casing.
25
+ Canonical path:
26
+ * use the exact plan wagon and feature identifiers in lowercase kebab-case.
27
+
28
+ During GREEN:
29
+ * derive both values from the feature currently being implemented,
30
+ * normalize only casing or separators when the identity is already correct,
31
+ * keep the component name, side, and layer untouched.
32
+
33
+ Do not broaden:
34
+ * do not invent or rename plan wagons/features to satisfy the source header,
35
+ * do not copy identifiers from a neighboring feature without checking ownership.
36
+
37
+ Prove:
38
+ * the current behavioral acceptance passes,
39
+ * wagon and feature segments match the plan's canonical identifiers.
31
40
  exceptions:
32
41
  - URNs that are not six well-formed segments are skipped (owned by `green-urn-pattern`).
33
42
  - The name, side and layer segments are governed by their own rules.
@@ -23,7 +23,22 @@ content:
23
23
  ADDED TO THE MIRROR, and worth flagging: the Convex sibling accepts only the FILENAME form, because its function tree is flat. A full-stack Bun repo commonly nests (`features/orders/domain/total.ts`), so accepting only filenames would refuse the idiomatic layout. This realization accepts BOTH.
24
24
  The obligation is unchanged: a reader should know a file's role before opening it, and the layering rules need something to read.
25
25
  fix_hint: |
26
- Either rename the file to its layer, or move it into the layer directory it belongs to.
26
+ Canonical path:
27
+ * place the module in the architectural layer that owns its responsibility, or name the file with that layer when the repository uses the filename form.
28
+
29
+ During GREEN:
30
+ * derive the layer from the responsibility the current behavior actually implements,
31
+ * follow the nearest existing feature layout,
32
+ * move or rename only the affected module when placement is wrong.
33
+
34
+ Do not broaden:
35
+ * do not reorganize sibling features,
36
+ * do not invent a new layer name,
37
+ * do not choose a layer merely to make another import rule pass.
38
+
39
+ Prove:
40
+ * the current behavioral acceptance passes,
41
+ * the file's declared location or name matches its actual architectural responsibility.
27
42
  exceptions:
28
43
  - Test files and vendored/build directories are never scanned.
29
44
  - Bare npm specifiers resolve outside the project graph and are not layer-checked.
@@ -0,0 +1,111 @@
1
+ schema_version: 1.1.0
2
+ rule_id: coder.bun.phase-discipline
3
+ kind: policy
4
+ status: active
5
+ name: GREEN establishes behavior before REFACTOR optimizes design
6
+ statement: >-
7
+ During governed coding work, GREEN MUST target the smallest correct implementation that makes the current
8
+ behavioral acceptance pass while respecting active construction constraints. REFACTOR begins only after
9
+ behavioral GREEN and uses quality findings as design sensors. Phase ordering never waives strict
10
+ enforcement: review-ready work MUST pass all active profiles.
11
+ terms:
12
+ - term_id: behavioral_green
13
+ text: >-
14
+ the point where the current RED behavioral acceptance passes against the implementation. It proves the
15
+ requested behavior exists; it is not yet the end of the coding loop.
16
+ - term_id: construction_constraint
17
+ text: >-
18
+ a rule that constrains what counts as a legal implementation while behavior is being discovered:
19
+ traceability and topology, architecture and dependency direction, runtime, design-system and responsive
20
+ boundaries, plus every other active non-refactor profile such as security.
21
+ - term_id: refactor_sensor
22
+ text: >-
23
+ a quality finding whose metric is evidence of a design smell rather than the design objective itself.
24
+ In the Bun coder profile these are the seven bun_ts_metrics_detector rules: complexity-cyclomatic,
25
+ complexity-length, complexity-nesting, dead-code-reachability, duplication-intra-layer,
26
+ quality-comments, and quality-mi.
27
+ - term_id: review_ready
28
+ text: >-
29
+ the point after behavioral GREEN and REFACTOR when the required behavior still passes and all active
30
+ ATDD Bun profiles are green. Only this state is completion.
31
+ content:
32
+ summary: >-
33
+ Keep GREEN and REFACTOR as different search problems without changing enforcement. GREEN finds the
34
+ smallest legal implementation of the required behavior; REFACTOR then uses the seven metrics findings
35
+ as guided design sensors while preserving that behavior.
36
+ normative_text: |
37
+ The `green-*` rule prefix is a traceability family name, not a phase assignment. Those conventions
38
+ declare implementation identity, proof, runtime, purpose, side and layer; they stay where they are and
39
+ remain construction constraints during GREEN.
40
+
41
+ GREEN starts from one failing behavioral acceptance. Its objective is the smallest correct implementation
42
+ that makes that acceptance pass while respecting the active system constraints. Reuse existing contracts,
43
+ components, dependencies and patterns. Add only the boundary or abstraction the current behavior actually
44
+ needs. Do not redesign adjacent systems, generalize for hypothetical callers, or perform unrelated cleanup
45
+ while behavior is still being discovered.
46
+
47
+ Within the coder profile, the construction-constraint families are the rules emitted by
48
+ `atdd_topology`, `bun_green_traceability_detector`, `bun_clean_architecture_detector`,
49
+ `bun_fullstack_detector`, `bun_design_system_detector`, and `bun_responsive_detector`. They constrain the
50
+ solution during GREEN; they are not debts to knowingly violate and repair later. Other active profiles,
51
+ especially tester, traceability and security, remain equally binding.
52
+
53
+ The refactor-sensor family is `bun_ts_metrics_detector`:
54
+ * coder.bun.complexity-cyclomatic
55
+ * coder.bun.complexity-length
56
+ * coder.bun.complexity-nesting
57
+ * coder.bun.dead-code-reachability
58
+ * coder.bun.duplication-intra-layer
59
+ * coder.bun.quality-comments
60
+ * coder.bun.quality-mi
61
+
62
+ These sensors may run at any time and remain strict. The phase distinction changes the agent's response,
63
+ not the validator. While the acceptance is still red, do not broaden the implementation merely to optimize
64
+ a quality metric and do not game a finding. Prefer a naturally simple implementation, but keep the search
65
+ objective on the missing behavior. Once the acceptance first passes, hold behavior fixed and use each
66
+ sensor's smell-specific Diagnose / Prefer / Avoid / Verify guidance to improve the design.
67
+
68
+ `dead-code-reachability` is the one sensor that can expose a false GREEN: a unit-level acceptance can pass
69
+ against code that no production root can reach. When the finding applies to the newly implemented behavior,
70
+ wire it through the real owner before treating the behavior as complete; never manufacture an import edge.
71
+
72
+ GREEN is therefore not permission to write deliberately poor code, and REFACTOR is not permission to add
73
+ behavior. The intended loop is RED -> smallest legal behavioral GREEN -> guided REFACTOR -> full-profile
74
+ proof. A task is not review-ready until the target behavior still passes and every active strict finding is
75
+ cleared.
76
+ fix_hint: |
77
+ During GREEN:
78
+ * start from the current failing behavioral acceptance,
79
+ * derive traceability metadata from the plan and the acceptance rather than inventing it,
80
+ * reuse the nearest existing compliant pattern, contract and dependency,
81
+ * implement the smallest path that makes the required behavior pass,
82
+ * introduce a new boundary only when no existing compliant path can express the behavior,
83
+ * stop expanding scope once the behavior passes and the construction constraints are satisfied.
84
+
85
+ During REFACTOR:
86
+ * keep the now-green behavior fixed,
87
+ * address the seven refactor sensors one finding at a time,
88
+ * follow the finding's smell-specific Diagnose / Prefer / Avoid / Verify guidance,
89
+ * reject metric gaming and unrelated redesign.
90
+
91
+ Before review:
92
+ * rerun the behavioral proof,
93
+ * run the applicable ATDD Bun profiles,
94
+ * correct every strict finding caused by or exposed by the work.
95
+ exceptions:
96
+ - >-
97
+ A narrow structural change may precede behavioral GREEN when the existing design makes the required
98
+ behavior impossible to implement correctly. Preserve already-proven behavior and change only the verified
99
+ blocker.
100
+ - >-
101
+ Phase ordering never suppresses a validator, weakens a threshold, or permits a security, architecture,
102
+ runtime, traceability or other active constraint to remain violated in review-ready work.
103
+ - >-
104
+ If a refactor sensor is already satisfied by the smallest correct implementation, keep that result; do not
105
+ force a violation merely to preserve a ceremonial phase boundary.
106
+ metadata:
107
+ aliases:
108
+ - BUN-CODER-PHASE-DISCIPLINE-001
109
+ introduced_in: 0.10.10
110
+ implementation:
111
+ type: none
@@ -16,8 +16,23 @@ content:
16
16
  normative_text: CSS custom properties cannot be used in media queries, so breakpoints cannot be tokens. Declaring
17
17
  them once and requiring every query to use them keeps layouts switching at the same widths everywhere instead
18
18
  of at a new one per component.
19
- fix_hint: 'Use `@media (min-width: 768px)`, or add the width to `frontend.breakpoints` if the design system really
20
- needs it.'
19
+ fix_hint: |
20
+ Canonical path:
21
+ * use only widths declared in `frontend.breakpoints` for media-query conditions.
22
+
23
+ During GREEN:
24
+ * reuse an existing breakpoint that expresses the required layout transition,
25
+ * add one breakpoint only when the current design genuinely requires a distinct transition width,
26
+ * change only the affected media query or configuration entry.
27
+
28
+ Do not broaden:
29
+ * do not add speculative breakpoints for future devices,
30
+ * do not normalize unrelated responsive rules,
31
+ * do not use an undeclared one-off width as a shortcut.
32
+
33
+ Prove:
34
+ * the current responsive acceptance passes at the relevant viewports,
35
+ * every affected media-query width is declared.
21
36
  exceptions:
22
37
  - Vendored and generated trees (`node_modules`, `dist`, `build`, `_generated`) are never scanned.
23
38
  metadata:
@@ -14,7 +14,23 @@ content:
14
14
  summary: No width or min-width wider than the smallest viewport.
15
15
  normative_text: An element wider than the screen forces horizontal scrolling on every phone. Wide layouts are
16
16
  expressed with `max-width`, percentages, or layouts that wrap.
17
- fix_hint: 'Replace `width: 960px` with `width: 100%; max-width: 960px`.'
17
+ fix_hint: |
18
+ Canonical path:
19
+ * make content fluid at small viewports, usually with `width: 100%` plus an appropriate `max-width` rather than an oversized fixed `width` or `min-width`.
20
+
21
+ During GREEN:
22
+ * fix only the element responsible for the current overflow,
23
+ * reuse existing layout containers and responsive primitives,
24
+ * preserve the intended large-screen cap while allowing the element to shrink.
25
+
26
+ Do not broaden:
27
+ * do not redesign unrelated layout,
28
+ * do not hide overflow to mask an oversized element,
29
+ * do not remove useful max-width constraints merely to pass the detector.
30
+
31
+ Prove:
32
+ * the current responsive acceptance passes at the smallest governed viewport,
33
+ * the affected declaration no longer forces horizontal overflow.
18
34
  exceptions:
19
35
  - Vendored and generated trees (`node_modules`, `dist`, `build`, `_generated`) are never scanned.
20
36
  - '`max-width` is not judged; it is how wide layouts are meant to be bounded.'
@@ -14,7 +14,22 @@ content:
14
14
  summary: Every HTML document declares a device-width viewport and allows zoom.
15
15
  normative_text: Without a device-width viewport a phone renders the page as a zoomed-out desktop layout, whatever
16
16
  the CSS says. Blocking zoom fails users who need to enlarge text, which is also an accessibility failure.
17
- fix_hint: '`<meta name="viewport" content="width=device-width, initial-scale=1">`'
17
+ fix_hint: |
18
+ Canonical path:
19
+ * declare `<meta name="viewport" content="width=device-width, initial-scale=1">` in each full HTML document and keep zoom available.
20
+
21
+ During GREEN:
22
+ * add or correct the single viewport declaration in the document/layout that serves the current behavior,
23
+ * reuse the existing shared layout when one owns the document head.
24
+
25
+ Do not broaden:
26
+ * do not duplicate viewport tags across fragments,
27
+ * do not disable zoom with `user-scalable=no` or restrictive scale limits,
28
+ * do not restructure unrelated head markup.
29
+
30
+ Prove:
31
+ * the current browser acceptance passes,
32
+ * the full document declares device width and permits zoom.
18
33
  exceptions:
19
34
  - Vendored and generated trees (`node_modules`, `dist`, `build`, `_generated`) are never scanned.
20
35
  - HTML fragments that are not full documents (no `<html>`) are out of scope.
@@ -35,19 +35,22 @@ content:
35
35
  HTML transformer available only through the Bun server, and it is the natural place to assemble and
36
36
  post-process fragments.
37
37
  fix_hint: |
38
- Replace the framework server with the native one:
39
-
40
- const app = express(); // ✗ node-compat path
41
- app.get("/orders", (req, res) => …);
42
- app.listen(3000);
43
-
44
- Bun.serve({ // ✓ native
45
- port: 3000,
46
- routes: { "/orders": (req) => new Response(renderOrders(), htmlHeaders) },
47
- });
48
-
49
- Middleware becomes plain function composition around the handler. `strict` — the rule exists to
50
- hold the stack decision, so it is not suppressible.
38
+ Canonical path:
39
+ * serve HTTP with `Bun.serve` and express middleware behavior as ordinary function composition around handlers.
40
+
41
+ During GREEN:
42
+ * add only the route, handler, or middleware composition required by the current acceptance,
43
+ * reuse the existing `Bun.serve` instance and routing pattern,
44
+ * when replacing a forbidden framework in new work, migrate only the path required to make the behavior correct.
45
+
46
+ Do not broaden:
47
+ * do not introduce Express, Fastify, Koa, or `node:http` for convenience,
48
+ * do not rewrite unrelated routes,
49
+ * do not build a compatibility abstraction over a forbidden server.
50
+
51
+ Prove:
52
+ * the current behavioral acceptance passes through the real Bun server,
53
+ * the application server remains `Bun.serve`.
51
54
  exceptions:
52
55
  - A `createServer(` call that is not an HTTP server (a test double, an unrelated factory) is a known
53
56
  imprecision of the name-based match; rename it (atdd-bun has no per-rule scope).
@@ -34,12 +34,22 @@ content:
34
34
  diverge — someone runs `npm install` out of habit, the trees fork, and the divergence is discovered
35
35
  much later in a failing deploy.
36
36
  fix_hint: |
37
- Delete the foreign lockfile and let Bun own resolution:
38
-
39
- rm package-lock.json # or yarn.lock / pnpm-lock.yaml
40
- bun install # regenerates bun.lock from package.json
41
-
42
- Add the foreign names to `.gitignore` so a stray `npm install` cannot reintroduce one. `strict`.
37
+ Canonical path:
38
+ * keep Bun's lockfile as the single dependency-resolution source and remove npm, Yarn, or pnpm lockfiles.
39
+
40
+ During GREEN:
41
+ * if the current change adds a dependency, install it with Bun,
42
+ * remove only foreign lockfiles and regenerate `bun.lock` when dependency state actually changed,
43
+ * keep package-manager behavior otherwise untouched.
44
+
45
+ Do not broaden:
46
+ * do not switch package managers,
47
+ * do not update unrelated dependencies,
48
+ * do not keep a second lockfile as a temporary convenience.
49
+
50
+ Prove:
51
+ * the current behavioral acceptance and install/check path pass,
52
+ * only Bun's lockfile governs dependency resolution.
43
53
  exceptions:
44
54
  - A vendored or fixture lockfile inside an excluded tree (`node_modules`, `dist`, `build`,
45
55
  `_generated`) is never scanned.