@orkestrel/scaffold 0.0.33 → 0.0.36

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 (45) hide show
  1. package/dist/host/agents/orchestration.md +28 -12
  2. package/dist/host/agents/skills/enterprise-bootstrap/SKILL.md +146 -194
  3. package/dist/host/agents/skills/enterprise-bootstrap/references/bootstrap-reference.md +29 -22
  4. package/dist/host/agents/skills/enterprise-bootstrap/references/components.md +31 -4
  5. package/dist/host/agents/skills/enterprise-bootstrap/references/frontend-design.md +103 -33
  6. package/dist/host/agents/skills/enterprise-bootstrap/references/utilities.md +1 -1
  7. package/dist/host/agents/skills/orkestrel-build-application/references/application.md +2 -2
  8. package/dist/host/agents/skills/orkestrel-debrief/SKILL.md +2 -1
  9. package/dist/host/agents/skills/orkestrel-falsify/SKILL.md +21 -3
  10. package/dist/host/agents/skills/orkestrel-falsify/agents/openai.yaml +4 -0
  11. package/dist/host/agents/skills/orkestrel-falsify/references/brief.md +7 -7
  12. package/dist/host/agents/skills/orkestrel-falsify/references/reconcile.md +10 -2
  13. package/dist/host/agents/skills/orkestrel-human-journey/SKILL.md +124 -0
  14. package/dist/host/agents/skills/orkestrel-human-journey/agents/openai.yaml +4 -0
  15. package/dist/host/agents/skills/orkestrel-human-journey/references/captures.md +74 -0
  16. package/dist/host/agents/skills/orkestrel-human-journey/references/layer.md +131 -0
  17. package/dist/host/claude/agents/analyst.md +4 -4
  18. package/dist/host/claude/agents/codex.md +4 -4
  19. package/dist/host/claude/agents/grok.md +4 -4
  20. package/dist/host/claude/agents/sol.md +56 -0
  21. package/dist/host/claude/rules/application.md +5 -3
  22. package/dist/host/claude/rules/documentation.md +6 -3
  23. package/dist/host/claude/rules/patterns.md +10 -0
  24. package/dist/host/claude/rules/quality.md +5 -4
  25. package/dist/host/claude/rules/tests.md +17 -12
  26. package/dist/host/claude/settings.json +94 -5
  27. package/dist/host/claude/skills/orkestrel-human-journey/SKILL.md +10 -0
  28. package/dist/host/claude/skills/orkestrel-polish-surface/SKILL.md +1 -1
  29. package/dist/host/codex/agents/grok.toml +1 -1
  30. package/dist/host/codex/agents/opus.toml +3 -3
  31. package/dist/host/codex/agents/planner.toml +1 -1
  32. package/dist/host/codex/agents/reviewer.toml +1 -1
  33. package/dist/host/dotfiles/gitignore +3 -0
  34. package/dist/host/manifest.json +41 -1
  35. package/dist/host/scripts/codex.sh +0 -0
  36. package/dist/host/scripts/cursor.sh +0 -0
  37. package/dist/host/scripts/deps.sh +0 -0
  38. package/dist/host/scripts/ollama.sh +0 -0
  39. package/dist/host/tests/policy.test.ts +33 -0
  40. package/dist/host/tests/setupPolicy.ts +319 -2
  41. package/dist/src/core/index.cjs +1 -1
  42. package/dist/src/core/index.cjs.map +1 -1
  43. package/dist/src/core/index.js +1 -1
  44. package/dist/src/core/index.js.map +1 -1
  45. package/package.json +2 -2
@@ -79,8 +79,6 @@ CDN (5.3.8 is the current — and final — 5.3.x patch before 5.4):
79
79
  <div class="row gx-5 gy-3">Independent horizontal/vertical gutters</div>
80
80
  ```
81
81
 
82
- Mobile first: write for the smallest screen, add `sm`/`md`/`lg`/`xl`/`xxl` modifiers upward. Test every breakpoint you claim.
83
-
84
82
  ## Color Modes (light / dark / custom)
85
83
 
86
84
  The 5.3 color-mode system replaces the old per-component dark variants.
@@ -90,7 +88,7 @@ The 5.3 color-mode system replaces the old per-component dark variants.
90
88
  - `data-bs-theme="light|dark"` on `<html>` sets the mode globally; on any element it scopes the mode to that subtree (nested scopes win over ancestors). Default is light.
91
89
  - Mode switching works by re-pointing root CSS variables — components never change their own rules. Core variables swapped per mode: `--bs-body-bg`, `--bs-body-color`, `--bs-emphasis-color`, `--bs-secondary-color`, `--bs-secondary-bg`, `--bs-tertiary-color`, `--bs-tertiary-bg`, `--bs-border-color`, `--bs-heading-color`, `--bs-link-color`.
92
90
  - Each theme color also gets a mode-adaptive triplet — `--bs-{color}-text-emphasis`, `--bs-{color}-bg-subtle`, `--bs-{color}-border-subtle` — surfaced as `.text-{color}-emphasis`, `.bg-{color}-subtle`, `.border-{color}-subtle`. These are the workhorses for status UI that must read in both modes.
93
- - **The triplet is a recipe, not a guarantee.** `text-{color}-emphasis` on `bg-{color}-subtle` is _designed_ to pass, and it usually does in stock Bootstrap — but the values are tokens, and a compatible skin redefines them. Resolve the actual computed values from the compiled cascade the page loads (the shipped CSS, dependency stylesheets included) and measure each pairing once per theme before you rely on it. A class with no rule of its own may still inherit one; documentation memory decides nothing.
91
+ - **The triplet is a recipe, not a guarantee.** `text-{color}-emphasis` on `bg-{color}-subtle` is _designed_ to pass, and it usually does in stock Bootstrap — but the values are tokens, and a compatible skin redefines them. Resolve the actual computed values from the compiled cascade the page loads (the shipped CSS, dependency stylesheets included) and measure each pairing once per theme before you rely on it. A class with no rule of its own may still inherit one; never accept a value from documentation.
94
92
  - Deprecated by this system: `.navbar-dark`, `.dropdown-menu-dark`, `.btn-close-white`, `.carousel-dark` → put `data-bs-theme="dark"` on the component or an ancestor instead.
95
93
 
96
94
  ### Author rules
@@ -337,19 +335,28 @@ Dropdowns, tooltips, and popovers require Popper — load `bootstrap.bundle.min.
337
335
 
338
336
  ### Baseline (every screen)
339
337
 
340
- - Skip link (`.visually-hidden-focusable`) to `<main>`; landmarks (`nav`, `main`, `aside`); heading order `h1 h2 h3` without skips.
341
- - `aria-label` on icon-only controls; `aria-current="page"` on active nav; `aria-selected` on active tabs; `aria-expanded` + `aria-controls` on disclosure triggers; `aria-describedby` for help/errors.
342
- - Visible focus everywhere keep Bootstrap's rings; use the `.focus-ring` helper on custom interactive elements instead of removing outlines.
343
- - Meaning never by color alone: pair status color with text, an icon, or a visually-hidden word.
344
- - Body text contrast 4.5:1 (3:1 for large text and UI graphics). Bootstrap's own docs warn parts of the default palette can fall short — verify your combinations; don't assume framework colors pass.
338
+ Hold the baseline in [SKILL.md](../SKILL.md) → Accessibility baseline. Its Bootstrap-specific parts:
339
+
340
+ - Skip link: `.visually-hidden-focusable` to `<main>`. Landmarks: `nav`, `main`, `aside`. Heading order `h1 h2 h3` without skips.
341
+ - Keep Bootstrap's focus rings; use the `.focus-ring` helper on custom interactive elements instead of removing outlines.
342
+ - `.visually-hidden` for screen-reader-only text; `.visually-hidden-focusable` for skip links. Never combine the two.
343
+ - Verify every color pairing against the shipped cascade. Bootstrap's own docs warn that parts of the default palette fall short.
344
+
345
+ **Measuring the bars:**
346
+
347
+ - Hold the bars from [SKILL.md](../SKILL.md) → Surfaces, color, contrast: **≥ 4.5:1** for everything information-bearing, **≥ 3:1** for textless marks and state chrome. WCAG 2.2 permits 3:1 for large text; this package does not — size grants no lower tier.
348
+ - Measure in **both themes**, from the compiled cascade, never from the token names. A pairing that passes in light routinely fails in dark, and a skin's values are its own.
349
+ - Focus rings and hover fills are UI graphics: they are in scope for the 3:1 bar.
350
+ - Disabled controls are exempt from the bars by the spec. That exemption covers legibility, not meaning — see [Destructive actions](#destructive-actions) for the one disabled state that still has to change color.
351
+
352
+ **The instrument.** Bootstrap paints in translucent layers: a card header and footer are a 3% tint of the body color over the card's own background. A reader that stops at the first painted ancestor and drops its alpha treats that tint as full-strength paint, and is then wrong in **both** directions — it green-lights a pairing nobody can read, and it red-flags one that reads fine. Use a reader that:
345
353
 
346
- **Measuring the bars (the part that gets skipped):**
354
+ - collects every painted layer from the element upward to the first opaque one, then composites them top over bottom (Porter-Duff `over`) onto that opaque base;
355
+ - composites a translucent foreground over that result before taking the ratio, rather than reading the declared color;
356
+ - measures both themes in one run, since the theme swap re-points the tokens under every layer;
357
+ - carries a negative control drawn from outside the population it covers — a pairing known to fail — and voids the run if that control passes.
347
358
 
348
- - Measure in **both themes**, from the compiled cascade, not from the token names. A pairing that passes in light routinely fails in dark, and a skin's values are its own.
349
- - **≥ 4.5:1** for everything information-bearing — including `small`, captions, meta lines, and timestamps. Small size is not a licence for a lower tier; `text-body-tertiary` is decoration, `text-body-secondary` is the floor for text a user must read.
350
- - **≥ 3:1** for textless marks and state indicators — status glyphs, rings, dividers that carry meaning — and for the hover/focus chrome that signals state. Focus rings and hover fills are UI graphics: they are in scope, and they are the ones nobody measures.
351
- - Disabled controls are exempt from the bars by the spec. That exemption is about legibility, not about meaning: see [Destructive actions](#destructive-actions) for the one disabled state that still has to change color.
352
- - `.visually-hidden` for SR-only text; `.visually-hidden-focusable` for skip links (never combine the two).
359
+ Wire the reader into the suite once it has settled a question.
353
360
 
354
361
  ### WCAG 2.2 deltas that bite dense app UI
355
362
 
@@ -398,7 +405,7 @@ The Bootstrap implementation — a responsive offcanvas that renders inline abov
398
405
  <header class="navbar bg-body-tertiary border-bottom sticky-top">
399
406
  <div class="container-fluid">
400
407
  <button
401
- class="btn btn-outline-secondary d-lg-none"
408
+ class="btn btn-secondary d-lg-none"
402
409
  type="button"
403
410
  data-bs-toggle="offcanvas"
404
411
  data-bs-target="#appSidebar"
@@ -506,20 +513,20 @@ Give header cells an **opaque background** (`bg-body-secondary` or a table varia
506
513
  ### Wizards & multi-step forms
507
514
 
508
515
  - Show step progress: current position, total, and step names ("Step 2 of 4 — Billing"); `list-group-numbered` or a simple nav renders it honestly.
509
- - Validate per-step before advancing failing forward compounds; failing at the end is worse.
516
+ - Validate per step before advancing; never let a step advance carrying invalid data.
510
517
  - Back never loses data. Persist partial state (save-and-resume) for anything beyond ~3 steps or that crosses sessions.
511
518
  - Never re-ask what a previous step collected (Redundant Entry, 3.3.7) — carry it forward or offer "same as above".
512
519
  - Last step: a review summary with per-section edit links, then one clearly-named commit action ("Create account", not "Submit").
513
520
 
514
521
  ### The five states
515
522
 
516
- Design **all five** for every data surface: ideal (populated), empty, loading, partial, error. A component isn't done until all five exist — empty and error are where trust is won or lost.
523
+ Design **all five** for every data surface: ideal (populated), empty, loading, partial, error. A component isn't done until all five exist.
517
524
 
518
525
  - **Skeleton vs spinner:** skeleton (`placeholder` + `placeholder-glow`) when you know the content's shape and it fills a region — tables, cards, detail panes — because it holds layout and shortens perceived wait. Spinner for short, indeterminate, or in-control waits (inside a button, a small inline fetch).
519
526
  - **Thresholds (guidance):** under ~1s show nothing — a flashed loader is worse than none; ~1–10s show a spinner or skeleton; beyond ~10s show determinate progress (percent or step) so it doesn't feel hung.
520
527
  - **Optimistic vs pessimistic:** apply UI immediately and reconcile (rolling back loudly on failure) for reversible high-frequency actions — toggles, stars, reorders. Await confirmation for money, audited records, and anything a rollback would confuse.
521
- - **Empty states** invite the next action (button + one line of why), and filtered-empty differs from never-had-data.
522
- - **Every error state carries a keyboard-reachable retry** and preserves surrounding context — a body fetch failure must not blow away the toolbar and filters.
528
+ - **Empty states** invite the next action (button + one line of why). Never-had-data and filtered-empty are different states with different escapes — never ship one generic "nothing here".
529
+ - **Every error state states what failed and how to fix it**, carries a keyboard-reachable retry in place, and preserves surrounding context — a body fetch failure must not blow away the toolbar and filters.
523
530
 
524
531
  ### Feedback discipline
525
532
 
@@ -540,9 +547,9 @@ Match friction to reversibility × blast radius:
540
547
  2. **Confirm dialog** for irreversible-but-scoped operations. Restate the specific consequence ("This permanently deletes 3 invoices"), verb-labeled buttons ("Delete invoices" / "Cancel" — never Yes/No), destructive action visually separated from safe; `alertdialog` semantics; focus lands on the safe action.
541
548
  3. **Type-to-confirm** (type the entity name) only for high-blast-radius irreversible operations — delete an org, drop a dataset.
542
549
 
543
- Don't type-gate a single-row delete; don't one-tap a tenant wipe. Overused confirmations train the click-through reflex that defeats them.
550
+ Don't type-gate a single-row delete; don't one-tap a tenant wipe. Confirm only where this ladder calls for it — a confirmation on every action gets clicked through.
544
551
 
545
- **A disabled destructive control stops looking destructive.** `btn-danger` at full saturation reads as armed and available whatever the `disabled` attribute says — the loudest control on the screen is the one the user cannot use, and the contrast exemption for disabled controls does not excuse it. While the action is unavailable, neutralize the variant (drop to the neutral/outline variant, or let the disabled state mute the fill) so the color stops promising an action, and say _why_ it is unavailable in text the assistive layer reaches: `aria-describedby` pointing at the reason, with `title` only as the pointer-user convenience on top. A `title` alone is not an explanation — it never reaches a keyboard or screen-reader user, and it disappears on touch.
552
+ **Neutralize a disabled destructive control.** `btn-danger` at full saturation reads as armed whatever the `disabled` attribute says, and the contrast exemption for disabled controls does not excuse it. While the action is unavailable, drop to the neutral or outline variant (or let the disabled state mute the fill) so the color stops promising an action, and say _why_ it is unavailable in text the assistive layer reaches: `aria-describedby` pointing at the reason, with `title` only as the pointer-user convenience on top. Never use `title` alone — it never reaches a keyboard or screen-reader user, and it disappears on touch.
546
553
 
547
554
  ## RTL
548
555
 
@@ -570,7 +577,7 @@ Bootstrap has **no** combobox/autocomplete, date picker, multi-select tags input
570
577
 
571
578
  - **Reach for native first:** `<input type="date">`, `<datalist>` for light autocomplete, `<select multiple>` where acceptable. Native widgets bring keyboard and AT behavior free.
572
579
  - **Reach for an established accessible library second** when the product genuinely needs the richer widget (combobox with async search, spreadsheet grid, drag-reorder tree). Budget for auditing it against the APG contract.
573
- - **Hand-roll last**, only with the APG contract in hand ([Accessibility](#accessibility) → Pattern contracts) and time to implement the _keyboard_ half the visual half is the easy 20%.
580
+ - **Hand-roll last**, only with the APG contract in hand ([Accessibility](#accessibility) → Pattern contracts) and budget for the _keyboard_ half, which is most of the work.
574
581
  - Never fake it: a `.dropdown-menu` posing as a select, a `<div>` grid with click handlers, or a scroll-anchor "wizard" each break keyboard and AT users in ways a demo never shows.
575
582
 
576
583
  ## Common Layout Patterns
@@ -112,6 +112,8 @@ Variants: `.accordion-flush` (edge-to-edge, no outer borders); omit `data-bs-par
112
112
 
113
113
  `role="alert"` announces immediately when the element is injected into the DOM — right for errors and warnings. For calm status messages injected dynamically, prefer a polite live region (`role="status"`). Anything that _looks_ like an alert carries the alert role: styling and semantics disagree the moment a notice wears `.alert` chrome with no role, and an accessibility snapshot is what catches it. When to use alert vs toast vs banner: [bootstrap-reference.md](bootstrap-reference.md) → Feedback discipline.
114
114
 
115
+ An alert is a subtle fill — apply the subtle-fill degradation rule to everything inside it ([SKILL.md](../SKILL.md) → Surfaces, color, contrast).
116
+
115
117
  ### Badge
116
118
 
117
119
  ```html
@@ -186,6 +188,8 @@ The current page is `aria-current="page"` and not a link. Use breadcrumbs only f
186
188
 
187
189
  Icon-only buttons need `aria-label` and a ≥24×24 px target (WCAG 2.2) — `btn-sm` icon clusters in toolbars are the common violation; pad rather than shrink.
188
190
 
191
+ Choose the variant by contrast rather than by taste ([SKILL.md](../SKILL.md) → Hierarchy & actions).
192
+
189
193
  ### Button Group
190
194
 
191
195
  ```html
@@ -400,6 +404,29 @@ Multiple targets: give each panel `.multi-collapse` and point separate triggers
400
404
 
401
405
  ### Modal
402
406
 
407
+ **Build a blocking dialog on the native `<dialog>`.** `showModal()` brings focus containment, Esc, an inert background, and top-layer stacking from the platform — nothing to construct, nothing to dispose when the view unmounts, and no JS instance for a virtual-DOM framework to fight with over the same nodes. Leave the element itself unpainted and put Bootstrap chrome inside it:
408
+
409
+ ```html
410
+ <dialog class="p-0 border-0 bg-transparent" role="alertdialog" aria-labelledby="confirmHeading">
411
+ <div class="card shadow">
412
+ <div class="card-header">
413
+ <h2 id="confirmHeading" class="h5 mb-0">Delete invoice</h2>
414
+ </div>
415
+ <div class="card-body">
416
+ <p class="card-text mb-0">This permanently deletes INV-1042.</p>
417
+ </div>
418
+ <div class="card-footer d-flex flex-wrap justify-content-end gap-2">
419
+ <button type="button" class="btn btn-secondary">Keep</button>
420
+ <button type="button" class="btn btn-danger">Delete invoice</button>
421
+ </div>
422
+ </div>
423
+ </dialog>
424
+ ```
425
+
426
+ `role="alertdialog"` for a destructive confirm, `role="dialog"` otherwise; `aria-labelledby` points at the heading. The element's own `close` event is where the host clears the state that opened it, so Esc and the buttons all close by one path. The scrim is the UA's `::backdrop`, which no Bootstrap class touches — restyling it is a rung-4 decision.
427
+
428
+ Bootstrap's `.modal` is the answer when the project already drives its dialogs through Bootstrap's JS:
429
+
403
430
  ```html
404
431
  <div
405
432
  class="modal fade"
@@ -467,7 +494,7 @@ Bootstrap's modal enforces focus, adds `role="dialog"`/`aria-modal="true"`, clos
467
494
  </ul>
468
495
  <form class="d-flex" role="search">
469
496
  <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search" />
470
- <button class="btn btn-outline-success" type="submit">Search</button>
497
+ <button class="btn btn-success" type="submit">Search</button>
471
498
  </form>
472
499
  </div>
473
500
  </div>
@@ -941,7 +968,7 @@ The textless mark that survives both themes — dots, ticks, rings, pulses — i
941
968
  <span class="bi bi-circle fs-6 lh-1 text-body-secondary" role="img" aria-label="Not started"></span>
942
969
  ```
943
970
 
944
- - **Color from the emphasis tokens.** `text-*-emphasis` is the mode-adaptive tier built for marks on subtle surfaces; the plain `text-*` colors are tuned for light and thin out in dark. Measure every mark at **≥ 3:1** against the surface it sits on, **in both themes**, against the compiled cascade — a skin's token values are its own.
971
+ - **Color from the emphasis tokens.** `text-*-emphasis` is the mode-adaptive tier built for marks on subtle surfaces; the plain `text-*` colors are tuned for light and thin out in dark. On a filled surface — `.active`, `.bg-primary`, `text-bg-*` — drop the tone class instead and let the fill's contrast color take the glyph ([Selection fills](#selection-fills)). Measure every mark at **≥ 3:1** against the surface it sits on, **in both themes**, against the compiled cascade — a skin's token values are its own.
945
972
  - **Filled and hollow say different things** — done vs pending, live vs idle — so pair glyphs that share one advance width (a filled/hollow pair from the same icon family). Mixed widths make a column of marks jitter row to row.
946
973
  - **Size with `fs-*` _and_ `lh-1`.** A glyph inherits the row's line-height, so an `fs-*` bump without `lh-1` grows the line box and pushes the row taller than its neighbors.
947
974
  - Give the mark an accessible name (`role="img"` + `aria-label`, or a `.visually-hidden` word next to an `aria-hidden` glyph) — a mark whose only meaning is its color and shape is color-only status.
@@ -961,7 +988,7 @@ The textless mark that survives both themes — dots, ticks, rings, pulses — i
961
988
  | Long documentation in-product | `accordion` or scrollable `modal` | One infinite tinted card stack |
962
989
  | Dense data | `table` + `table-responsive` (+ `table-sm` when appropriate) | Non-semantic grids of text |
963
990
  | Choosing a form value | `form-select` (or native input) | A `dropdown` menu posing as an input |
964
- | Confirmations / focused tasks | `modal` with header, body, footer actions | Nested modals |
991
+ | Confirmations / focused tasks | native `<dialog>` with header, body, footer actions | Nested modals |
965
992
  | Secondary filters on small screens | `offcanvas` | Permanent wide sidebars that crush content |
966
993
  | Transient success feedback | `toast` | `alert()`; toasts for errors |
967
994
  | Loading a known layout | `placeholder` skeleton | Layout-collapsing centered spinner |
@@ -977,7 +1004,7 @@ The textless mark that survives both themes — dots, ticks, rings, pulses — i
977
1004
 
978
1005
  A selected row, pill, or filter chip repaints everything inside it — marks included. Two traps, both invisible until the selected state is captured in both themes:
979
1006
 
980
- - **A mark on an active fill of the same family disappears.** `.active` on a `list-group-item`, `nav-pill`, or `page-item` sets the item's own color, and a `text-bg-primary`-family mark inside it inherits or loses to that fill — the mark is there in the markup and gone on screen. `text-body-emphasis` (or an outline glyph that keeps its own token) survives the fill; verify by capturing the selected row, not by reading the class list.
1007
+ - **A mark on an active fill of the same family disappears.** `.active` on a `list-group-item`, `nav-pill`, or `page-item` sets the item's own color, and a `text-bg-primary`-family mark inside it inherits or loses to that fill — present in the markup, gone on screen. Carry no tone class inside the fill ([SKILL.md](../SKILL.md) Surfaces, color, contrast). Verify by capturing the selected row, not by reading the class list.
981
1008
  - **`btn-check` filter labels invert in dark.** A `btn-outline-secondary` label reads as "chosen" in light and as "muted" in dark, because the checked fill and the surface swap relative weight. Give chosen filters an accent variant (a real theme color) rather than the neutral outline, so "chosen" reads the same way in both modes.
982
1009
 
983
1010
  Exactly one item in a selection carries `aria-current` — the visual fill and the announced state must be the same item.
@@ -4,56 +4,126 @@
4
4
  > process, and copy guidance — use when setting visual direction.
5
5
  > Operate layer: [SKILL.md](../SKILL.md).
6
6
 
7
- Approach this as the design lead at a small studio known for giving every client a visual identity that could not be mistaken for anyone else's. This client has already rejected proposals that felt templated, and is paying for a distinctive point of view: make deliberate, opinionated choices about palette, typography, and layout that are specific to this brief, and take one real aesthetic risk you can justify.
7
+ Give the surface a visual identity that could not be mistaken for anyone else's, and reject any
8
+ direction that reads as templated. Make deliberate, opinionated choices about palette, typography,
9
+ and layout that are specific to this brief, and take one real aesthetic risk you can justify.
8
10
 
9
11
  ## Ground it in the subject
10
12
 
11
- If the brief does not pin down what the product or subject is, pin it yourself before designing: name one concrete subject, its audience, and the page's single job, and state your choice. If there's any information in your memory about the human's preferences, context about what they're building, or designs you've made before — use that as a hint. The subject's own world, its materials, instruments, artifacts, and vernacular, is where distinctive choices come from. Build with the brief's real content and subject matter throughout.
13
+ Pin the subject before designing whenever the brief leaves it open: name one concrete subject, its
14
+ audience, and the page's single job, and state the choice. Use what you know of the user's
15
+ preferences, of what they are building, and of designs you have made for them before as hints, never
16
+ as templates. Draw the distinctive choices from the subject's own world — its materials,
17
+ instruments, artifacts, and vernacular. Build with the brief's real content and subject matter
18
+ throughout.
12
19
 
13
20
  ## Design principles
14
21
 
15
- For web designs, the hero is a thesis. Open with the most characteristic thing in the subject's world, in whatever form makes sense for it: a headline, an image, an animation, a live demo, an interactive moment. Be deliberate with your choice: a big number with a small label, supporting stats, and a gradient accent is the template answeronly use it if that's truly the best option.
22
+ Open a web design's hero with the subject's thesis the one claim the page makescarried by the
23
+ most characteristic thing in the subject's world, in whatever form suits it: a headline, an image,
24
+ an animation, a live demo, an interactive moment. Choose that opening deliberately — a big number
25
+ with a small label, supporting stats, and a gradient accent is the template answer, so take it only
26
+ where it is genuinely the best option.
16
27
 
17
- Typography carries the personality of the page. Pair the display and body faces deliberately, not the same families you would reach for on any other project, and set a clear type scale with intentional weights, widths, and spacing. Make the type treatment itself a memorable part of the design, not a neutral delivery vehicle for the content.
28
+ Set the typography as a decision rather than a default. Pair the display and body faces
29
+ deliberately, and not the families you would reach for on any other project. Set a clear type scale
30
+ with intentional weights, widths, and spacing. Make the type treatment one of the things the design
31
+ is remembered by.
18
32
 
19
- Structure is information. Structural devices — numbering, eyebrows, dividers, labels — should encode something true about the content, not decorate it. Many generic designs use numbered markers (01 / 02 / 03), but that's only appropriate if the content actually is a sequence, like a real process or a typed timeline where order carries information the reader needs. Question whether choices like numbered markers actually make sense before incorporating them.
33
+ Make every structural device — numbering, eyebrows, dividers, labels — encode something true about
34
+ the content rather than decorate it. Use numbered markers (01 / 02 / 03) only where the content is
35
+ a sequence: a real process, or a typed timeline whose order carries information the reader needs.
36
+ Before adding a device, check that it encodes something the reader needs.
20
37
 
21
- Leverage motion deliberately. Think about where and whether animation can serve the subject: a page-load sequence, a scroll-triggered reveal, hover micro-interactions, ambient atmosphere. An orchestrated moment usually lands harder than scattered effects; choose what the direction calls for. Sometimes less is more — extra animation is one of the fastest ways to make a design feel AI-generated.
38
+ Decide where and whether animation serves the subject: a page-load sequence, a scroll-triggered
39
+ reveal, hover micro-interactions, ambient atmosphere. Prefer one orchestrated moment to scattered
40
+ effects, and follow the direction where it calls for something else. Cut animation the direction
41
+ does not need — extra animation is one of the fastest ways to make a design read as AI-generated.
22
42
 
23
- Match complexity to the vision. Maximalist directions need elaborate execution; minimal directions need precision in spacing, type, and detail. Elegance is executing the chosen vision well.
43
+ Match complexity to the vision. Maximalist directions need elaborate execution; minimal directions
44
+ need precision in spacing, type, and detail.
24
45
 
25
- Consider written content carefully. A design brief often contains no real content, and it's up to you to come up with copy. Copy can make a design feel as templated as the layout itself. See the writing section below.
46
+ Write the copy yourself when the brief supplies none, and treat it as design material: templated
47
+ copy makes a surface read as templated as a templated layout does. Follow the writing rules below.
26
48
 
27
49
  ## Where the signature lives in product UI
28
50
 
29
- The same craft applies to dense, authenticated tools but the signature moves. In an admin screen or dashboard, the data is the content and must stay quiet, legible, and fast to scan; spending the aesthetic risk on the table itself taxes every user on every visit. Put the point of view in the chrome instead: the navigation and header treatment, the type pairing, the empty states, the way status and density are handled. A distinctive product UI is one whose _frame_ could not be mistaken for another product while its data surfaces stay disciplined and conventional enough to disappear into use.
51
+ Apply the same craft to dense, authenticated tools, and move the signature. In an admin screen or
52
+ dashboard the data is the content: keep it quiet, legible, and fast to scan, and never spend the
53
+ aesthetic risk on the table itself, which adds scan time for every user on every visit. Put the
54
+ point of view in the chrome — the navigation and header treatment, the type pairing, the empty
55
+ states, the handling of status and density. Make the frame impossible to mistake for another
56
+ product's, and keep the data surfaces disciplined and conventional enough to read without effort.
30
57
 
31
58
  ## Process: brainstorm, explore, plan, critique, build, critique again
32
59
 
33
- For calibration: AI-generated design right now clusters around three looks: (1) a warm cream background (near #F4F1EA) with a high-contrast serif display and a terracotta accent; (2) a near-black background with a single bright acid-green or vermilion accent; (3) a broadsheet-style layout with hairline rules, zero border-radius, and dense newspaper-like columns. All three are legitimate for some briefs, but they are defaults rather than choices, and they appear regardless of subject. Where the brief pins down a visual direction, follow it exactly — the brief's own words always win, including when it asks for one of these looks. Where it leaves an axis free, don't spend that freedom on one of these defaults. Just like a hired human designer, there's a careful balance between doing what you're good at and taking each project as a chance to experiment and learn.
34
-
35
- Work in two passes. First, brainstorm a short design plan based on the human's design brief: create a compact token system with color, type, layout, and signature. Color: describe the palette as 4–6 named hex values. Type: the typefaces for 2+ roles (a characterful display face used with restraint, a complementary body face, and a utility face for captions or data if needed). Layout: a layout concept, using one-sentence prose descriptions and ASCII wireframes to ideate and compare. Signature: the single unique element this page will be remembered by, embodying the brief in an appropriate way.
36
-
37
- Then review that plan against the brief before building: if any part of it reads like the generic default you would produce for any similar page (work through a similar prompt to see if you arrive somewhere similar) rather than a choice made for this specific brief — revise that part, and say what you changed and why. Only after you've confirmed the relative uniqueness of your design plan should you start to write the code, following the revised plan exactly and deriving every color and type decision from it.
38
-
39
- When writing the code, be careful structuring your CSS selector specificities. It's easy to generate classes that cancel each other out (especially a type-based selector like `.section` against an element-based selector like `.cta`), and paddings/margins between sections are where it happens most.
40
-
41
- Do a lot of this planning and iteration in your thinking, and only show ideas to the user when you have higher confidence they'll delight.
60
+ Calibrate against the three looks AI-generated design currently clusters around: (1) a warm cream
61
+ background (near #F4F1EA) with a high-contrast serif display and a terracotta accent; (2) a
62
+ near-black background with a single bright acid-green or vermilion accent; (3) a broadsheet-style
63
+ layout with hairline rules, zero border-radius, and dense newspaper-like columns. All three are
64
+ legitimate for some briefs; they are defaults rather than choices, and they appear regardless of
65
+ subject. Follow the brief exactly where it pins a visual direction — the brief's own words always
66
+ win, including when they ask for one of these looks. Where the brief leaves an axis free, spend that
67
+ freedom somewhere other than these defaults. Balance the moves you have already proven against
68
+ experimenting where the brief invites it.
69
+
70
+ Work in two passes. First, brainstorm a short design plan from the brief: a compact token system
71
+ with color, type, layout, and signature. Color: describe the palette as 4–6 named hex values. Type:
72
+ name the typefaces for 2+ roles — a characterful display face used with restraint, a complementary
73
+ body face, and a utility face for captions or data where one is needed. Layout: state a layout
74
+ concept, using one-sentence prose descriptions and ASCII wireframes to ideate and compare.
75
+ Signature: name the single element this page will be remembered by, embodying the brief.
76
+
77
+ Then review that plan against the brief before building. Where a part of it reads like the generic
78
+ default you would produce for any similar page — work through a similar prompt and see whether you
79
+ arrive somewhere similar — revise that part, and say what you changed and why. Start writing code
80
+ only once the plan is specific to this brief, then follow the revised plan exactly and derive every
81
+ color and type decision from it.
82
+
83
+ Structure your CSS selector specificities deliberately when writing the code. Classes cancel each
84
+ other out easily, especially a type-based selector like `.section` against an element-based selector
85
+ like `.cta`, and the padding and margin between sections is where it happens most.
86
+
87
+ Do this planning and iteration in your thinking. Show the user a direction only once it satisfies
88
+ the brief and the quality floor below.
42
89
 
43
90
  ## Restraint and self-critique
44
91
 
45
- Spend your boldness in one place. Let the signature element be the one memorable thing, keep everything around it quiet and disciplined, and cut any decoration that does not serve the brief. Not taking a risk can be a risk itself! Build to a quality floor without announcing it: responsive down to mobile, visible keyboard focus, reduced motion respected. Critique your own work as you build, taking screenshots if your environment supports it — a picture is worth 1000 tokens, and it is the only thing that can tell you whether the design you wrote is the design that rendered. Look at both themes and both the wide and the narrow viewport; a treatment that only exists in the markup is not a treatment yet. Consider Chanel's advice: before leaving the house, look in the mirror and remove one accessory. Human creators have memory and always try to do something new; if you have a place to jot down notes about what you've tried, it will help future passes.
46
-
47
- ## More on writing in design
48
-
49
- Words appear in a design for one reason: to make it easier to understand, and therefore easier to use. They are design material, not decoration. Bring the same intentionality to copy that you bring to spacing and color. Before writing anything, ask what the design needs to say, and how it can best be said to help the person navigate the experience.
50
-
51
- Write from the end user's side of the screen. Name things by what people control and recognize, never by how the system is built. A person manages notifications, not webhook config. Describe what something does in plain terms rather than selling it. Being specific is always better than being clever.
52
-
53
- Use active voice as default. A control should say exactly what happens when it's used: "Save changes," not "Submit." An action keeps the same name through the whole flow, so the button that says "Publish" produces a toast that says "Published." The vocabulary of an interface is the signposting for someone navigating the product. Cohesion and consistency are how people learn their way around.
54
-
55
- Treat failure and emptiness as moments for direction, not mood. Explain what went wrong and how to fix it, in the interface's voice rather than a person's. Errors don't apologize, and they are never vague about what happened. An empty screen is an invitation to act.
56
-
57
- Keep the register conversational and tuned: plain verbs, sentence case, no filler, with tone matched to the brand and the audience. Let each element do exactly one job. A label labels, an example demonstrates, and nothing quietly does double duty.
58
-
59
- Brevity on a control is not the same as vagueness. Where the surrounding context already names the object, the visible label can be a single word and stay unambiguous the specific phrase then lives in the control's accessible name, so nothing is lost for someone who arrives without the context. The same discipline governs the visual vocabulary: a glyph is a word, and a word means one thing. Once a mark stands for "finished" it cannot also stand for "selected" three panels over, or the reader has to relearn the language on every screen.
92
+ Spend the boldness in one place. Let the signature element be the one memorable thing, keep
93
+ everything around it quiet and disciplined, and cut any decoration that does not serve the brief —
94
+ decorative emoji as UI, pill soup, glow effects, and gradient-on-everything are the usual instances
95
+ of decoration with no reason in the subject. Treat a surface with no deliberate risk as failing the
96
+ distinctiveness mandate. Meet the quality floor without announcing it: responsive down to mobile,
97
+ visible keyboard focus, reduced motion respected. Critique your own work as you build, and take
98
+ screenshots where the environment supports it. Read both themes and both the wide and the narrow
99
+ viewport from those captures, not the markup. Before shipping, remove one accessory: cut the
100
+ least-necessary decorative element, and restore it only where the surface demonstrably loses
101
+ information without it. Where notes persist across passes, record what you tried so the next pass
102
+ reads it.
103
+
104
+ ## Writing in design
105
+
106
+ Keep a word only where it makes the design easier to understand, and therefore easier to use. Bring
107
+ the same intentionality to copy as to spacing and color. Before writing anything, decide what the
108
+ design needs to say, and how to say it so the person can navigate the experience.
109
+
110
+ Write from the end user's side of the screen. Name things by what people control and recognize,
111
+ never by how the system is built: a person manages notifications, not webhook config. Describe what
112
+ something does in plain terms rather than selling it, and choose the specific word over the clever
113
+ one.
114
+
115
+ Use the active voice by default. Make a control say exactly what happens when it is used: "Save
116
+ changes," not "Submit." Keep an action's name through the whole flow, so the button that says
117
+ "Publish" produces a toast that says "Published." Hold one vocabulary across every screen.
118
+
119
+ Give failure and emptiness direction rather than mood. State what went wrong and how to fix it, in
120
+ the interface's voice rather than a person's, without apology and without vagueness about what
121
+ happened. Name the action that fills an empty screen.
122
+
123
+ Keep the register conversational and tuned: plain verbs, sentence case, no filler, tone matched to
124
+ the brand and the audience. Give each element exactly one job: a label labels, an example
125
+ demonstrates, and nothing does double duty.
126
+
127
+ Keep a short control label unambiguous. Where the surrounding context already names the object, make
128
+ the visible label a single word and carry the specific phrase in the control's accessible name, so
129
+ nothing is lost for someone who arrives without that context.
@@ -301,7 +301,7 @@ Helpers are single-purpose classes that sit alongside utilities.
301
301
 
302
302
  - **Spacing scale:** prefer `gap-*` on flex/grid parents over scattering `m-*` on every child — the parent owns rhythm, children stay reorderable. Use `p-3` / `p-4` for panel padding; reserve `p-5` for sparse marketing-like empty states.
303
303
  - **Body surfaces:** `bg-body`, `bg-body-secondary`, `bg-body-tertiary` track `data-bs-theme` — raw `bg-white` / `bg-light` freeze the surface in light mode.
304
- - **Text hierarchy:** `text-body` for content, `text-body-secondary` for meta, `text-*-emphasis` when a status must stay readable on subtle backgrounds. `text-body-tertiary` is the decoration tier — it misses the 4.5:1 bar for information-bearing small text, so anything a user must read is `text-body-secondary` or better.
304
+ - **Text hierarchy:** `text-body` for content, `text-body-secondary` for meta, `text-*-emphasis` for any status a reader acts on. The plain `text-success` / `text-danger` / `text-warning` colors and `text-body-tertiary` are the decoration tier ([SKILL.md](../SKILL.md) → Surfaces, color, contrast).
305
305
  - **Opacity traps:** `text-white-50` / `text-black-50` often fail contrast — prefer `text-opacity-75` on a known solid, or `text-body-secondary`. Every one of these pairings is measured against the shipped cascade in both themes; a skin retunes the same token names.
306
306
  - **Flex floors:** a flex column gives its items an automatic minimum size, and `text-truncate` removes it. Titles and marks that must keep their height carry `flex-shrink-0`; only the growing sibling absorbs the slack.
307
307
  - **Flex toolbars:** `d-flex align-items-center gap-2 flex-wrap` (or `flex-nowrap overflow-auto` for dense bars). Equal-height siblings: `align-items-stretch` + `h-100` on cards.
@@ -35,8 +35,8 @@ include app/core so shared transport contracts have one host-independent owner.
35
35
  - Types, constants, helpers, validators, parsers, and factories live in their
36
36
  centralized kind files; an implementation file holds one class plus imports.
37
37
  `ApplicationServerRunner` lives alone in `ApplicationServerRunner.ts` and
38
- `startApplicationServer` in `factories.ts`; `main.ts` owns no reusable
39
- declarations.
38
+ `startApplicationServer` in `handlers.ts`, because `factories.ts` admits only
39
+ `create`-prefixed construction; `main.ts` owns no reusable declarations.
40
40
  - Enforcement is layered, and each layer owns exactly what it can express:
41
41
  - `.oxlintrc.json` `no-restricted-imports` owns **literal-string** declared
42
42
  package, alias, and conventional relative imports, in both directions.
@@ -16,7 +16,8 @@ Read the current files in this order:
16
16
  before auditing the agent/rule/skill/process layer;
17
17
  [field-testing.md](references/field-testing.md) before running or judging a live field
18
18
  pass of an agent-facing surface.
19
- 4. `guides/README.md`, the governing guides for what the campaign built, and `ROADMAP.md`.
19
+ 4. `guides/README.md`, the governing guides for what the campaign built, and `ROADMAP.md` when
20
+ the repository keeps one.
20
21
 
21
22
  The user's current instruction wins. The debrief judges the artifact and the process that
22
23
  produced it; neither is exempt. Capture successes as deliberately as mistakes, and codify
@@ -75,6 +75,16 @@ nobody claimed.
75
75
  engine is dark; do not restate them here.
76
76
  - A round run with one lane is a deviation. Record it rather than glossing it. If an engine is
77
77
  unavailable, the remaining engine runs both lanes — it never drops one.
78
+ - **Pair every finder with an independent refuter when the round fans out past two lanes.** The
79
+ refuter receives one slice's findings, never that finder's work, and is briefed to BREAK them
80
+ rather than to re-audit the subject. It reproduces each stated vector itself and defaults to
81
+ refuted when uncertain.
82
+ - Refute on any of six grounds, and name which: the vector does not reproduce; the behaviour is
83
+ correct and documented; it is unreachable through the public API or a documented seam; it asks
84
+ for new capability rather than naming a defect; it restates a finding an earlier round
85
+ repaired; or its diagnosis is wrong — then CONFIRM with the correction.
86
+ - Only a survivor earns a fix unit. An unrefuted finding is a hypothesis. The two scope grounds,
87
+ unreachable and new capability, are what keep a round from drifting into a redesign.
78
88
  - **Give every auditor the means to run its attacks.** A lens that can only read returns derivations,
79
89
  and a derivation reads exactly like a verdict — it will confirm a claim that one probe would break.
80
90
  - **Tell each auditor exactly where a probe may live, and verify that place works before you say it.**
@@ -87,8 +97,9 @@ nobody claimed.
87
97
  concurrent auditor a distinct filename that already satisfies the repository's test naming
88
98
  convention; never invent a prefix to dodge collisions, and never let two auditors claim one path. A
89
99
  probe left in the mirrored suite is discovered and fails a run nobody else caused.
90
- - **Run auditors concurrently only when their writes cannot collide.** Read-only lenses still write
91
- probes; give each a distinct path and forbid whole-project runs, or serialize the round. **This binds
100
+ - **Run auditors concurrently only when their writes cannot collide.** A lens that can execute
101
+ still writes probes; give each a distinct path and forbid whole-project runs, or serialize the
102
+ round. **This binds
92
103
  the orchestrator too:** a tree-wide gate run while a round is live sees the auditors' in-flight probes
93
104
  and reports a failure nobody caused. Wait for the round, or scope the command to paths no auditor
94
105
  owns. Never delete another executor's working file to make your own command pass.
@@ -97,7 +108,14 @@ nobody claimed.
97
108
  and where the pass cannot avoid it, naming it is what recovers the round. A clean pass on its own
98
109
  engine's work is the least valuable result a lane can return.
99
110
  - Supply the evidence the subject type requires, per the table above.
100
- - Auditors are read-only and spawn nothing.
111
+ - Auditors edit no source and spawn nothing. Read-only describes the SUBJECT, never the lane's
112
+ tools.
113
+ - **Read the lane's allowlist before writing its brief.** A lane with no write tool cannot create
114
+ a probe; a lane with no exec tool cannot run one or read `git`. Naming either stops the unit on
115
+ arrival over a detail the allowlist already settled.
116
+ - Where the lane cannot execute, run the probe yourself, record its control and its output, and
117
+ supply that record as the lane's evidence. The Orchestrator produces, the lane rules. Never
118
+ widen a lane's tools to fit a brief.
101
119
  - Blind reports are **immutable**. Nothing an auditor returns is edited, merged, or revised — by
102
120
  anyone, including the auditor — once it has been returned.
103
121
 
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: 'Falsify Finished Work'
3
+ short_description: 'Run an adversarial audit round that tries to break named claims'
4
+ default_prompt: 'Use $orkestrel-falsify to audit the work that looks finished: numbered falsifiable claims, blind lanes, independent refutation, reconciliation, one ruling.'
@@ -1,7 +1,7 @@
1
1
  # Writing the claims brief
2
2
 
3
- The brief decides the round. Every weak audit this process has produced was a weak brief read
4
- faithfully; every finding worth having came from a claim written sharply enough to be attacked.
3
+ The brief decides the round. An auditor reads it faithfully, so a claim too vague to attack
4
+ returns a confirmation that proves nothing. Write every claim sharply enough to be broken.
5
5
 
6
6
  ## Anatomy
7
7
 
@@ -48,11 +48,11 @@ A successor brief:
48
48
  - **states what changed in the brief itself**, so a reader can see which claims are new;
49
49
  - **adds claims that attack the previous round's own rulings.**
50
50
 
51
- That last one is the highest-yield idea in this process. A fix round makes _decisions_ — it rules
52
- that some input should be refused rather than carried, that some widening is deliberate, that some
53
- site is sound and needs no change. Those rulings are the freshest and least-examined surface in the
54
- package, and they were made by the engine least able to see their consequences. Write a claim for
55
- each one.
51
+ Attack the previous round's rulings first. A fix round makes _decisions_ — that some input is
52
+ refused rather than carried, that some widening is deliberate, that some site is sound and needs no
53
+ change. Those rulings are the freshest and least-examined surface in the package, and the engine
54
+ that made them is least able to see their consequences. Write a claim for each one. Expect a
55
+ repair to carry the next defect; a round that finds them is converging, not failing.
56
56
 
57
57
  ## Claims that repeatedly find things
58
58
 
@@ -14,8 +14,7 @@ claim by hand, against the built output, before it enters a fix brief.
14
14
  **Build the hostile input outside the `try`.** A probe that wraps construction and invocation in one
15
15
  catch cannot distinguish _the subject threw_ from _my harness threw_ — a missing import, a wrong
16
16
  arity, a `require` in an ESM context all surface as the finding you were hoping to see. Construct
17
- first, let harness failures crash loudly, and only guard the call under test. Every campaign that has
18
- run this process has produced at least one finding that was the instrument failing.
17
+ first, let harness failures crash loudly, and only guard the call under test.
19
18
 
20
19
  Reproduction produces three outcomes, and all three matter:
21
20
 
@@ -24,6 +23,10 @@ Reproduction produces three outcomes, and all three matter:
24
23
  - the finding **confirms but is bounded smaller** — real, and not where the auditor thought;
25
24
  - the finding **evaporates**, because the auditor's input could not exercise what it claimed to test.
26
25
 
26
+ Separate a dead finding from a dead vector before evaporating anything. A reported vector the
27
+ compiler rejects refutes the vector alone; re-derive one the types admit, and record which vector
28
+ was actually tested.
29
+
27
30
  The same reproduction discipline applies to your own probes. A probe whose input cannot reach the
28
31
  code under test reports a pass that means nothing, and it will read exactly like a real pass.
29
32
 
@@ -101,6 +104,11 @@ Find the rule that fits both. It is usually about **agreement** rather than abou
101
104
  a reader reads, its answer must carry — and it dissolves the special cases rather than enumerating
102
105
  them.
103
106
 
107
+ Measure a proposed fix before adopting it; it is itself a claim. Run it against the set it must
108
+ not break, including every case an earlier round pinned. Where it fails that set, document the
109
+ limit on the helper that owns it and pin the limit with a test that names it as one. A heuristic
110
+ that trades one wrong answer for another fails quietly; a stated boundary does not.
111
+
104
112
  Where the choice is genuinely open, it is a design judgement with a subjective and an objective
105
113
  half, and it goes to a blind design pass before code. Ruling it unilaterally is how a fix round
106
114
  becomes the next audit's finding.