@deslop/coding-standards 0.1.912 → 0.1.913

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/dist/install.js CHANGED
@@ -24685,7 +24685,7 @@ const runWith = (command, config) => {
24685
24685
  };
24686
24686
  //#endregion
24687
24687
  //#region package.json
24688
- var version = "0.1.912";
24688
+ var version = "0.1.913";
24689
24689
  //#endregion
24690
24690
  //#region src/install.ts
24691
24691
  const cli = pipe(make("deslop-coding-standards", {}, fnUntraced(function* () {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deslop/coding-standards",
3
- "version": "0.1.912",
3
+ "version": "0.1.913",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/MP281X/deslop",
@@ -1,30 +1,37 @@
1
1
  ---
2
2
  name: design
3
- description: 'UI and UX rules for screens and visual explanations. Use when building, prototyping, or reviewing a component, diagram, review page, or other rendered agent output.'
3
+ description: 'UI and UX rules for product screens, creative pages and visual explanations. Use when building, prototyping or reviewing a component, page, diagram, review page or other rendered agent output.'
4
4
  ---
5
5
 
6
6
  # Design
7
7
 
8
- **Scope.** Follow repository-specific CODING_STANDARDS.md and engineering.
8
+ Follow the repository's `CODING_STANDARDS.md` and the engineering skill.
9
9
 
10
- **Two modes.** Consistent mode works inside an existing product: its components, tokens and every rule below. Creative mode covers work with no product to match, such as websites, landing pages, portfolios, launch pages, motion design and videos. It follows [Creative mode](#creative-mode) in place of Decide and Build, whose calm, dense product rules make every page a dashboard; only Access and responsiveness and Verify still apply. When a request mixes both, the product's screens stay consistent.
10
+ **Two modes.** Consistent mode works inside an existing product and follows every rule below. Creative mode covers work with no product to match, such as websites, launch pages, portfolios, motion and video. It replaces Decide and Build with [Creative mode](#creative-mode), because dense product rules turn every page into a dashboard; Access and phones and Verify still apply. In a mixed request, the product's screens stay consistent.
11
11
 
12
12
  ## Decide
13
13
 
14
- **Direction.** Start from the actual task, audience, content and settled preferences. Make the next user action and its relevant content dominant, not generic "premium" styling. When a reference is useful, inspect the relevant accepted one for transferable hierarchy, density and interaction choices; distinguish observed details from inferred ones. Community brand analyses are inspiration, not verified current tokens.
14
+ **Direction.** Start from the task, audience, content and the user's settled preferences. The next user action and its content dominate, not a generic "premium" style. When a reference helps, take hierarchy, density and interaction from the accepted one, and say which details you observed and which you inferred. Community brand analyses are inspiration, not verified current tokens.
15
15
 
16
- **One meaning.** Each visible element must add information, enable a distinct action or clarify a relationship. Delete repeated headings, summaries, counts, status badges, decorative wrappers and controls that say or do the same thing. Remove explanations that merely restate the visible example/state. Keyboard shortcuts, screen-reader labels and responsive placement are not redundant visible controls; preserve their function.
16
+ **One meaning.** Each visible element adds information, enables a distinct action or shows a relationship. Delete repeated headings, summaries, counts, status badges, decorative wrappers and controls that say or do the same thing, and text that restates the visible example or state. Keyboard shortcuts, screen-reader labels and responsive placement are not redundant; keep their function.
17
17
 
18
- **Scan-first.** Put the task, relevant content and next action where they can be identified without reading a paragraph. Use stable visual roles, not another card/badge/icon for every fact. Expose needed detail on demand, never hide a consequential warning or essential action.
18
+ **Scan first.** The task, its content and the next action read without a paragraph. Use stable visual roles, not another card, badge or icon for each fact. Put detail on demand, but never hide a consequential warning or an essential action.
19
19
 
20
- **Hierarchy.** Blur a capture: the primary content and the next action must still stand out. Give unequal priorities unequal weight, and repeat one layout only for records with equal roles. De-emphasize labels, metadata and chrome before enlarging the important content. Give each decision area one strongest action, with secondary or text variants for the rest. Keep gaps inside a group smaller than gaps between groups, and space above a heading larger than below it. The first phone viewport shows real content and the next action, not an introduction. Left-align prose and records; keep prose at 45 to 75 characters per line. Reserve the accent for actions and selection, status colors for states and chart colors for series.
20
+ **Hierarchy.** Blur a capture: the primary content and the next action still stand out.
21
21
 
22
- | Content | Preferred treatment |
23
- | -------------------------- | ------------------------------------------------------------------------- |
24
- | Comparable records/options | Aligned rows/columns; consistent order, units and metadata placement |
25
- | Familiar action | Conventional icon-only control with an accessible name; one visible owner |
26
- | Ambiguous action | Clear text label, not an invented/guessed icon or redundant icon + text |
27
- | Explanation | Real state/example first; text only for missing context or consequences |
22
+ - Unequal priorities get unequal weight; repeat a layout only for records with equal roles.
23
+ - Mute labels, metadata and chrome before you enlarge content. Each decision area has one strongest action; the others use secondary or text variants.
24
+ - Gaps inside a group are smaller than gaps between groups; space above a heading is larger than below it.
25
+ - The first phone viewport shows real content and the next action, not an introduction.
26
+ - Left-align prose and records, and keep prose at 45 to 75 characters a line.
27
+ - The accent marks actions and selection, status colors mark states, and chart colors mark series.
28
+
29
+ | Content | Treatment |
30
+ | ----------------------------- | ------------------------------------------------------------------------------------- |
31
+ | Comparable records or options | Aligned rows and columns with consistent order, units and metadata placement |
32
+ | Familiar action | A conventional icon-only control with an accessible name and one owner |
33
+ | Ambiguous action | A clear text label, never an invented or guessed icon, or an icon with redundant text |
34
+ | Explanation | The real state or example first; text only for missing context or impact |
28
35
 
29
36
  ```tsx
30
37
  // one visible action, named for assistive technology
@@ -33,13 +40,13 @@ description: 'UI and UX rules for screens and visual explanations. Use when buil
33
40
  <Button><PencilIcon />Rename</Button>
34
41
  ```
35
42
 
36
- Do not remove necessary names, status, comfortable hit targets or instructions merely to make a screen smaller.
43
+ Never remove a needed name, status, comfortable hit target or instruction only to make a screen smaller.
37
44
 
38
45
  ## Build
39
46
 
40
- These rules apply to product UI. A rendered explanation follows the host's rendering contract and the rules below.
47
+ These rules cover product UI. A rendered explanation follows the host's rendering contract and these rules.
41
48
 
42
- **Canonical components.** Reuse the existing renderer, states and interactions for the same role. Inspect its relevant source/API, not a full catalogue; add missing primitives through the repository registry command. Fix wrong shared patterns at their owner when delivering retained code, not before an exploratory preview. Without a sibling, use the supplied reference and component defaults within settled preferences.
49
+ **Components.** Reuse the existing renderer, states and interactions for the same role; read its relevant source or API, not the whole catalogue. Add a missing primitive through the repository's registry command. Fix a wrong shared pattern at its owner when you deliver retained code, not before an exploratory preview. Without a sibling, use the supplied reference and the component defaults within settled preferences.
43
50
 
44
51
  ```tsx
45
52
  // same model-selection control used elsewhere
@@ -48,7 +55,7 @@ These rules apply to product UI. A rendered explanation follows the host's rende
48
55
  <Select value={model} onValueChange={setModel} />
49
56
  ```
50
57
 
51
- **Tokens and structure.** Use the existing app host, compiler, theme, shared components and Tailwind tokens. No custom-CSS/dynamic-class escape, hardcoded color/size exception or weakened shared rules. Keep surfaces flat and dense; group by proximity before adding borders or elevation. No nested cards or wrappers that merely label content again. Whitespace must support hierarchy, separation or comfortable use, not fill the page.
58
+ **Tokens and surfaces.** Use the existing app host, compiler, theme, shared components and Tailwind tokens. Add no escape into custom CSS or dynamic classes and no hardcoded color or size exception, and weaken no shared rule. Keep surfaces flat and dense: group by proximity before borders or elevation, and nest no cards or wrappers that only label content again. Whitespace serves hierarchy, separation or comfortable use, not filling the page.
52
59
 
53
60
  ```tsx
54
61
  // existing primitives and semantic tokens
@@ -57,105 +64,111 @@ These rules apply to product UI. A rendered explanation follows the host's rende
57
64
  <div className="rounded-full bg-[#eef] px-[7px] text-[11px]">No runs yet</div>
58
65
  ```
59
66
 
60
- **Typography.** Give headings, navigation, body text and data deliberate roles through the existing type scale, weights, line heights and readable line lengths. Use tabular numerals where values need comparison; let prose wrap without making controls inconsistent. Preserve established fonts and tokens rather than changing them for novelty. Do not substitute tiny labels, gratuitous capitals or isolated accent words for hierarchy.
67
+ **Typography.** Give headings, navigation, body text and data deliberate roles from the existing type scale, weights, line heights and line lengths. Use tabular numerals for compared values, and let prose wrap without making controls inconsistent. Keep the established fonts and tokens; never change them for novelty. Never use tiny labels, needless capitals or one accented word in place of hierarchy.
61
68
 
62
- **Copy.** Name actions from the user's task, not implementation internals. Keep the same vocabulary across controls and confirmations. Use plain verbs and sentence case; labels describe outcomes, not decoration. Empty states offer a relevant next action; errors identify the failed action and available recovery. Reuse its existing control rather than repeating the action in text or adding another button; do not invent a recovery that cannot work.
69
+ **Copy.** Name actions after the user's task, not implementation internals, with one vocabulary across controls and confirmations. Use plain verbs and sentence case; labels describe outcomes. An empty state offers the relevant next action. An error names the failed action and the recovery that exists, beside its existing control; never repeat the action in text or invent a recovery that cannot work.
63
70
 
64
71
  | Weak | Useful |
65
72
  | ---------------------- | ----------------------------------------------------------------- |
66
- | `Submit` | `Save changes` → `Changes saved` |
73
+ | `Submit` | `Save changes`, then `Changes saved` |
67
74
  | `Something went wrong` | `Couldn't save.` beside the existing retry action; keep the draft |
68
75
  | `No data` | `No notes yet` beside the existing create action |
69
76
 
70
- **Alignment.** Give related headings, search, pinned rows, dividers and records one owning grid/inset. Headers and row contents share columns; action columns stay fixed when labels wrap or are absent. Use the same component/size variant for equivalent controls: icon box/stroke, hit target, control height, baseline and spacing. Pinned content stays outside the scroll area; borders do not jump while scrolling. Fix the owning layout/component, not per-instance offsets; matching boxes alone does not establish optical alignment or legibility. Trace the cause before applying these repairs:
77
+ **Alignment.** Related headings, search, pinned rows, dividers and records share one grid and inset, and headers share columns with row contents. Action columns stay fixed when labels wrap or are missing. Equivalent controls share component and size: icon box, stroke, hit target, height, baseline and spacing. Pinned content stays outside the scroll area, and borders stay still while scrolling. Fix the owning layout or component, never one instance's offset; equal boxes alone prove neither optical alignment nor legibility. Trace the cause first:
71
78
 
72
- | Defect | Check | Owning repair |
73
- | ---------------------------------- | --------------------------------------------- | -------------------------------------------------------------------------------------------------- |
74
- | Squashed icon/avatar | Fixed-size flex child shrinks | Preserve its canonical box with `shrink-0` |
75
- | Trailing action disappears | Content track refuses to shrink | `min-w-0` on content; `shrink-0` on the control, or a shrinkable grid track |
76
- | Wrapped rows look adrift | Center alignment against variable-height text | Consistent, deliberate top/baseline alignment |
77
- | Identifiers look identical | Truncation hides the distinguishing segment | Preserve that segment; expose the full value through an existing keyboard/touch-accessible surface |
78
- | Counts shift during updates | Proportional digits/inconsistent formatting | `tabular-nums` + consistent locale/units |
79
- | Accents/tall scripts clip | Tight line height or text-box clipping | Fix the owning type-scale/overflow choice; don't shrink the font to fit |
80
- | Missing metadata leaves separators | Empty optional slots still render | Omit orphaned separators/lines; reserve space only when the layout needs it |
79
+ | Defect | Cause | Repair |
80
+ | ---------------------------------- | --------------------------------------- | ---------------------------------------------------------------------------------- |
81
+ | Squashed icon or avatar | A fixed-size flex child shrinks | `shrink-0` keeps its canonical box |
82
+ | Trailing action disappears | The content track refuses to shrink | `min-w-0` on the content and `shrink-0` on the control, or a shrinkable grid track |
83
+ | Wrapped rows look adrift | Centering against text of varied height | One deliberate top or baseline alignment |
84
+ | Identifiers look identical | Truncation hides the distinct part | Keep that part; show the full value on an existing keyboard and touch surface |
85
+ | Counts shift during updates | Proportional digits or mixed formats | `tabular-nums` with consistent locale and units |
86
+ | Accents or tall scripts clip | Tight line height or text-box clipping | Fix the owning type scale or overflow; never shrink the font to fit |
87
+ | Missing metadata leaves separators | Empty optional slots still render | Omit orphaned separators and lines; reserve space only when layout needs it |
81
88
 
82
89
  **Prevent before rejecting.** When the app already knows an action is not allowed, such as a missing permission, a referenced record or invalid input, disable or hide the control and show the reason beside it. Never let the user act and then show an error the app can predict.
83
90
 
84
- **Motion.** Explain change without delaying input or moving content just for decoration. Reuse existing tokens/components; no new library for a fade or universal curve, duration, bounce or press scale. Show press, pending, success and failure through the existing primitives. Where no primitive sets the easing, use ease-out for entrances, ease-in-out for morphs and linear only for elapsed progress. Start an entrance near its resting size, never from zero. Keep a dismissible surface mounted through its exit, reverse its entry path, and move its panel, backdrop and content together while unrelated chrome stays still. Delay a loader so fast results never flash it, and size it like the final content. List transition properties explicitly; never `transition-all`. Delay the first tooltip, then open neighboring ones at once.
85
-
86
- | Interaction | Treatment |
87
- | -------------------------------------- | -------------------------------------------------------------------------------------------------- |
88
- | Typing, shortcuts, frequent navigation | Immediate response; no decorative movement |
89
- | Trigger-anchored surface | Enter/exit from its trigger; a centered unanchored modal keeps a centered origin |
90
- | Rapid toggle/reversal | Retarget from the visible state; no input lock, stale-target snap or wait for the prior transition |
91
- | Drag/gesture | Follow the pointer; preserve the existing primitive's capture, cancellation and release behavior |
92
- | Reduced motion | Preserve feedback through a suitable static or gentle non-spatial equivalent |
93
-
94
- Use responsive entry easing and brief existing durations. Simple retargetable states suit transitions; gestures can use the existing spring. Prefer transforms and opacity where appropriate, but CSS and WAAPI do not guarantee compositor execution. Profile observed performance problems, not every animation. Inspect rapid repetition, reversal and reduced motion, not only the final frame.
91
+ **Motion.** Motion explains a change; it never delays input or moves content for decoration. Reuse existing tokens and components: no new library for a fade, and no universal curve, duration, bounce or press scale. Show press, pending, success and failure through the existing primitives.
95
92
 
96
- **Access and responsiveness.** Preserve the complete task on phones, not merely stacked desktop panes. Keep essential actions reachable with keyboard, touch and zoom. Use semantic structure, accessible names, visible focus, logical order and deliberate focus return. Inspect long/duplicate content, overflow, contrast and relevant failure/permission states. Do not remove an accessible affordance to satisfy visual minimalism.
93
+ - Use brief existing durations and responsive entry easing. Where no primitive sets the easing, use ease-out for entrances, ease-in-out for morphs and linear only for elapsed progress.
94
+ - An entrance starts near its resting size, never from zero. A dismissible surface stays mounted through its exit and reverses its entry path; its panel, backdrop and content move together while unrelated chrome stays still.
95
+ - A surface anchored to a trigger enters and exits from it; a centered unanchored modal keeps a centered origin.
96
+ - Typing, shortcuts and frequent navigation respond at once, without decorative movement. A rapid toggle or reversal retargets from the visible state, with no input lock, stale-target snap or wait for the earlier transition.
97
+ - A drag follows the pointer and keeps the primitive's capture, cancel and release behavior. Reduced motion keeps the feedback with a static or gentle non-spatial equivalent.
98
+ - Delay a loader so fast results never flash it, and size it like the final content. List transition properties; never `transition-all`. Delay the first tooltip, then open neighbors at once.
99
+ - Transitions suit simple states that retarget; gestures can use the existing spring. Prefer transforms and opacity, but neither CSS nor WAAPI guarantees compositor execution. Profile only an observed performance problem.
100
+ - Inspect rapid repetition, reversal and reduced motion in slowed intermediate frames for jumps and stretched text, not only the final frame.
97
101
 
98
- | Mobile defect | Check |
99
- | --------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
100
- | Hover remains after tap | Capability-aware styles; inspect the framework's handling before adding another gate |
101
- | Input zoom/wrong keyboard | Readable input sizing + correct input type/mode; never disable browser zoom |
102
- | Bottom controls disappear | Real browser chrome, software keyboard and safe areas; appropriate supported viewport sizing/insets |
103
- | Drag blocks scrolling/content can't be copied | Scope gesture/selection restrictions to their owner; preserve scrolling, zoom and selectable content |
102
+ **Access and phones.** The whole task works on a phone, not only stacked desktop panes, and essential actions stay reachable with keyboard, touch and zoom. Use semantic structure, accessible names, visible focus, logical order and deliberate focus return. Inspect long and duplicate content, overflow, contrast, and the failure and permission states that apply. Never remove an accessible affordance for minimalism.
104
103
 
105
- Touch and mouse can coexist; do not infer capabilities from user-agent strings or viewport width. No blanket suppression of overscroll, selection or native feedback without a demonstrated need and working replacement. Emulation verifies selected layout cases, not every phone behavior: affected device-specific keyboard/viewport/gesture contracts need target-device proof before completion.
104
+ - Hover that stays after a tap needs capability-aware styles; read the framework's handling before you add another gate.
105
+ - Inputs use a readable size and the right input type and mode; never disable browser zoom.
106
+ - Bottom controls survive real browser chrome, the software keyboard and safe areas, with supported viewport units and insets.
107
+ - Scope gesture and selection limits to their owner, and keep scrolling, zoom and selectable content.
108
+ - Touch and mouse coexist: never infer capabilities from the user agent or the viewport width. Add no blanket suppression of overscroll, selection or native feedback without a shown need and a working replacement.
109
+ - Emulation verifies selected layout cases, not every phone behavior: an affected device-specific keyboard, viewport or gesture contract needs proof on the target device.
106
110
 
107
111
  ## Creative mode
108
112
 
109
- Work as the design lead of a studio whose clients reject anything templated, and aim at the level of an award-winning site, not a tidy product page. Every choice of palette, type, layout and motion comes from this brief.
113
+ Work as the design lead of a studio whose clients reject anything templated, and aim at an award-winning site, not a tidy product page. Every choice of palette, type, layout and motion comes from this brief.
110
114
 
111
- **Ground it.** Name the subject, the audience and the page's one job before designing. Take the visual language from the subject's world: its materials, tools, documents, places, times of day and vernacular. The brief's data is raw material for an idea, not content to lay out; write copy that names concrete capabilities and outcomes, never selling filler.
115
+ **Ground it.** Before designing, name the subject, the audience and the page's one job. Take the visual language from the subject's world: its materials, tools, documents, places, times of day and vernacular. The brief's data is raw material for an idea, not content to lay out. Copy names concrete capabilities and outcomes, never selling filler.
112
116
 
113
- **Concept first.** Before any system or code, write three concepts that differ in structure, not in palette. Each is one paragraph: the big idea in one sentence; the metaphor or artifact from the subject's world; the structure it gives the page, such as a clock running from night to morning, a document being read, a journey or one interactive object; the signature moment; the motion; and the visual world of type, color, texture and imagery. Score each from 1 to 5 on three questions: would a viewer remember it tomorrow, could it exist for no other subject, does it make the reader act. Discard any concept whose structure is hero, features, list and form. Build the winner whole, with the full canvas, display typefaces chosen for the subject from Fontshare or Google Fonts, and canvas or SVG where the idea needs them; never retreat toward a safe page while building.
117
+ **Concept first.** Before any system or code, write three concepts that differ in structure, not palette. Each is one paragraph: the big idea in one sentence; the metaphor or artifact from the subject's world; the structure it gives the page, such as a clock from night to morning, a document being read, a journey or one interactive object; the signature moment; the motion; and the visual world of type, color, texture and imagery. Score each from 1 to 5: would a viewer remember it tomorrow, does it belong to this subject alone, does it make the reader act. Discard any concept built as hero, features, list and form. Build the winner whole: the full canvas, display typefaces from Fontshare or Google Fonts chosen for the subject, and canvas or SVG where the idea needs them. Never retreat toward a safe page while building.
114
118
 
115
- **Plan, then challenge the plan.** Then write a compact system for the chosen concept: four to six named colors with roles (canvas, ink, atmosphere, action), one or two clearly distinct typefaces with roles and a type scale, and a layout concept with alignment. Sketch three different compositions as ASCII wireframes, not three palettes, and pick one. Then ask what you would produce for any similar brief; revise every part of the plan that matches it, and say what changed.
119
+ **Plan, then challenge it.** Write a compact system: four to six named colors with roles (canvas, ink, atmosphere, action), one or two distinct typefaces with roles and a type scale, and a layout concept with its alignment. Sketch three compositions as ASCII wireframes, not three palettes, and pick one. Then ask what you would produce for any similar brief, change every part of the plan that matches it, and say what changed.
116
120
 
117
- **Defaults to avoid.** These appear whatever the subject, so they read as generated: a cream canvas with a serif display and a clay accent; near-black with one acid accent; broadsheet hairlines with zero radius; identical rounded cards with soft shadows and gradient washes; all-caps eyebrows above headings, middle-dot meta strings, a monospace face for labels, `→` on every link; one emphasized word in a headline; numbering on content that is no sequence. Also the generated launch-page skeleton: hero, feature table, ranked list, logo row, email form, each section opened by a heading on the left and a grey paragraph on the right; a pale sage or off-white canvas with navy ink. Use one only when the brief asks for it.
121
+ **Defaults to avoid** unless the brief asks for one, because they appear whatever the subject and read as generated:
118
122
 
119
- **Compose.** Build the page around one artifact from the subject's world, shown as it lives there: the message as it arrives, the object as it is used, the document as it is read. Invent the page's structure from the story that artifact tells, not from a section template, and give the product a mark people remember. Open with the most characteristic thing in its best form: a headline, an image, a live demo or an interaction, not a big number with a gradient by default. Own the grid: deliberate spans, overlaps and whitespace, with repeated layouts only for content with equal roles. Alternate dense demonstrations with quiet reading passages. Let typography carry the personality, as an active visual element, with body lines under 75 characters. Spend boldness on one memorable signature, keep everything around it quiet, and remove one more element before you finish.
123
+ - a cream canvas with a serif display and a clay accent; near-black with one acid accent; navy ink on pale sage or off-white;
124
+ - broadsheet hairlines with zero radius; identical rounded cards with soft shadows and gradient washes;
125
+ - all-caps eyebrows, middle-dot meta strings, a monospace label face, `→` on every link, one emphasized headline word, and numbering on content that is no sequence;
126
+ - the launch-page skeleton: hero, feature table, ranked list, logo row and email form, each section a heading on the left and a grey paragraph on the right.
120
127
 
121
- **Imagery and texture.** Make subject-specific assets with one consistent light, material, palette and crop; keep text and controls in code. Take texture from the subject's real materials, never a universal grain or grid overlay. Never present a generated picture or invented testimonial as evidence.
128
+ **Compose.** Build the page around one artifact from the subject's world, shown as it lives there: the message as it arrives, the object in use, the document as it is read. Take the structure from that artifact's story, not a section template, and give the product a mark people remember. Open with the most characteristic thing in its best form: a headline, an image, a live demo or an interaction, not a big number with a gradient by default. Own the grid with deliberate spans, overlaps and whitespace, and repeat a layout only for content with equal roles. Alternate dense demonstrations with quiet reading passages. Typography carries the personality as an active visual element, with body lines under 75 characters. Spend boldness on one signature, keep the rest quiet, and remove one more element before you finish.
122
129
 
123
- **Motion.** Use motion to explain: a cause and its effect, a before and after, a process in order, not content fading in. Choreograph one orchestrated moment, such as the page load or one reveal, instead of fade-up entrances on every section. Before coding a sequence, write its purpose, focal order, movement, easing, duration, overlap and resting moment. Animate interactions from their spatial origin and keep them interruptible. Bind scroll storytelling to scroll progress without hijacking scrolling, and keep the first viewport readable and actionable before any animation runs. Every motion has a complete reduced-motion and static version; stop offscreen animation. For a video, storyboard timed keyframes with reading holds, persistent objects and deterministic frames, and check text at the size it plays.
130
+ **Imagery and texture.** Make assets for the subject with one consistent light, material, palette and crop, and keep text and controls in code. Take texture from the subject's real materials, never a universal grain or grid overlay. Never present a generated picture or an invented testimonial as evidence.
124
131
 
125
- **Critique.** Capture desktop and phone, and slowed motion frames; compare them with the plan and with the defaults above. Batch the repairs and recheck once. The quality floor is silent: responsive to phones, visible keyboard focus, sufficient contrast and reduced motion respected.
132
+ **Motion.** Motion explains a cause and its effect, a before and after, or a process in order; it never only fades content in. Choreograph one moment, such as the page load or one reveal, instead of fade-ups on every section. Before coding a sequence, write its purpose, focal order, movement, easing, duration, overlap and resting moment. Animate interactions from their spatial origin and keep them interruptible. Scroll storytelling follows scroll progress without hijacking it, and the first viewport reads and acts before any animation runs. Every motion has a complete reduced-motion and static version, and offscreen animation stops. A video gets a storyboard of timed keyframes with reading holds, persistent objects and deterministic frames, and its text is checked at playback size.
133
+
134
+ **Critique.** Capture desktop, phone and slowed motion frames, and compare them with the plan and the defaults above. Batch the repairs and recheck once. The quality floor holds without mention: phone layouts, visible keyboard focus, enough contrast and reduced motion.
126
135
 
127
136
  ## Prototype
128
137
 
129
- **Try the question.** Build one rough representative screen or interaction in the existing host with realistic data. Inspect enough to make the trial trustworthy, then show it to the user before merge-readiness work. Label stubs and limits; a conceptual sketch is sufficient only when execution is unnecessary, never proof of working software. Set a short first-preview budget; show a partial result or blocker rather than expanding unseen. No production completeness or polished gallery first.
138
+ **Try the question.** Build one rough representative screen or interaction in the existing host with realistic data. Inspect enough to trust the trial, then show it before any merge-readiness work. Label stubs and limits; a sketch is enough only when execution is unnecessary, and it never proves working software. Set a short budget for the first preview, and show a partial result or a blocker rather than growing unseen. Build no production completeness or polished gallery first.
130
139
 
131
- **Use the findings.** For layout questions, compare hierarchy or interaction, not color-only variants. Compare several directions at the mockup stage; add real attempts only for unresolved uncertainty, feedback or an explicit request. A style question can compare style. Keep useful comparisons; discard/rebuild freely and combine compatible strengths, not incompatible mechanisms. Test the weakest assumption while it can change the choice. A settled direction needs no manufactured taste question or exploration round.
140
+ **Use the findings.** For a layout question, compare hierarchy or interaction, not color variants; a style question can compare style. Compare several directions as mockups, and build real attempts only for open uncertainty, feedback or an explicit request. Keep useful comparisons, discard and rebuild freely, and combine compatible strengths, never incompatible mechanisms. Test the weakest assumption while it can still change the choice. A settled direction needs no invented taste question or exploration round.
132
141
 
133
142
  ## Verify and show
134
143
 
135
- **Inspect retained UI.** Open actual captures at the sizes needed for the task. Compare related edges, columns, baselines and equivalent controls across rows/screens—not just successful clicks. Use realistic long names/URLs, translated labels, Unicode, missing fields and relevant 0/1/many records at the actual container width. Respect schema/API limits; never add a validation limit to make layout pass. Mix cases across rows. Check selected/focus/error states and scrolling; a clean default row can hide misalignment. Inspect hierarchy, density, legibility and clipping. Exercise the relevant keyboard/touch, narrow/wide, zoom and focus-return journeys; run axe where applicable. A clean scan does not prove contrast or usability. Inspect meaningful video frames and sequence; a playable file is not proof of a good composition. Batch relevant inspection/repairs; recheck affected views rather than restart a whole audit after each micro-edit. Visible misalignment, inconsistent controls or redundant elements remain defects even when types/tests pass; fix them before claiming acceptance. Inspect motion in slowed intermediate frames for jumps and stretched text.
144
+ **Inspect retained UI** in real captures at the sizes the task needs:
136
145
 
137
- **Generic output.** Check every capture for these tells and fix each one before showing it:
146
+ - Compare related edges, columns, baselines and equivalent controls across rows and screens, not only successful clicks.
147
+ - Use long names and URLs, translated labels, Unicode, missing fields and 0, 1 and many records, mixed across rows at the real container width. Respect schema and API limits; never add a validation limit to make a layout pass.
148
+ - Check selected, focus, error and scrolling states, and the hierarchy, density, legibility, contrast and clipping.
149
+ - Walk the keyboard, touch, narrow, wide, zoom and focus-return journeys that apply, and run axe where it applies; a clean scan proves neither contrast nor usability.
150
+ - Inspect video frames in sequence; a playable file is not a good composition.
138
151
 
139
- | Tell | Check |
140
- | ----------------------------------------------- | -------------------------------------------------------- |
141
- | Every section is a bordered card with an icon | Each container has a grouping purpose; remove the others |
142
- | Everything has equal prominence | The blurred capture still shows the primary content |
143
- | Uniform gaps | Unrelated groups sit farther apart than related items |
144
- | Each tile gets its own accent color | Every hue names a state, series or action |
145
- | An emphasized headline word or decorative label | Removing the treatment loses no meaning, so remove it |
146
- | Charts, rings or dots without readable data | Each graphic shows values, units or state |
147
- | Generic copy such as "seamless" or "Learn more" | Each label names its capability or the click's outcome |
148
- | Content that waits for an entrance animation | The first frame is readable and actionable |
152
+ Batch repairs and recheck only the affected views instead of restarting the audit after each small edit. Misalignment, inconsistent controls and redundant elements stay defects when types and tests pass; fix them before you claim acceptance.
149
153
 
150
- **Show the design.** Use inspected screenshots for layout and short video for behavior. Compare at consistent sizes with states needed for the decision; no variant switcher just to see the options. A visual must add spatial or interactive information, not reproduce prose, a file list or a fake runtime screenshot. Embed useful existing captures in the render rather than recreate them. For diagrams, review pages and rendered answers, follow Visual explanations below. Use the user's theme and verify the actual browser color preference. Preserve useful media and retire settled attempts; environment decides how long previews run.
154
+ **Generic output.** Fix each of these tells before you show a capture:
151
155
 
152
- **Review surfaces.** Open on the outcome the user needs to judge, with technical detail available on demand. Group by changed behavior, not files or agent stages. A selected example, diagram or diff must reveal its scope; never make curated evidence look like complete coverage. Do not build a custom review dashboard when existing captures and the PR can answer the question. A design-skill edit is not a product-screen change.
156
+ | Tell | Check |
157
+ | ----------------------------------------------- | ------------------------------------------------------ |
158
+ | Every section is a bordered card with an icon | Each container groups something; remove the others |
159
+ | Everything has equal prominence | The blurred capture still shows the primary content |
160
+ | Uniform gaps | Unrelated groups sit farther apart than related items |
161
+ | Each tile gets its own accent color | Every hue names a state, series or action |
162
+ | An emphasized headline word or decorative label | Removing the treatment loses no meaning, so remove it |
163
+ | Charts, rings or dots without readable data | Each graphic shows values, units or state |
164
+ | Generic copy such as "seamless" or "Learn more" | Each label names its capability or the click's outcome |
165
+ | Content that waits for an entrance animation | The first frame is readable and actionable |
153
166
 
154
- ## Visual explanations
167
+ **Show the design** with inspected screenshots for layout and short video for behavior, at consistent sizes, with the states the decision needs, in the user's theme and the browser's real color preference. Embed existing captures instead of recreating them, and build no variant switcher only to view options. Keep useful media and retire settled attempts; environment decides how long previews run. A review surface opens on the outcome the user judges, with technical detail on demand, and groups by changed behavior, not by file or agent stage. Build no custom dashboard when captures and the pull request answer the question. A design-skill edit is not a product-screen change.
155
168
 
156
- These rules cover diagrams, review pages and rendered agent answers; the pair prompt decides when a reply needs a render. A render replaces the text it shows; it never repeats it.
169
+ ## Visual explanations
157
170
 
158
- **Pick the exhibit from the question.**
171
+ These rules cover diagrams, review pages and rendered agent answers; the pair prompt decides when a reply needs a render. A render adds spatial or interactive information and replaces the text it shows; it never redraws prose, a file list or a fake runtime screenshot.
159
172
 
160
173
  | The reader asks | Exhibit |
161
174
  | ------------------------------------ | -------------------------------------------------------------- |
@@ -171,30 +184,18 @@ These rules cover diagrams, review pages and rendered agent answers; the pair pr
171
184
  | Which option is better? | Options side by side at the same size and with the same data |
172
185
  | What will a video show? | Storyboard of chapter frames, the outcome frame marked |
173
186
 
174
- When none fits, choose the form that matches the data's shape, not the first card layout that comes to mind. Draw a list as a list.
175
-
176
- - **One message.** Each page answers one question. Its title states the conclusion, such as "The catalog loads 26 times faster", not the topic.
177
- - **One dominant element.** Size, weight and position show importance. Mute the context and make secondary detail smaller.
178
- - **Color means something.** Use the theme's status colors only for states and the chart colors only for series. Keep one accent, and never color for decoration.
179
- - **Label directly.** Put names and values on the data instead of a distant legend. Show units, and use one scale per comparison.
180
- - **Real content.** Use real names, numbers and captures. Show the scope, so a sample never looks like full coverage.
187
+ When none fits, choose the form that matches the data's shape, not the first card layout; draw a list as a list.
181
188
 
182
- - **Grid and rhythm.** Align to one grid. Use a spacing scale of 4, 8, 12 and 16 pixels, two or three type sizes, and one corner radius.
183
- - **Little text.** Labels and captions stay under twelve words. A visual holds no paragraphs.
184
- - **Small multiples.** Compare several cases with repeated small exhibits on the same scale, rather than one crowded chart.
185
- - **Both themes and widths.** Use the host's theme variables, check light and dark, and keep the page readable at phone width.
186
- - **Inspect before showing.** Look at the rendered page for clipping, overlap, contrast and empty areas, and fix them first.
189
+ - **One message.** Each page answers one question, and its title states the conclusion, such as "The catalog loads 26 times faster", not the topic.
190
+ - **One dominant element.** Size, weight and position show importance; mute the context and shrink secondary detail.
191
+ - **Color.** Use the theme's status colors only for states and its chart colors only for series. Keep one accent and no decorative color.
192
+ - **Labels.** Put names, values and units on the data instead of a distant legend, with one scale per comparison. Repeat small exhibits on one scale rather than crowd one chart.
193
+ - **Real content.** Use real names, numbers and captures, and show the scope, so a sample never looks like full coverage.
194
+ - **Grid.** Align to one grid with 4, 8, 12 and 16 pixel spacing, two or three type sizes and one corner radius. Labels and captions stay under twelve words, and a visual holds no paragraphs.
195
+ - **Check.** Use the host's theme variables, check light, dark and phone width, and fix clipping, overlap, contrast and empty areas before you show it.
187
196
 
188
- **Avoid** these:
189
-
190
- - A table or bullet list redrawn as styled boxes.
191
- - A card, badge or icon for every fact.
192
- - Gradients, shadows and illustrations that carry no information.
193
- - Crossing links, when an ordered list or lanes would show the same relation.
194
- - A visual that repeats the text around it.
197
+ **Avoid** a table or list redrawn as styled boxes, and a card, badge or icon for every fact. Avoid gradients, shadows and illustrations that carry no information, crossing links where an ordered list or lanes show the same relation, and a visual that repeats the text around it.
195
198
 
196
199
  ## Image assets
197
200
 
198
- Use image generation only for a needed illustrative asset, atmosphere, texture or icon exploration—not ordinary text, exact diagrams or fake working UI. Use the native tool exposed by the harness; no invented invocation or replacement API client when unavailable. Report missing capability honestly.
199
-
200
- Describe purpose, placement, composition, palette and intended size and aspect ratio. For edits, supply the real source and state what remains unchanged. Generate only what the chosen direction needs; prefer existing icons or CSS when they express the job precisely. Inspect the returned asset at its intended size for crop, text and edge artifacts, contrast and fit. Preserve useful originals and identify generated assets as such; they are not runtime or browser proof. Keep only used assets in product source.
201
+ Generate an image only for a needed illustration, atmosphere, texture or icon exploration, never for text, exact diagrams or fake working UI. Use the harness's native tool; when it is missing, say so instead of inventing an invocation or an API client. Describe the purpose, placement, composition, palette, size and aspect ratio; for an edit, supply the real source and state what stays unchanged. Generate only what the chosen direction needs, and prefer existing icons or CSS when they fit. Inspect the result at its real size for crop, text, edge artifacts, contrast and fit. Keep useful originals, label generated assets as generated, never count them as runtime or browser proof, and keep only used assets in product source.
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: engineering
3
- description: 'TypeScript and Effect code conventions paired with shared lint. Use when designing, implementing or reviewing product/test code, including prototypes.'
3
+ description: 'TypeScript and Effect code conventions paired with shared lint. Use when designing, implementing or reviewing product and test code, including prototypes.'
4
4
  ---
5
5
 
6
6
  **Scope.** Apply these rules and repository-specific CODING_STANDARDS.md. Write each line right the first time: the examples exist so lint and review find nothing, and lint is only the fallback.
7
7
 
8
- **Dependency APIs.** Match the manifest and lockfile versions. Before adding an API wrapper or workaround, read the upstream source per workflow's research procedure. Library APIs do not define coding policy.
8
+ **Dependency APIs.** Match the manifest and lockfile versions. Before adding an API wrapper or workaround, read the upstream source per explore's source checkouts. Library APIs do not define coding policy.
9
9
 
10
10
  **Diagnostics.** Use the shown idiom, not casts, weakened rules or a rewrite trading one diagnostic for another.
11
11
 
@@ -13,7 +13,7 @@ description: 'TypeScript and Effect code conventions paired with shared lint. Us
13
13
 
14
14
  **Clarity.** Plain, explicit, idiomatic code, names and files; read top to bottom without commentary or cleverness. Match the surrounding code's naming, idiom and comment density.
15
15
 
16
- **Experiments.** Write with these idioms; reserve the full refactor/cleanup pass for retained delivery. Keep disposable source isolated and shared rules intact.
16
+ **Experiments.** Write with these idioms; reserve the full refactor and cleanup pass for retained delivery. Keep disposable source isolated and shared rules intact.
17
17
 
18
18
  - **Reuse first.** Check existing code, installed modules and platform capabilities before adding code. Implement only the missing behavior, without dropping required behavior, safety or accessibility. Workflow owns the scope. A refactor or cleanup request applies every rule to every line of the owned files.
19
19
  - **Inward layers.** Domain and service code never import HTTP, RPC, or other transport types, and domain schemas carry no transport annotation such as an HTTP status.
@@ -21,7 +21,7 @@ description: 'TypeScript and Effect code conventions paired with shared lint. Us
21
21
  - **No machinery.** Add hooks, guards or generators only for a required contract or a recurring defect.
22
22
  - **Behavior kept.** A refactor keeps observable behavior at every consumer. Report accepted differences only when they exist: a change no consumer observes, or one a rule here causes, such as an error keeping its cause. Printed diagnostics are not a contract. Any other behavior change follows workflow's scope.
23
23
  - **Reachable bugs.** Fix a bug that real input reaches when it lies inside workflow's scope, and check every consumer of the changed output. For a hard bug, use one reproduction and one prediction per probe. Remove edits based on disproven hypotheses, then rerun the original scenario. Delete handling only for input the contract excludes; keep and report code that looks intentional.
24
- - **Performance.** Optimize only when the request or a required contract needs it. Measure one real action on realistic input before and after the change, at the layer that owns the symptom: spans for backend calls, React commits for rerenders, a browser profile for main-thread work. Report run count and variation; a difference within noise is unproved.
24
+ - **Performance.** Optimize only when the request or a required contract needs it. Measure one real action on realistic input before and after the change. Measure at the layer that owns the symptom: spans for backend calls, React commits for rerenders, a browser profile for main-thread work. Report run count and variation; a difference within noise is unproved.
25
25
  - **Type safety.** A fix never weakens types to make a symptom go away: no widened or erased type, cast, dropped generic, or loosened exported type.
26
26
  - **Domain.** Implement the definition the domain uses, such as a cycle for recursion, never the nearest syntactic proxy.
27
27
 
@@ -72,7 +72,7 @@ _input => onSubmit(_input.value) // or input2: an outer input is shadowed
72
72
 
73
73
  **Nearest sibling.** Extend the nearest implementation; match permissions, errors, refresh and tests. Reuse its helpers and change only affected state.
74
74
 
75
- **Once.** Extract repeated logic once; one fact has one owner. A domain enum, such as a status, has one schema that every other schema reuses, and a cache key or atom family key carries the full identity of what it caches.
75
+ **Once.** Extract repeated logic once; one fact has one owner. A domain enum, such as a status, has one schema that every other schema reuses. A cache key or atom family key carries the full identity of what it caches.
76
76
 
77
77
  ```ts
78
78
  // good
@@ -88,11 +88,11 @@ pipe(
88
88
  )
89
89
  ```
90
90
 
91
- **Canonical data.** Store/send canonical data, derive display values, expose each state once and remove states no caller produces.
91
+ **Canonical data.** Store and send canonical data, derive display values, expose each state once and remove states no caller produces.
92
92
 
93
- **One way.** Replace superseded paths; no duplicate/subset/superset fields, methods, options or exports.
93
+ **One way.** Replace superseded paths; no duplicate, subset or superset fields, methods, options or exports.
94
94
 
95
- **No compatibility.** Rename the shape and every caller together. No alias, fallback, deprecated path or flag unless a documented/user-named contract requires it.
95
+ **No compatibility.** Rename the shape and every caller together. No alias, fallback, deprecated path or flag unless a documented or user-named contract requires it.
96
96
 
97
97
  **Present needs.** No speculative option, abstraction, layer, export, file or check. Configure only what callers vary.
98
98
 
@@ -122,7 +122,7 @@ if (enabled === true) return // enabled is a boolean
122
122
  if (props.selected) return // props.selected can be undefined
123
123
  ```
124
124
 
125
- **Flat.** Use early-return statements in Effect.fn. No nested ternaries or combinators deeper than equivalent statements. Match/combinators serve single expressions; Boolean.match selects a value, except one-line JSX-attribute ternaries.
125
+ **Flat.** Use early-return statements in Effect.fn. No nested ternaries or combinators deeper than equivalent statements. Match and combinators serve single expressions; Boolean.match selects a value, except one-line JSX-attribute ternaries.
126
126
 
127
127
  ```ts
128
128
  // good
@@ -185,7 +185,7 @@ const [first] = teamId
185
185
  items.filter(item => supports(item)).map(item => item.value)
186
186
  ```
187
187
 
188
- **Natives.** Use Effect modules instead of globals/native methods. Third-party-owned methods stay, with an inline diagnostic disable and reason when needed.
188
+ **Natives.** Use Effect modules instead of globals and native methods. Third-party-owned methods stay, with an inline diagnostic disable and reason when needed.
189
189
 
190
190
  ```ts
191
191
  // good
@@ -230,7 +230,7 @@ const text = Effect.fn('Ai.text')(function* (response: AiResponse) {
230
230
  })
231
231
  ```
232
232
 
233
- **Casts.** No `as`, `any` or erasing a known shape into `unknown`; `satisfies` and `as const` are the only assertions. Genuinely opaque SDK/framework inputs remain `unknown` until narrowed or decoded at their boundary—do not fabricate a shape to avoid that type.
233
+ **Casts.** No `as`, `any` or erasing a known shape into `unknown`; `satisfies` and `as const` are the only assertions. Opaque SDK and framework inputs remain `unknown` until narrowed or decoded at their boundary; never fabricate a shape to avoid that type.
234
234
 
235
235
  ```ts
236
236
  // good
@@ -247,7 +247,7 @@ const params: unknown = part.params // erases an already-known shape
247
247
  // good
248
248
  const load = Effect.fn('Plugin.load')(function* (path: string) {
249
249
  const endpoint = yield* Schema.decodeEffect(Endpoint)(config.endpoint)
250
- const manifest = yield* Schema.decodeEffect(PackageManifest)(yield* fs.readFileString(path))
250
+ const manifest = yield* Schema.decodeEffect(Schema.fromJsonString(PackageManifest))(yield* fs.readFileString(path))
251
251
  return {endpoint, manifest}
252
252
  })
253
253
  // bad
@@ -367,7 +367,7 @@ static readonly layer = Layer.effect(Ledger, makeLedger) // a make with one call
367
367
  query(sql: string): Effect.Effect<Rows> // a method signature instead of a readonly property
368
368
  ```
369
369
 
370
- **Primitives.** Use Effect's primitives directly; rpcs and services already trace, and one scope owns each lifetime. Compose established independent I/O with Effect.all and explicit appropriate concurrency; keep order-dependent, transactional or resource-conflicting work sequential.
370
+ **Primitives.** Use Effect's primitives directly; rpcs and services already trace, and one scope owns each lifetime. Compose established independent input and output with Effect.all and explicit appropriate concurrency; keep order-dependent, transactional or resource-conflicting work sequential.
371
371
 
372
372
  ```ts
373
373
  // good
@@ -412,7 +412,7 @@ entries.sort((left, right) => left.tokens - right.tokens)
412
412
 
413
413
  ## Types and Schema
414
414
 
415
- **Inference.** Infer types. Annotate recursion or branches TypeScript cannot unite; use schema types/indexed members in signatures. Keep intentional widening, not repeated inferred generics.
415
+ **Inference.** Infer types. Annotate recursion or branches TypeScript cannot unite; use schema types and indexed members in signatures. Keep intentional widening, not repeated inferred generics.
416
416
 
417
417
  ```ts
418
418
  // good
@@ -494,7 +494,7 @@ function isPathNotFound(error: unknown) {
494
494
 
495
495
  ## Shape
496
496
 
497
- **Inline.** Inline forwarding wrappers and single-use helpers/temporaries/constants. Argument-free functions are named values.
497
+ **Inline.** Inline forwarding wrappers and single-use helpers, temporaries and constants. Argument-free functions are named values.
498
498
 
499
499
  ```ts
500
500
  // good
@@ -573,7 +573,7 @@ onClick={() => Effect.runPromise(saveApp(draft))}
573
573
  useAtomValue(Atom.make(loadApp(appId))) // a new atom on every render
574
574
  ```
575
575
 
576
- **Outcomes.** Read data with `useAtomSuspense`. The route or section that owns a screen wraps it in one `Suspense` boundary for loading and one error boundary that shows the failure with a retry. Components never branch on loading or failure, and never turn a failure into an empty value. Take a write's pending and failure state from its atom's result, never from copied React state.
576
+ **Outcomes.** Read data with `useAtomSuspense`. The route or section that owns a screen wraps it in one `Suspense` boundary for loading. One error boundary there shows the failure with a retry. Components never branch on loading or failure, and never turn a failure into an empty value. Take a write's pending and failure state from its atom's result, never from copied React state.
577
577
 
578
578
  ```tsx
579
579
  // good
@@ -593,7 +593,7 @@ const [pending, setPending] = useState(false) // copies the write atom's waiting
593
593
  ```
594
594
 
595
595
  - **Ownership.** Give a component that owns its own atoms, writes or lifetime its own file; keep small presentational helpers beside their one user. Reset an editable draft through a `key` on its identity, never an Effect that copies props.
596
- - **Pure render.** Derive display values from props and subscribed state during render; never mutate them or perform an RPC, write or subscription there. Event handlers own user-triggered actions; Effects synchronize external systems, not copied state or calculations. Reuse the existing router/atom integration rather than fetching in a new Effect.
596
+ - **Pure render.** Derive display values from props and subscribed state during render; never mutate them or perform an RPC, write or subscription there. Event handlers own user-triggered actions; Effects synchronize external systems, not copied state or calculations. Reuse the existing router and atom integration rather than fetching in a new Effect.
597
597
  - **State identity.** Keep one owner for each value, stable domain keys for list items and deliberate reset boundaries. For an observed rerender problem, derive the needed value in the existing atom graph instead of subscribing to frequently changing unrelated state. Compiler memoization is a performance optimization, never a correctness or lifetime guarantee. Do not add manual memoization, compiler escape directives or weakened hook rules to hide an ownership problem.
598
598
 
599
599
  Testing judgment, fixtures, assertions and verification belong to the testing skill; these engineering rules still apply to test code.
@@ -1,16 +1,16 @@
1
1
  ---
2
2
  name: testing
3
- description: 'Select and run black-box behavior proof for Effect apps/tools. Use when choosing, writing, reviewing or running tests; apply engineering to test code and keep exploratory proof question-sized.'
3
+ description: 'Select and run black-box behavior proof for Effect apps and tools. Use when choosing, writing, reviewing or running tests; apply engineering to test code and keep exploratory proof question-sized.'
4
4
  ---
5
5
 
6
6
  # Testing
7
7
 
8
8
  **Scope.** Test behavior the changed code owns; a coverage count proves nothing.
9
9
 
10
- - **Worth it.** Test owned branching, computation, parsing/state transitions a plausible regression breaks; add missing valuable coverage before refactoring.
10
+ - **Worth it.** Test owned branching, computation, parsing and state transitions that a plausible regression breaks. Add missing valuable coverage before refactoring.
11
11
  - **Public interface.** Test exported Layers, services and functions through observable behavior, so a rewrite that keeps the contract keeps the tests green. The browser proves UI components.
12
12
  - **Redundant.** Delete touched cases that only repeat dependency guarantees, constants, wording, removed behavior or an already covered input. Keep boundary tests that prove the application's own validation, encoding or integration.
13
- - **Independent.** Expected values come from the contract/worked example, not implementation recomputation. Use the smallest reachable discriminating fixture.
13
+ - **Independent.** Expected values come from the contract or a worked example, not from recomputing the implementation. Use the smallest reachable fixture that tells the cases apart.
14
14
  - **Bugs.** Reproduce a bug before fixing it. Keep the failing case when it protects owned behavior, in the existing test that covers the fixed code, or a new case when none fits.
15
15
  - **Throwaway.** Settle a worry with a throwaway test or prototype and delete it once answered, unless it becomes a regression test under Bugs.
16
16
  - **Honest.** No wrong expectations or rule workarounds. Change assertions only for recorded behavior changes; preserve every still-relevant value.
@@ -38,26 +38,26 @@ assert.strictEqual(Array.flatMap(attioProvider.groups, group => group.actions).l
38
38
 
39
39
  ## Choose cases
40
40
 
41
- - **Contract.** Connect a reachable input to an observable output, so a plausible wrong implementation fails. Use the nearest public interface, not private helpers or new harnesses. When behavior is uncertain, settle one reachable case with a focused check and minimal implementation, then choose the next case from the findings; do not batch tests for an imagined implementation or require universal TDD.
42
- - **Branches.** Exercise reachable empty/duplicate/concurrent/dependency-failure distinctions; no Cartesian product or random/repeated happy paths without a hypothesis.
43
- - **Failure.** Effect.flip for expected failure; Effect.exit for both outcomes. Assert domain identity and preserved state/resources: no partial write, lost value, extra retry or leak. Wording/rejection alone is insufficient; no incidental order assertions.
41
+ - **Contract.** Connect a reachable input to an observable output, so a plausible wrong implementation fails. Use the nearest public interface, not private helpers or new harnesses. When behavior is uncertain, settle one reachable case with a focused check and a minimal implementation. Then choose the next case from the findings; never batch tests for an imagined implementation or require universal TDD.
42
+ - **Branches.** Exercise the reachable distinctions: empty, duplicate, concurrent and dependency failure. Write no Cartesian product, and no random or repeated happy paths without a hypothesis.
43
+ - **Failure.** Use `Effect.flip` for an expected failure and `Effect.exit` for both outcomes. Assert domain identity and preserved state and resources: no partial write, lost value, extra retry or leak. Wording or rejection alone is not enough, and incidental order is no assertion.
44
44
  - **Control.** Run the regression test against the unfixed implementation, and confirm that the intended assertion fails, not setup, imports or compilation. Before a refactor, cover the old behavior first.
45
45
 
46
46
  ## Effect and fixtures
47
47
 
48
- - **Entrypoint.** Plain it: sync/Promise public functions. it.effect(name, () => effect): virtual services; it.live: real services. Return Effect from a callback, no runner wrapper. it.layer caches its block context and exposes effect, not live; shared live layers use {excludeTestServices: true}. Verify matched cloned-source APIs/imports.
49
- - **Lifetime.** it.effect/live supply case Scope; it.layer acquisition belongs to its block. Use scoped platform resources, no redundant whole-case Effect.scoped. To assert cleanup, close the smaller operation scope before inspection.
50
- - **Isolation.** Shared layers share mutable services/TestClock/TestConsole; Layer.fresh does not reset cached context. Distinct keys, public reset or case-local fixtures; cases pass alone/together, never depend on earlier output.
51
- - **Clock.** TestClock/TestConsole from effect/testing. Fork, await a dependency-boundary Deferred carrying the actual key/path, adjust time, join; forking alone is not readiness. JavaScript timers/sockets/processes need live services, not TestClock.
52
- - **Concurrency.** Dependency entered/release pair: await entry, start competing action, release, assert contract. Set Effect.all concurrency for overlap. Cancellation: await acquisition, interrupt and await completion; unrelated outer Scope stays open. Don't test primitives/incidental ordering.
53
- - **Boundary.** Double only dependencies outside tested logic, via Layer/public parameter. SDK/process/filesystem/HTTP/browser/package integration claims require the real boundary, not matching mocks/spies.
54
- - **Artifacts.** Public-tool proof uses real packing/declared dependencies, not source imports/stubs. Generate fixtures with the real generator after one representative input settles; never alter expected output to fit a bug.
55
- - **Platform.** FileSystem.layerNoop is not memory storage; HttpServer.layerServices supplies no filesystem. Use platform Layer/scoped paths. RpcTest bypasses serialization; HttpApiTest bypasses sockets while testing routing/encoding/middleware/decoding. Neither proves deployment/external integration.
48
+ - **Entrypoint.** Plain `it` tests sync and Promise public functions. `it.effect(name, () => effect)` runs with virtual services and `it.live` with real ones. Return the Effect from the callback, with no runner wrapper. `it.layer` caches its block context and exposes `effect`, not `live`; shared live layers use `{excludeTestServices: true}`. Check APIs and imports against the cloned source.
49
+ - **Lifetime.** `it.effect` and `it.live` supply a Scope per case; `it.layer` acquisition belongs to its block. Use scoped platform resources and no redundant whole-case `Effect.scoped`. To assert cleanup, close the smaller operation scope before you inspect.
50
+ - **Isolation.** Shared layers share mutable services, `TestClock` and `TestConsole`, and `Layer.fresh` does not reset cached context. Use distinct keys, a public reset or case-local fixtures. Cases pass alone and together, and never depend on earlier output.
51
+ - **Clock.** Take `TestClock` and `TestConsole` from `effect/testing`. Fork, await a `Deferred` at the dependency boundary that carries the actual key or path, adjust time, then join; forking alone is not readiness. JavaScript timers, sockets and processes need live services, not `TestClock`.
52
+ - **Concurrency.** Give the dependency an entered and release pair: await entry, start the competing action, release, then assert the contract. Set `Effect.all` concurrency for overlap. For cancellation, await acquisition, interrupt and await completion; an unrelated outer Scope stays open. Never test primitives or incidental ordering.
53
+ - **Boundary.** Double only dependencies outside the tested logic, through a Layer or a public parameter. A claim about an SDK, process, filesystem, HTTP, browser or package integration needs the real boundary, not matching mocks or spies.
54
+ - **Artifacts.** Prove a public tool with real packing and declared dependencies, not source imports or stubs. Generate fixtures with the real generator after one representative input settles; never alter expected output to fit a bug.
55
+ - **Platform.** `FileSystem.layerNoop` is not memory storage, and `HttpServer.layerServices` supplies no filesystem; use a platform Layer and scoped paths. `RpcTest` bypasses serialization, and `HttpApiTest` bypasses sockets while it tests routing, encoding, middleware and decoding. Neither proves deployment or an external integration.
56
56
 
57
57
  ## Run and reconcile
58
58
 
59
59
  - **Run.** Use the documented test selectors and confirm that they collect and execute the intended cases. Zero collected tests, setup alone or exit code 0 alone prove nothing.
60
- - **Inventory.** Collect independent failures once instead of cancelling the suite at the first failure. Distinguish separate cases from repeated observations. Rerun a timed-out test once in isolation; a pass proves that run, not the cause of the timeout. Do not call a bypassed selector or a skipped operation flaky.
60
+ - **Inventory.** Collect independent failures once instead of cancelling the suite at the first failure. Distinguish separate cases from repeated observations. Rerun a timed-out test once in isolation; a pass proves that run, not the cause of the timeout. Never call a bypassed selector or a skipped operation flaky.
61
61
  - **Evidence.** Preserve the first failure, exact command, execution count and exit status. Separate cause from hypothesis, product defect from setup failure, and a skipped criterion from a passing one. A source read or overall green command never substitutes for a missing behavior check.
62
62
  - **Stable inputs.** A check proves only the source, dependencies and configuration it ran on; an edit to them invalidates its result.
63
63
  - **Final proof.** Reconcile every required behavior on the final code. Screenshots and video prove visible outcomes; execution through the public interface proves the rest.