@orkestrel/scaffold 0.0.63 → 0.0.65
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/README.md +29 -104
- package/dist/bin/main.js +95 -27
- package/dist/bin/main.js.map +1 -1
- package/dist/host/AGENTS.md +2 -2
- package/dist/host/CLAUDE.md +6 -0
- package/dist/host/agents/orchestration.md +23 -15
- package/dist/host/agents/skills/enterprise-bootstrap/SKILL.md +184 -177
- package/dist/host/agents/skills/enterprise-bootstrap/references/bootstrap-reference.md +314 -91
- package/dist/host/agents/skills/enterprise-bootstrap/references/color-modes.md +241 -0
- package/dist/host/agents/skills/enterprise-bootstrap/references/components.md +83 -36
- package/dist/host/agents/skills/enterprise-bootstrap/references/frontend-design.md +297 -98
- package/dist/host/agents/skills/enterprise-bootstrap/references/inputs.md +25 -14
- package/dist/host/agents/skills/enterprise-bootstrap/references/inspection.md +216 -128
- package/dist/host/agents/skills/enterprise-bootstrap/references/responsive-layout.md +187 -0
- package/dist/host/agents/skills/enterprise-bootstrap/references/utilities.md +109 -20
- package/dist/host/agents/skills/orkestrel-debrief/references/field-testing.md +5 -5
- package/dist/host/agents/skills/orkestrel-falsify/references/reconcile.md +1 -1
- package/dist/host/agents/skills/orkestrel-publish/SKILL.md +15 -15
- package/dist/host/agents/skills/orkestrel-publish/references/wave.md +43 -17
- package/dist/host/agents/skills/orkestrel-publish/references/window.md +41 -16
- package/dist/host/claude/agents/orkestrel.md +56 -56
- package/dist/host/claude/agents/reviewer.md +13 -0
- package/dist/host/claude/rules/architecture.md +51 -45
- package/dist/host/claude/rules/documentation.md +18 -1
- package/dist/host/claude/rules/portability.md +2 -0
- package/dist/host/claude/rules/quality.md +1 -1
- package/dist/host/claude/rules/tests.md +12 -11
- package/dist/host/claude/rules/typescript.md +5 -0
- package/dist/host/claude/rules/workspace.md +25 -20
- package/dist/host/claude/rules/writing.md +4 -0
- package/dist/host/claude/settings.json +1 -1
- package/dist/host/claude/skills/enterprise-bootstrap/SKILL.md +10 -9
- package/dist/host/codex/agents/orkestrel.toml +3 -3
- package/dist/host/codex/agents/reviewer.toml +4 -2
- package/dist/host/configs/helpers.ts +311 -2
- package/dist/host/configs/policy.ts +1100 -51
- package/dist/host/dotfiles/oxlintrc.json +72 -1
- package/dist/host/guides/guide.md +749 -222
- package/dist/host/guides/scaffold.md +529 -394
- package/dist/host/manifest.json +53 -40
- package/dist/host/scripts/ollama.sh +322 -13
- package/dist/host/tests/config.test.ts +1200 -16
- package/dist/host/tests/policy.test.ts +157 -173
- package/dist/host/tests/setupPolicy.ts +522 -1007
- package/dist/src/core/index.cjs +402 -287
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +160 -128
- package/dist/src/core/index.d.ts +160 -128
- package/dist/src/core/index.js +400 -286
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +28 -21
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +38 -33
- package/dist/src/server/index.d.ts +38 -33
- package/dist/src/server/index.js +28 -21
- package/dist/src/server/index.js.map +1 -1
- package/package.json +18 -19
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
.bg-opacity-10, .bg-opacity-25, .bg-opacity-50, .bg-opacity-75, .bg-opacity-100
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
Prefer `bg-body
|
|
27
|
+
Prefer `bg-body`, `bg-body-secondary`, `bg-body-tertiary`, and `bg-*-subtle` for quiet surfaces; inherit text without an added foreground class. Treat original contextual `bg-*`, including `bg-light` and `bg-dark`, as non-adaptive in stock 5.3. Take ownership and exceptions from [color-modes.md](color-modes.md).
|
|
28
28
|
|
|
29
29
|
### Borders
|
|
30
30
|
|
|
@@ -39,7 +39,11 @@ Prefer `bg-body-*` and `*-subtle` over `bg-white`/`bg-light` — they track `dat
|
|
|
39
39
|
.rounded-0, .rounded-1, .rounded-2, .rounded-3, .rounded-4, .rounded-5
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
Use adaptive border roles for quiet separation. Measure boundaries needed to identify a control or state; `border-*-subtle` adapts but does not automatically meet the contrast bar.
|
|
43
|
+
|
|
44
|
+
- **`border-{1..5}` sets `border-width` on every side.** On a component that already has a border (`.card`, `.alert`) it thickens the whole box. For a one-side accent, zero first, restore one side, then widen — `card border-0 border-top border-4 border-primary` — utility source order (`border` → `border-{side}` → `border-width`) makes it hold, and the cleared sides have no border style so their width never paints.
|
|
45
|
+
- Strengthen a rule that reads too faint with `border-2` on its soft color, not with a darker color; heavier width keeps the softness.
|
|
46
|
+
- `border-{color}` is the fixed brand color in both modes; check an accent against a dark `bg-*-subtle` before shipping it.
|
|
43
47
|
|
|
44
48
|
### Colors (Text)
|
|
45
49
|
|
|
@@ -48,10 +52,13 @@ For borders that must stay visible in both color modes, prefer the `border-*-sub
|
|
|
48
52
|
.text-body, .text-body-secondary, .text-body-tertiary, .text-body-emphasis
|
|
49
53
|
.text-primary-emphasis, .text-secondary-emphasis, .text-success-emphasis, .text-danger-emphasis, .text-warning-emphasis, .text-info-emphasis, .text-light-emphasis, .text-dark-emphasis
|
|
50
54
|
.text-black, .text-white, .text-black-50, .text-white-50
|
|
51
|
-
.text-muted /*
|
|
55
|
+
.text-muted /* Deprecated in 5.3; use a deliberate .text-body-secondary role instead. */
|
|
56
|
+
.text-reset /* Restore inherited color; not the same as .text-body. */
|
|
52
57
|
.text-opacity-25, .text-opacity-50, .text-opacity-75, .text-opacity-100
|
|
53
58
|
```
|
|
54
59
|
|
|
60
|
+
Default ordinary text to inheritance. Original contextual `text-*` colors do not adapt in stock 5.3; body-role and `text-*-emphasis` colors do. `text-body-secondary` (body color at .75 alpha) clears 4.5:1 on every stock body surface in both modes; `text-body-tertiary` (.5 alpha) measures 3.0–4.1:1 and is decoration or disabled only. Neither, nor `text-white-50`, is a quiet tier on a colored fill — take the same-hue token from [color-modes.md](color-modes.md) → Text tiers. Do not add emphasis text automatically to subtle fills, and do not replace a component's native foreground without inspecting its state contract.
|
|
61
|
+
|
|
55
62
|
### Display
|
|
56
63
|
|
|
57
64
|
```css
|
|
@@ -120,6 +127,8 @@ For borders that must stay visible in both color modes, prefer the `border-*-sub
|
|
|
120
127
|
.link-offset-1, .link-offset-2, .link-offset-3
|
|
121
128
|
```
|
|
122
129
|
|
|
130
|
+
Keep normal links on Bootstrap's link rules inside prose. Where most things are links — navigation, lists, tables — use `link-body-emphasis link-underline-opacity-0 link-underline-opacity-100-hover link-offset-2`: body tone, underline on hover and focus, and the one colored-link helper that adapts to dark mode; add `fw-semibold` where the link is the row's identity. For a brand underline that completes on hover: `link-underline-primary link-underline-opacity-50 link-underline-opacity-100-hover link-offset-2`. Do not replace hover/focus rules with a text-color utility.
|
|
131
|
+
|
|
123
132
|
### Object Fit
|
|
124
133
|
|
|
125
134
|
```css
|
|
@@ -133,6 +142,8 @@ For borders that must stay visible in both color modes, prefer the `border-*-sub
|
|
|
133
142
|
.opacity-0, .opacity-25, .opacity-50, .opacity-75, .opacity-100
|
|
134
143
|
```
|
|
135
144
|
|
|
145
|
+
Opacity is not a text tier: it reads as disabled and lets the surface show through the glyphs. Do not use whole-element opacity to quiet a region containing readable text. Color-opacity utilities affect only rules that consume their variable; stock subtle backgrounds do not consume `--bs-bg-opacity`. Measure the composited result rather than assuming a tint.
|
|
146
|
+
|
|
136
147
|
### Overflow
|
|
137
148
|
|
|
138
149
|
```css
|
|
@@ -160,9 +171,11 @@ For borders that must stay visible in both color modes, prefer the `border-*-sub
|
|
|
160
171
|
.shadow-none, .shadow-sm, .shadow, .shadow-lg
|
|
161
172
|
```
|
|
162
173
|
|
|
174
|
+
Three elevation steps: `shadow-sm` (`0 .125rem .25rem` at .075) for slightly raised cards and controls, `shadow` (`0 .5rem 1rem` at .15) for floating menus and a dragged item, `shadow-lg` (`0 1rem 3rem` at .175) for dialogs. Stock dropdowns, popovers, toasts, and modals all sit on `--bs-box-shadow`; lift a modal to the top step through `--bs-modal-box-shadow` ([bootstrap-reference.md](bootstrap-reference.md) → Elevation and depth). No shadow is a valid role.
|
|
175
|
+
|
|
163
176
|
### Sizing
|
|
164
177
|
|
|
165
|
-
Bootstrap ships exactly these — nothing else (no `.vw-25`, `.vh-50`, `.mw-auto`, `.min-vh-75
|
|
178
|
+
Bootstrap ships exactly these — nothing else (no `.vw-25`, `.vh-50`, `.mw-auto`, or `.min-vh-75`; add missing steps through the utilities API if a project truly needs them — see [bootstrap-reference.md](bootstrap-reference.md)):
|
|
166
179
|
|
|
167
180
|
```css
|
|
168
181
|
/* Width / height (percent of parent) */
|
|
@@ -222,14 +235,16 @@ Notes: `s`/`e` are logical start/end — they flip automatically under RTL; neve
|
|
|
222
235
|
/* Size */
|
|
223
236
|
.fs-1, .fs-2, .fs-3, .fs-4, .fs-5, .fs-6
|
|
224
237
|
|
|
225
|
-
/* Truncate — needs
|
|
238
|
+
/* Truncate — needs a constrained inline width and block/inline-block layout */
|
|
226
239
|
.text-truncate
|
|
227
240
|
```
|
|
228
241
|
|
|
242
|
+
`fs-6…1` = 1 · 1.25 · 1.5 · 1.75 · 2 · 2.5 rem (16–40 px at the default root); `display-6…1` = 2.5–5 rem. Values above 1.25 rem scale down fluidly below a 1200 px viewport under RFS; `fs-5`, `fs-6`, `.lead`, and controls do not. There is no `rem` step below 1 rem: `.small` and `<small>` are `.875em`, so use one level only — `.small` inside `.small` is 12.25 px, off every scale — and take a 14 px or 12 px role from the generated `fs-sm`/`fs-xs` ([bootstrap-reference.md](bootstrap-reference.md) → Layout and type extensions). Stock 5.3 ships no letter-spacing utility; generate `ls-tight`/`ls-wide` there for display text and `text-uppercase` labels. `fw-light`/`fw-lighter` (300) belong only at display size; `.lead` and `display-*` ship at 300 by design.
|
|
243
|
+
|
|
229
244
|
The composition traps in this group:
|
|
230
245
|
|
|
231
246
|
- **`fs-*` without `lh-1` grows the row.** A resized glyph or mark keeps the parent's line-height, so the line box stretches and the row sits taller than its neighbors. Pair `fs-*` with `lh-1` on anything that is a mark rather than a paragraph.
|
|
232
|
-
- **`text-truncate`
|
|
247
|
+
- **`text-truncate` is not a minimum-size utility.** It sets hidden overflow, ellipsis, and no wrapping; it does not declare `min-width: 0`. Give the truncating element a constrained width and make its flex ancestry shrink where required. In a constrained column, protect a title from height loss with `flex-shrink-0`. Take any missing inline-size utility from the project's generated scale, never an invented `.min-w-0`.
|
|
233
248
|
|
|
234
249
|
### Vertical Align
|
|
235
250
|
|
|
@@ -261,6 +276,17 @@ The composition traps in this group:
|
|
|
261
276
|
| `5` | $spacer \* 3 (3rem = 48px) |
|
|
262
277
|
| `auto` | auto |
|
|
263
278
|
|
|
279
|
+
Use the installed scale as the first choice. Assign its steps to internal, group, panel, and section
|
|
280
|
+
gaps; keep inter-group gaps larger than internal gaps. Compare adjacent steps before adding one.
|
|
281
|
+
The displayed pixel equivalents assume the default root size; they are not fixed pixel constraints.
|
|
282
|
+
|
|
283
|
+
The shipped jumps are +100 / +100 / +50 / +100 %: coarse above 16 px, with no 12 px or 32 px
|
|
284
|
+
step and nothing above 48 px for section rhythm. A missing step is not permission to type `p-2.5`
|
|
285
|
+
or `p-6`; those resolve to no rule and fail silently. Add a named step through
|
|
286
|
+
[bootstrap-reference.md](bootstrap-reference.md) → Layout and type extensions and verify the
|
|
287
|
+
generated class in the shipped build. Take type, width, and spacing decisions from
|
|
288
|
+
[frontend-design.md](frontend-design.md).
|
|
289
|
+
|
|
264
290
|
## Z-index Scale (components)
|
|
265
291
|
|
|
266
292
|
| Component | Z-index |
|
|
@@ -288,25 +314,88 @@ Helpers are single-purpose classes that sit alongside utilities.
|
|
|
288
314
|
|
|
289
315
|
- **`.visually-hidden`** — hide visually, keep for screen readers (icon-button labels, table caption text, "Danger:" prefixes).
|
|
290
316
|
- **`.visually-hidden-focusable`** — hidden until focused; the skip-link class. Never combine with `.visually-hidden`.
|
|
291
|
-
- **`.stretched-link`** — makes a whole `position-relative` container (
|
|
317
|
+
- **`.stretched-link`** — makes a whole `position-relative` container (for example, a card) the click target of one inner link, without wrapping everything in `<a>`.
|
|
292
318
|
- **`.ratio .ratio-16x9`** (also `1x1`, `4x3`, `21x9`, or `--bs-aspect-ratio`) — responsive embeds/iframes.
|
|
293
319
|
- **`.vstack` / `.hstack gap-*`** — shorthand vertical/horizontal flex stacks for quick toolbars and side rails.
|
|
294
320
|
- **`.vr`** — vertical rule divider inside an `.hstack` or flex row.
|
|
295
|
-
- **`.focus-ring`** (+ `.focus-ring-primary` … per theme color) — opt-in focus ring for custom interactive elements; tune
|
|
296
|
-
- **`.icon-link`** (+ `.icon-link-hover`) — pairs a Bootstrap Icon SVG with a text link; icon auto-sizes to 1em; give decorative icons `aria-hidden="true"`. Hover shift
|
|
321
|
+
- **`.focus-ring`** (+ `.focus-ring-primary` … per theme color) — opt-in focus ring for custom interactive elements; tune through `--bs-focus-ring-width` (.25rem), `--bs-focus-ring-opacity` (.25), `--bs-focus-ring-color`, `--bs-focus-ring-x/y/blur`. Use it instead of `outline: none` hacks so keyboard focus stays visible.
|
|
322
|
+
- **`.icon-link`** (+ `.icon-link-hover`) — pairs a Bootstrap Icon SVG with a text link; icon auto-sizes to 1em; give decorative icons `aria-hidden="true"`. Hover shift through `--bs-icon-link-transform`.
|
|
297
323
|
|
|
298
324
|
## Enterprise notes (utilities)
|
|
299
325
|
|
|
300
326
|
### Composition habits
|
|
301
327
|
|
|
302
|
-
- **Spacing
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
- **
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
-
|
|
328
|
+
- **Spacing:** let the parent own rhythm with `gap-*`; use margins where the relationship requires
|
|
329
|
+
them. Choose panel padding from the shared scale, not a separate value per card. Keep labels,
|
|
330
|
+
controls, help, and errors closer together than neighboring groups: `.form-label` ships `.5rem`
|
|
331
|
+
below, so field groups take `mb-3` or `row g-3`. Headings ship `margin-bottom: .5rem` and no top
|
|
332
|
+
margin, so a section heading after a paragraph attaches to the wrong block — add `mt-4`/`mt-5`
|
|
333
|
+
or let a `vstack gap-4` parent own the rhythm. In a row, `hstack gap-2` inside a group and
|
|
334
|
+
`gap-4` between groups. Start a gap one step too large and step down.
|
|
335
|
+
- **Hierarchy:** use `fw-normal` for reading and `fw-semibold`/`fw-bold` for emphasis; headings
|
|
336
|
+
ship at 500, barely a step above body on a system stack, so pair a smaller heading class with
|
|
337
|
+
`fw-semibold` (`<h2 class="h5 fw-semibold">`) rather than a large heading at 500. Never
|
|
338
|
+
`fw-light` on UI text. Start ordinary text and quiet status with inheritance; add
|
|
339
|
+
`text-body-secondary` as the one quiet tier. Do not make metadata tiny or translucent to quiet
|
|
340
|
+
it. Quiet a heavy icon beside a label with `text-body-secondary` on the icon, not a larger label.
|
|
341
|
+
Quiet an active nav item's competitors (inherited text, normal weight) before making the active
|
|
342
|
+
item louder.
|
|
343
|
+
- **Type:** `fs-*` changes size, not semantic heading level. Choose `lh-*` by the text's role;
|
|
344
|
+
`lh-1` suits a glyph or suitable display treatment, not every paragraph. Keep prose start-aligned
|
|
345
|
+
and bound its measure independently of wider content.
|
|
346
|
+
- **Baseline:** use `align-items-baseline` for mixed-size text on one row. Keep `align-items-center`
|
|
347
|
+
for controls or icon/text combinations where the boxes, rather than text baselines, need to align.
|
|
348
|
+
- **Body surfaces:** `bg-body`, `bg-body-secondary`, and `bg-body-tertiary` track `data-bs-theme`.
|
|
349
|
+
Keep ordinary text inherited on those surfaces; use an explicit pair only at an owned boundary.
|
|
350
|
+
Take exceptions from [color-modes.md](color-modes.md).
|
|
351
|
+
- **Opacity:** do not use `text-white-50`, `text-black-50`, or `text-opacity-*` as the default secondary
|
|
352
|
+
tier. On colored fills, inherit the tested foreground or use a scoped opaque token. Any opacity
|
|
353
|
+
changes the composited contrast, including opacity on an ancestor.
|
|
354
|
+
- **Width:** use `w-100` inside a content-led maximum width, not `w-50` merely to avoid a wide form.
|
|
355
|
+
Stock Bootstrap has no prose-measure, fixed-rail, or zero-inline-minimum utility. Generate needed
|
|
356
|
+
roles through [bootstrap-reference.md](bootstrap-reference.md) → Layout and type extensions.
|
|
357
|
+
- **Flex floors:** allow a flexible main region to shrink without clipping its essential content.
|
|
358
|
+
Protect titles or marks that must retain height with `flex-shrink-0`. Do not add `overflow-hidden`
|
|
359
|
+
to an ancestor to conceal a layout bug; it can clip menus and focus rings.
|
|
360
|
+
- **Toolbars:** start with `d-grid gap-2` or labelled `row g-2` controls; expand with `d-sm-flex
|
|
361
|
+
flex-sm-wrap` or `col-md-auto` only when the container fits. Do not default to a horizontal
|
|
362
|
+
scroller for search or primary actions. Keep matching control sizes and usable hit areas. Align equal-height
|
|
363
|
+
cards only where their content benefits, not to fill empty space.
|
|
364
|
+
- **Responsive content:** follow [responsive-layout.md](responsive-layout.md); unprefixed utilities define the complete narrow task. A class that resolves can still implement the wrong layout. Reflow and prioritize before truncating. Hide a button caption only when
|
|
365
|
+
its remaining icon is recognizable and its accessible name remains complete; unfamiliar or
|
|
366
|
+
consequential actions keep visible labels. Do not erase task information to save the brand's width.
|
|
367
|
+
- **Links:** use persistent underlines for inline prose links. In conventional navigation, quieter
|
|
368
|
+
color and weight can carry hierarchy; retain visible hover and focus. Never rely on hover alone
|
|
369
|
+
for discovery. An action remains a button even when styled with `btn-link`.
|
|
370
|
+
- **RTL:** use `ms-*`/`me-*`/`ps-*`/`pe-*`, `text-start`/`text-end`, and logical custom properties;
|
|
371
|
+
verify the matching RTL build and the content's writing direction.
|
|
372
|
+
- **Density:** drive compact/comfortable variants from shared tokens or a wrapper, not scattered
|
|
373
|
+
per-element tweaks. Dense data retains readable text and ≥24px control targets.
|
|
374
|
+
- **Boundaries and depth:** separate with spacing first, then a surface change, then a shadow, then
|
|
375
|
+
a line: `bg-body-tertiary` panels instead of bordered ones; `card border-0 shadow-sm` on a page
|
|
376
|
+
surface that differs from the card; `list-group-flush`, `accordion-flush`, `table-borderless`,
|
|
377
|
+
`border-0` on a `card-header`; `gap-4` instead of an `<hr>`. Remove a border where a distinct
|
|
378
|
+
background already separates. Use `border-0` or `shadow-none` only when grouping and control
|
|
379
|
+
recognition survive. Assign `shadow-sm`, `shadow`, and `shadow-lg` by layer role; do not shadow
|
|
380
|
+
every panel or replace the focus indicator with depth. A `bg-body` panel on `bg-body-tertiary`
|
|
381
|
+
reads raised and `bg-body-secondary` inside `bg-body` reads inset — depth with no shadow, in
|
|
382
|
+
both modes.
|
|
383
|
+
- **Accents and decoration:** one accent border per region (see [Borders](#borders)); the shipped
|
|
384
|
+
`nav-underline` is the active-item accent. Alternate `bg-body` and `bg-body-tertiary` sections
|
|
385
|
+
before decorating; a `bg-primary-subtle` band emphasizes one panel. `bg-gradient` is a
|
|
386
|
+
white-to-transparent fade over the current fill, not a hero gradient.
|
|
387
|
+
- **Overlap:** `position-relative translate-middle-y` for a card that straddles two surfaces;
|
|
388
|
+
`mt-n*` only after `$enable-negative-margins`. Ring an overlapping avatar in the body color
|
|
389
|
+
with `rounded-circle border border-3` plus the `ring-body` class from
|
|
390
|
+
[bootstrap-reference.md](bootstrap-reference.md) → Elevation and depth, never `border-white`.
|
|
391
|
+
- **Images:** combine a declared frame or ratio with `object-fit-cover` only when cropping is safe;
|
|
392
|
+
take `object-fit-contain` when the whole asset matters. Guard a user upload against bleeding into
|
|
393
|
+
a same-color surface with `border border-black border-opacity-10` — translucent, so it does not
|
|
394
|
+
clash with the photo. Reduce a photo's dynamics before placing text on it: a `bg-dark
|
|
395
|
+
bg-opacity-50` (or `-75`) overlay layer under `card-img-overlay`, measured at every crop. Keep a
|
|
396
|
+
small glyph near 16–24 px inside `rounded-circle bg-primary-subtle p-3` rather than scaling it up.
|
|
397
|
+
Keep useful image detail and icon optical size rather than stretching assets to fill a box.
|
|
398
|
+
- **Lists and quotes:** `list-unstyled` with a meaningful glyph per item (`d-flex gap-2
|
|
399
|
+
align-items-baseline`, glyph `aria-hidden="true"`); `.blockquote` with `.blockquote-footer`.
|
|
400
|
+
- **Print:** mark chrome `d-print-none` and keep results readable; do not hide data merely because
|
|
401
|
+
its interactive controls have no print role.
|
|
@@ -8,10 +8,10 @@ model consumes.
|
|
|
8
8
|
Test from the top down, and do not stop at the tier that passes:
|
|
9
9
|
|
|
10
10
|
1. **Frontier** (the harness's default model) — proves the surface works at all.
|
|
11
|
-
2. **Mid tier** (
|
|
12
|
-
schema abbreviation and a model that reads less carefully.
|
|
13
|
-
3. **Small harness-native** (
|
|
14
|
-
tier: these must walk the surface unaided, or the surface is not done.
|
|
11
|
+
2. **Mid tier** (for example, a codex mechanical model) — proves the surface survives a
|
|
12
|
+
harness's schema abbreviation and a model that reads less carefully.
|
|
13
|
+
3. **Small harness-native** (for example, Haiku or a codex high-volume model) — the
|
|
14
|
+
acceptance tier: these must walk the surface unaided, or the surface is not done.
|
|
15
15
|
4. **Local floor** (a quantized 2B-class model through a real tool-calling client) — not
|
|
16
16
|
an acceptance gate; a stochastic probe that exposes teaching gaps nothing else hits.
|
|
17
17
|
Its residual failures must be provably consumer-floor (malformed emission, attention
|
|
@@ -29,7 +29,7 @@ Test from the top down, and do not stop at the tier that passes:
|
|
|
29
29
|
- **Caps and journals.** Every pass runs as a tracked background command under a hard
|
|
30
30
|
time cap with its transcript journaled; the journal is the evidence of record.
|
|
31
31
|
|
|
32
|
-
## Capture the reasoning, not
|
|
32
|
+
## Capture the reasoning, not the calls alone
|
|
33
33
|
|
|
34
34
|
Where the runtime exposes thinking (local runtimes expose it directly; harness stream
|
|
35
35
|
formats carry interstitial text), record it. The call log shows WHAT failed; the trace
|
|
@@ -120,7 +120,7 @@ leaves this round is the procedure.
|
|
|
120
120
|
|
|
121
121
|
When a round certifies an instrument — a pin, an identity check, a generated sweep — the controls
|
|
122
122
|
are usually drawn from whatever the instrument obviously covers, because that is where the examples
|
|
123
|
-
|
|
123
|
+
take the least construction. That sampling proves discrimination _within_ the population and is
|
|
124
124
|
routinely reported as proof the instrument works.
|
|
125
125
|
|
|
126
126
|
So before running controls, write down the instrument's **membership rule** in one sentence, then
|
|
@@ -10,8 +10,9 @@ description: Run an Orkestrel release from layer order to registry confirmation.
|
|
|
10
10
|
Read the current files in this order:
|
|
11
11
|
|
|
12
12
|
1. `AGENTS.md` and every applicable `.claude/rules/*.md` file.
|
|
13
|
-
2. `.agents/orchestration.md` § Publishing the fleet
|
|
14
|
-
section binds every step
|
|
13
|
+
2. `.agents/orchestration.md` § Publishing the fleet, § Long-running commands, § Orchestrator and
|
|
14
|
+
executor, § Writing concurrency, and § Dispatch anatomy. Each named section binds every step
|
|
15
|
+
here.
|
|
15
16
|
3. The reference the moment needs: [wave.md](references/wave.md) before visiting a repository,
|
|
16
17
|
ruling on a bump, or preparing a layer; [window.md](references/window.md) before running
|
|
17
18
|
`npm login` or any upload.
|
|
@@ -42,21 +43,17 @@ following the skill.
|
|
|
42
43
|
Derive each pin from that reading, never from a local manifest.
|
|
43
44
|
3. **Visit each repository.** Run the visit in [wave.md](references/wave.md) in its stated order,
|
|
44
45
|
in parallel slices of disjoint repositories, each slice serial inside itself.
|
|
45
|
-
4. **Rule on each package's bump.** Apply the triggers in [wave.md](references/wave.md)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
run each package's own `prepublishOnly` to green, commit, and push. Every one of those steps
|
|
50
|
-
happens outside the window.
|
|
46
|
+
4. **Rule on each package's bump.** Apply the triggers in [wave.md](references/wave.md) § Rule on
|
|
47
|
+
the bump; the contract's § What a bump obliges owns the blast radius.
|
|
48
|
+
5. **Prepare the whole layer before authenticating**, in the order [wave.md](references/wave.md)
|
|
49
|
+
§ Prepare a layer fixes. Every one of those steps happens outside the window.
|
|
51
50
|
6. **Reach the approval.** Follow [window.md](references/window.md), and launch the login chain
|
|
52
51
|
only after the user signals they are at the keyboard.
|
|
53
52
|
7. **Authorize and upload.** Follow [window.md](references/window.md). Take the account's one-time
|
|
54
|
-
code where it has one
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
install until the version it names exists, so preparation and publication interleave and cannot
|
|
59
|
-
be batched ahead.
|
|
53
|
+
code where it has one; § Authorize the upload there fixes that code's life and the layer it
|
|
54
|
+
carries. Where the account answers with no code, follow § Spend the window there.
|
|
55
|
+
8. **Close the layer from the registry, then prepare the next**, per [wave.md](references/wave.md)
|
|
56
|
+
§ Prepare a layer.
|
|
60
57
|
|
|
61
58
|
Run that sequence for every layer, from the registry reading to the registry close. Refresh the
|
|
62
59
|
registry evidence between layers rather than carrying the previous round's reading forward.
|
|
@@ -71,7 +68,10 @@ Completion requires:
|
|
|
71
68
|
that section requires;
|
|
72
69
|
- every tarball swap is restored per § Fixing a dependency before it publishes, and no target
|
|
73
70
|
repository is left holding an uncommitted bump or an unpushed commit;
|
|
74
|
-
- every gate that proved a package ran outside the window and against the artifact that shipped
|
|
71
|
+
- every gate that proved a package ran outside the window and against the artifact that shipped;
|
|
72
|
+
- every gate red at a package's baseline for a cause `ROADMAP.md` already carries is recorded as a
|
|
73
|
+
standing reading beside the package's row with its carrier, and the release report names it. A
|
|
74
|
+
standing reading is not a gate the release ran.
|
|
75
75
|
|
|
76
76
|
Report the layers in publish order, each package with its registry-confirmed version, the bump
|
|
77
77
|
rulings and their evidence, the approvals the user granted, and anything still unpublished. End
|
|
@@ -10,9 +10,11 @@ prepare the next.
|
|
|
10
10
|
Run the visit in this order. A step that reads generated or installed state is invalid before the
|
|
11
11
|
step that writes it.
|
|
12
12
|
|
|
13
|
-
1. Re-pin
|
|
14
|
-
current vendored host.
|
|
15
|
-
2.
|
|
13
|
+
1. Re-pin every `@orkestrel` range to the registry caret (peer ranges included) and install, so
|
|
14
|
+
the overwrite runs the current vendored host.
|
|
15
|
+
2. Commit the manifest and the lockfile as the preparation commit. `scaffold overwrite` refuses a
|
|
16
|
+
tree carrying uncommitted changes, and the install left both dirty.
|
|
17
|
+
3. Run `scaffold overwrite`. One run repairs the `AGENTS.md` and `CLAUDE.md` pointers and deletes
|
|
16
18
|
every tracked copy the target still holds at an instruction-canon path. Prove the sweep with a
|
|
17
19
|
second `scaffold audit` that exits `0`.
|
|
18
20
|
- Where the target's `.claude/agents/orkestrel.md` carries a body outside the marker-bounded
|
|
@@ -30,12 +32,16 @@ step that writes it.
|
|
|
30
32
|
rather than waiving past it.
|
|
31
33
|
- A copy the target git-ignores stays a `foreign` finding, so that target never reaches exit `0`
|
|
32
34
|
again. Keep a local MCP server registration outside the repository rather than at `.mcp.json`.
|
|
33
|
-
|
|
35
|
+
4. Force-verify every `@orkestrel` range against a registry sweep taken after the previous layer
|
|
34
36
|
published.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
6.
|
|
38
|
-
7.
|
|
37
|
+
5. Run the full install. The overwrite re-declares the toolchain ranges, so the lockfile the first
|
|
38
|
+
install regenerated no longer matches the manifest.
|
|
39
|
+
6. Sweep the self-pins, per § Sweep the self-pins: the re-pin moves the snapshot class.
|
|
40
|
+
7. Run the mutating `format` script to converge generated writes.
|
|
41
|
+
8. Run the quality gates.
|
|
42
|
+
9. Fetch the published tarball, then compare the rebuilt `dist/` against it for material content.
|
|
43
|
+
An absent baseline is an unanswered comparison, never a moved dist: fetch and re-run rather than
|
|
44
|
+
ruling a bump owed.
|
|
39
45
|
|
|
40
46
|
Restore any unpublished tarball the target is holding before the quality gates run, per
|
|
41
47
|
`.agents/orchestration.md` § Fixing a dependency before it publishes. A distribution proof run
|
|
@@ -69,7 +75,15 @@ final runtime dependency set differs from the published packument.
|
|
|
69
75
|
per package rather than assuming it: a package that imports its own `package.json` version into
|
|
70
76
|
published code emits that version, so its pre-bump dist is stale the moment the version moves.
|
|
71
77
|
Rebuild after the bump there and pack from the rebuilt tree. The `npm publish --ignore-scripts`
|
|
72
|
-
command skips `prepack`, so that rebuild is the operator's step rather than the publish's.
|
|
78
|
+
command skips `prepack`, so that rebuild is the operator's step rather than the publish's. The
|
|
79
|
+
same holds for a package that writes its declared ranges into published output: its `dist/`
|
|
80
|
+
moves on a development re-pin, and `.agents/orchestration.md` § What a bump obliges rules that
|
|
81
|
+
re-pin a release.
|
|
82
|
+
|
|
83
|
+
One trigger orders rather than bumps. A package the fleet consumes as a development dependency,
|
|
84
|
+
whose consumers' gates read its unpublished tip, publishes on its own account ahead of the layer
|
|
85
|
+
order and again at its own slot after its runtime ranges move: each consumer's visit installs the
|
|
86
|
+
registry copy over any staged tip, so every consumer stays red until that tip is on the registry.
|
|
73
87
|
|
|
74
88
|
## Prepare a layer
|
|
75
89
|
|
|
@@ -77,16 +91,22 @@ An unpublished package's first version is `0.0.1`. Do not bump it before that fi
|
|
|
77
91
|
registry has nothing to serve, so there is no version to move away from, and bumping produces a
|
|
78
92
|
package whose history starts at a number nothing explains.
|
|
79
93
|
|
|
80
|
-
Prepare a published package's layer in this order:
|
|
94
|
+
Prepare a published package's layer in this order, after the visit has ruled the package's bump:
|
|
81
95
|
|
|
82
96
|
1. **Bump from what the registry serves, not from the local manifest.** A repository's `version`
|
|
83
97
|
field can sit a release behind what was published from another checkout, and bumping that
|
|
84
98
|
produces a version the registry already holds, which fails on upload after the whole gate chain
|
|
85
99
|
has run. Read the registry first.
|
|
86
|
-
2. **Re-pin every `@orkestrel` range to what the registry serves, and install.**
|
|
87
|
-
|
|
100
|
+
2. **Re-pin every `@orkestrel` range to what the registry serves, and install.** The visit's
|
|
101
|
+
preparation commit already precedes the overwrite; this install regenerates the lockfile for the
|
|
102
|
+
bumped manifest.
|
|
103
|
+
3. **Sweep the self-pins**, per the following section: the bump moves the version class.
|
|
88
104
|
4. **Run each package's own `prepublishOnly` script to green.**
|
|
89
|
-
5. **
|
|
105
|
+
5. **Write the release commit and push before the window opens.** The preparation commit inside
|
|
106
|
+
the visit is a different commit at a different moment.
|
|
107
|
+
|
|
108
|
+
Where an inventory taken before the round already ruled every dist moved, the bump rides the
|
|
109
|
+
visit's first step and these steps fold into the visit, whose comparison then confirms the ruling.
|
|
90
110
|
|
|
91
111
|
Prepare the next layer only after this one is on the registry. A dependent's new pin cannot
|
|
92
112
|
install until the version it names exists, so preparation and publication interleave and cannot be
|
|
@@ -99,12 +119,17 @@ the flag is what stops the gate chain running a second time inside the five minu
|
|
|
99
119
|
## Sweep the self-pins
|
|
100
120
|
|
|
101
121
|
A package's own version appears in its source and its tests as a literal, and a bump falsifies
|
|
102
|
-
every one of them.
|
|
122
|
+
every one of them. A snapshot of generated output carries the ranges the package writes rather than
|
|
123
|
+
its own version, and any re-pin, a development one included, falsifies it. Run this sweep after the
|
|
124
|
+
re-pin install, not after the manifest edit.
|
|
103
125
|
|
|
104
|
-
-
|
|
105
|
-
|
|
126
|
+
- Search `tests/` and `src/` in the publishing package for the prior version literal, and rule on
|
|
127
|
+
every hit. A canned packument in a fixture and a looked-up version in a CLI suite carry the
|
|
106
128
|
version with no tripwire comment beside them, so they surface as a red gate after the bump
|
|
107
129
|
rather than as a planned edit before it.
|
|
130
|
+
- Search `tests/` for the prior range of every re-pinned dependency, and move each snapshot the
|
|
131
|
+
search hits with the re-pin. A generated-manifest fixture never carries the package's own prior
|
|
132
|
+
version, so the version sweep cannot reach it.
|
|
108
133
|
- Move a documented tripwire — a golden digest over generated output — in the same change as the
|
|
109
134
|
version bump. That is what the tripwire is for.
|
|
110
135
|
- Re-take a generated artifact's digest after the install, because the generated bytes can derive
|
|
@@ -120,4 +145,5 @@ every one of them. Run this sweep after the re-pin install, not after the manife
|
|
|
120
145
|
|
|
121
146
|
Refresh the registry evidence between layers and derive each round's pins from it. A pin can only
|
|
122
147
|
name a version the registry already serves, so a dependency shipping in the same window keeps the
|
|
123
|
-
resolvable previous pin and takes its development-only re-pin after the window closes.
|
|
148
|
+
resolvable previous pin and takes its development-only re-pin after the window closes. That re-pin
|
|
149
|
+
takes the self-pin sweep too, because the snapshot class moves with no bump.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# The approval and the upload window
|
|
2
2
|
|
|
3
3
|
A release needs the user at the keyboard to authenticate the session, and again to authorize each
|
|
4
|
-
upload. An approval URL dies unclicked in under a minute, so mint one only in a
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
upload. An approval URL dies unclicked in under a minute, so mint one only in a moment the user can
|
|
5
|
+
click, and relay it byte for byte. Where the account answers with a one-time code, take that code
|
|
6
|
+
for the upload — it needs no browser authorization, and § Authorize the upload states the code's own
|
|
7
|
+
life. Where the account has no code, the browser authorization opens a five-minute window, and the
|
|
8
8
|
rest of the layer either fits inside it or takes another approval.
|
|
9
9
|
|
|
10
10
|
## Arm the terminal
|
|
@@ -25,8 +25,11 @@ rest of the layer either fits inside it or takes another approval.
|
|
|
25
25
|
zero.
|
|
26
26
|
- Re-probe `whoami` immediately before the first upload. A stored credential expires mid-session
|
|
27
27
|
and an overnight gap expires it, so a session-start answer does not hold.
|
|
28
|
-
- Read a login log that shows the spinner and then a legacy `Username:` prompt as
|
|
29
|
-
|
|
28
|
+
- Read a login log that shows the spinner and then a legacy `Username:` prompt as a dead attempt
|
|
29
|
+
rather than as a prompt to answer: expired, or refused on its first poll per § Read a `403` on the
|
|
30
|
+
poll. Kill it by the process id recorded at its launch, per `.agents/orchestration.md` § Confirm
|
|
31
|
+
dead before relaunching. Every publish here runs under the same `script -qfc` form, so a pattern
|
|
32
|
+
over the process list reaches a live upload as readily as the dead login.
|
|
30
33
|
- On a Windows host, Git Bash ships no `script` binary, so the upload step is operator-driven:
|
|
31
34
|
prepare the layer, prove the gates, surface the exact `npm publish` command, and the operator
|
|
32
35
|
runs it in a real terminal. Everything before and after the upload — bumps, re-pins, gates,
|
|
@@ -49,13 +52,17 @@ rest of the layer either fits inside it or takes another approval.
|
|
|
49
52
|
against `registry.npmjs.org` with `npm` 10.9.7 and `node` 22.22.2: npm polls `GET /-/v1/done`
|
|
50
53
|
every few seconds and takes `202` while the session waits, and the registry answers `403` at
|
|
51
54
|
about 45 seconds. Whether the registry fixes that abandon by elapsed time or by poll count is
|
|
52
|
-
unmeasured, so plan against the duration.
|
|
55
|
+
unmeasured, so plan against the duration. A `403` within seconds of the mint is not that abandon;
|
|
56
|
+
§ Read a `403` on the poll names it.
|
|
53
57
|
- Recognise the abandon on each side. The `npm login` command reads the `403` as web login being
|
|
54
58
|
unsupported and drops to its legacy `Username:` prompt. The `npm publish` command exits `E403`
|
|
55
59
|
naming `GET /-/v1/done?authId=`.
|
|
56
60
|
- Never keep a link alive by re-minting on a loop. Each mint invalidates the URL before it, so a
|
|
57
61
|
supervisor that re-mints on expiry makes the link a moving target and every relayed URL is dead
|
|
58
|
-
on arrival. Mint once per human moment, and mint again only when the user asks.
|
|
62
|
+
on arrival. Mint once per human moment, and mint again only when the user asks. That ban covers
|
|
63
|
+
a URL already relayed. While no URL has been relayed, mint attempts until one survives its own
|
|
64
|
+
first poll, relay that one alone, and kill the rest by process id; § Read a `403` on the poll
|
|
65
|
+
names the first-poll refusal this answers.
|
|
59
66
|
- Name the login approval and the upload authorization to the user before either arrives, or the
|
|
60
67
|
authorization link reads as the login having failed.
|
|
61
68
|
- Surface each approval URL the moment it appears in the log, and take the **last** one in log
|
|
@@ -75,17 +82,23 @@ rest of the layer either fits inside it or takes another approval.
|
|
|
75
82
|
|
|
76
83
|
- Take the account's one-time code where the account has one. The
|
|
77
84
|
`npm publish --ignore-scripts --otp=<code>` command uploads with no browser authorization and no
|
|
78
|
-
poll
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
85
|
+
poll. The code has its own life: measured on 2026-09-04 against `registry.npmjs.org`, one code
|
|
86
|
+
carried every upload of a layer started within about a minute of its first use, console at
|
|
87
|
+
20:25:02 through router at 20:25:58, and the upload started at 20:25:58 was refused `EOTP` at
|
|
88
|
+
20:26:00; a code read before its layer was ready was refused at its first upload.
|
|
89
|
+
- Prepare the whole layer, then ask for one code at the moment the layer's first upload starts, and
|
|
90
|
+
chase the layer's uploads back-to-back inside that code's life with no gate between them. A code
|
|
91
|
+
read minutes earlier is already spent.
|
|
92
|
+
- Read `EOTP` on this path as the code's life ending, never as the contention § Spend the window
|
|
93
|
+
describes for the browser path: the chain stops at the refused package, and the layer resumes
|
|
94
|
+
from that package on a fresh code. Never retry the refused upload on the same code.
|
|
83
95
|
- Ask for the code and nothing else. Never ask for a password, an access token, or an auth file.
|
|
84
96
|
`.agents/orchestration.md` § Publishing the fleet owns that law.
|
|
85
97
|
- Arm a one-time-code upload the way § Arm the terminal arms every other publish.
|
|
86
98
|
- Fall back to the browser authorization where the account answers with no code. That path mints
|
|
87
99
|
the `auth/cli/<id>` URL, needs the click inside the session's life, and opens the five-minute
|
|
88
|
-
window.
|
|
100
|
+
window. In the `@orkestrel/scaffold` 0.0.56 run on 2026-08-27 that authorization failed on the
|
|
101
|
+
45-second abandon and the one-time code uploaded the package with no retry.
|
|
89
102
|
- Tell the user that approving an `auth/cli/<id>` URL opens a five-minute window covering the rest
|
|
90
103
|
of the layer.
|
|
91
104
|
|
|
@@ -95,7 +108,8 @@ rest of the layer either fits inside it or takes another approval.
|
|
|
95
108
|
window, so none of it binds that path.
|
|
96
109
|
- The window opens when the user approves, not when the first publish starts.
|
|
97
110
|
- Open each layer with one package: publish it alone, surface its approval URL the moment the
|
|
98
|
-
journal shows it, and
|
|
111
|
+
journal shows it, and read its acceptance line in the journal before starting the rest; the
|
|
112
|
+
registry read confirms it.
|
|
99
113
|
- Then chase the remaining uploads back-to-back in one process with no gap. An upload started
|
|
100
114
|
within seconds of an approval frequently rides that approval, and each one that does not mints
|
|
101
115
|
its own URL.
|
|
@@ -127,14 +141,25 @@ the same status. Rule from the evidence, never from which cause reads likelier.
|
|
|
127
141
|
opened, and the registry closed the session.
|
|
128
142
|
- The user clicked a superseded URL and poisoned the live attempt. The poll fails mid-flight while
|
|
129
143
|
the user is looking at a page that reports success.
|
|
144
|
+
- The registry refused the attempt's first poll, seconds after the mint and before anyone could
|
|
145
|
+
click, because the poll left from an egress address other than the one that minted the session.
|
|
146
|
+
npm reads that `403` as web login unsupported and drops to the legacy `Username:` prompt within
|
|
147
|
+
seconds rather than at 45. Recover by minting attempts on a kept-alive connection until one
|
|
148
|
+
survives its first poll and relaying that one alone, per § Reach the approval.
|
|
130
149
|
- Tell those causes apart from the log and the user, never from the status alone. A single minted
|
|
131
150
|
URL that nobody opened in time is the abandon. A log carrying a URL the running attempt
|
|
132
|
-
superseded, with the user reporting a click, is the poisoned attempt.
|
|
151
|
+
superseded, with the user reporting a click, is the poisoned attempt. A drop within seconds of
|
|
152
|
+
the mint, before any relay, is the egress refusal.
|
|
133
153
|
- Recover the same way whichever it was: read the registry for the version, confirm no publish
|
|
134
154
|
process is live, then mint exactly one fresh attempt with the user at the keyboard.
|
|
135
155
|
|
|
136
156
|
## Read the verdict from the registry
|
|
137
157
|
|
|
158
|
+
- Read `+ @orkestrel/<name>@<version>` in the upload's own journal as the accepted verdict, and
|
|
159
|
+
advance the chain on it. The registry's read lags its processing by minutes, which the
|
|
160
|
+
`Your package is being processed and may take a few minutes to become available.` notice beside
|
|
161
|
+
that line announces, so a chain keyed on the registry stops on an accepted upload. Read the
|
|
162
|
+
registry to confirm and to record the layer's close, never to gate the next upload.
|
|
138
163
|
- Read the result from the registry, not from an exit code. A piped `npm publish` reports the exit
|
|
139
164
|
status of the pipeline, and a CDN read straight after a publish can still serve the previous
|
|
140
165
|
version.
|