@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.
- package/dist/host/agents/orchestration.md +28 -12
- package/dist/host/agents/skills/enterprise-bootstrap/SKILL.md +146 -194
- package/dist/host/agents/skills/enterprise-bootstrap/references/bootstrap-reference.md +29 -22
- package/dist/host/agents/skills/enterprise-bootstrap/references/components.md +31 -4
- package/dist/host/agents/skills/enterprise-bootstrap/references/frontend-design.md +103 -33
- package/dist/host/agents/skills/enterprise-bootstrap/references/utilities.md +1 -1
- package/dist/host/agents/skills/orkestrel-build-application/references/application.md +2 -2
- package/dist/host/agents/skills/orkestrel-debrief/SKILL.md +2 -1
- package/dist/host/agents/skills/orkestrel-falsify/SKILL.md +21 -3
- package/dist/host/agents/skills/orkestrel-falsify/agents/openai.yaml +4 -0
- package/dist/host/agents/skills/orkestrel-falsify/references/brief.md +7 -7
- package/dist/host/agents/skills/orkestrel-falsify/references/reconcile.md +10 -2
- package/dist/host/agents/skills/orkestrel-human-journey/SKILL.md +124 -0
- package/dist/host/agents/skills/orkestrel-human-journey/agents/openai.yaml +4 -0
- package/dist/host/agents/skills/orkestrel-human-journey/references/captures.md +74 -0
- package/dist/host/agents/skills/orkestrel-human-journey/references/layer.md +131 -0
- package/dist/host/claude/agents/analyst.md +4 -4
- package/dist/host/claude/agents/codex.md +4 -4
- package/dist/host/claude/agents/grok.md +4 -4
- package/dist/host/claude/agents/sol.md +56 -0
- package/dist/host/claude/rules/application.md +5 -3
- package/dist/host/claude/rules/documentation.md +6 -3
- package/dist/host/claude/rules/patterns.md +10 -0
- package/dist/host/claude/rules/quality.md +5 -4
- package/dist/host/claude/rules/tests.md +17 -12
- package/dist/host/claude/settings.json +94 -5
- package/dist/host/claude/skills/orkestrel-human-journey/SKILL.md +10 -0
- package/dist/host/claude/skills/orkestrel-polish-surface/SKILL.md +1 -1
- package/dist/host/codex/agents/grok.toml +1 -1
- package/dist/host/codex/agents/opus.toml +3 -3
- package/dist/host/codex/agents/planner.toml +1 -1
- package/dist/host/codex/agents/reviewer.toml +1 -1
- package/dist/host/dotfiles/gitignore +3 -0
- package/dist/host/manifest.json +41 -1
- package/dist/host/scripts/codex.sh +0 -0
- package/dist/host/scripts/cursor.sh +0 -0
- package/dist/host/scripts/deps.sh +0 -0
- package/dist/host/scripts/ollama.sh +0 -0
- package/dist/host/tests/policy.test.ts +33 -0
- package/dist/host/tests/setupPolicy.ts +319 -2
- package/dist/src/core/index.cjs +1 -1
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.js +1 -1
- package/dist/src/core/index.js.map +1 -1
- 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;
|
|
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
|
-
|
|
341
|
-
|
|
342
|
-
-
|
|
343
|
-
-
|
|
344
|
-
-
|
|
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
|
-
|
|
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
|
-
|
|
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-
|
|
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
|
|
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
|
|
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)
|
|
522
|
-
- **Every error state carries a keyboard-reachable retry
|
|
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.
|
|
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
|
-
**
|
|
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
|
|
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-
|
|
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 |
|
|
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 —
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
22
|
+
Open a web design's hero with the subject's thesis — the one claim the page makes — carried 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
43
|
+
Match complexity to the vision. Maximalist directions need elaborate execution; minimal directions
|
|
44
|
+
need precision in spacing, type, and detail.
|
|
24
45
|
|
|
25
|
-
|
|
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
|
-
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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`
|
|
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 `
|
|
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.**
|
|
91
|
-
probes; give each a distinct path and forbid whole-project runs, or serialize the
|
|
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
|
|
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.
|
|
4
|
-
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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.
|
|
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.
|