@adia-ai/adia-ui-forge 0.8.57 → 0.8.59
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/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/CHANGELOG.md +64 -0
- package/README.md +2 -2
- package/__init__.py +3 -3
- package/package.json +2 -2
- package/plugin.yaml +1 -1
- package/scripts/lint-rules.generated.mjs +29342 -131
- package/skills/a2ui-maintenance/references/pipeline-overview.md +8 -2
- package/skills/component-md-authoring/SKILL.md +18 -14
- package/skills/demo-audit/SKILL.md +3 -3
- package/skills/demo-audit/agents/openai.yaml +1 -1
- package/skills/demo-audit/references/admin-shell-anatomy.md +9 -1
- package/skills/demo-audit/references/app-shell-pitfalls.md +7 -2
- package/skills/demo-audit/references/chat-shell-anatomy.md +98 -0
- package/skills/demo-audit/references/editor-shell-anatomy.md +109 -0
- package/skills/package-release/references/cut-procedure.md +66 -0
- package/skills/package-release/scripts/bump.mjs +41 -2
- package/skills/package-release/scripts/gate-roster.mjs +35 -0
- package/skills/package-release/scripts/release-pack.mjs +57 -0
- package/skills/primitive-authoring/SKILL.md +5 -2
- package/skills/primitive-authoring/agents/openai.yaml +1 -1
- package/skills/primitive-authoring/references/anti-patterns.md +40 -0
- package/skills/primitive-authoring/references/css-patterns.md +12 -0
- package/skills/primitive-authoring/references/form-control-sizing.md +10 -0
- package/skills/primitive-authoring/references/shell-patterns.md +8 -1
- package/skills/primitive-authoring/references/token-contract.md +19 -1
- package/skills/primitive-authoring/references/yaml-contract.md +16 -0
|
@@ -65,7 +65,7 @@ has no standing replacement — see ADR-0072 Decision 2 / gh#2410 for the
|
|
|
65
65
|
closure record.
|
|
66
66
|
|
|
67
67
|
All paths repo-relative. Specs worth reading before structural changes:
|
|
68
|
-
`.claude/docs/specs/a2ui-
|
|
68
|
+
`.claude/docs/specs/a2ui-v1.0-catalog-guide.md` (protocol + catalog format),
|
|
69
69
|
`.claude/docs/specs/genui-multiturn-architecture.md` (state cache, refiner,
|
|
70
70
|
op format), `.claude/docs/specs/genui-chunk-marker.md` (chunk attributes),
|
|
71
71
|
`.claude/docs/conventions/gen-ui-pipeline.md` (harvester wiring + embedding
|
|
@@ -154,7 +154,13 @@ for any constant or decision lives in git and PR descriptions
|
|
|
154
154
|
7. **Registry ↔ catalog parity.** A component in the runtime registry but
|
|
155
155
|
missing from catalog schemas silently drops from generated compositions —
|
|
156
156
|
`npm run check:registry-catalog-coherence` guards it; run it after catalog
|
|
157
|
-
changes.
|
|
157
|
+
changes. `packages/gen-ui/a2ui/registry.js` is Class R (ADR-0069,
|
|
158
|
+
gh#3055): never hand-edit it — a new component enters through its yaml
|
|
159
|
+
`component:`/`tag:` fields, an alias or native-element mapping through
|
|
160
|
+
`packages/gen-ui/a2ui/registry.exceptions.json`, then
|
|
161
|
+
`node scripts/build/a2ui-registry.mjs` (derived-resync regenerates it on
|
|
162
|
+
main; `check:a2ui-registry` is the advisory freshness gate,
|
|
163
|
+
`check:a2ui-registry:validate` the blocking validity gate).
|
|
158
164
|
8. **Multi-turn emits A2UI `updateComponents` messages, not new compositions.**
|
|
159
165
|
The chunk-refiner mutates the binding plan via four ops (`rebindSlot` /
|
|
160
166
|
`appendToSlot` / `removeFromSlot` / `replacePage`); state chains via
|
|
@@ -6,7 +6,7 @@ description: >-
|
|
|
6
6
|
component's states, composed children, aria behavior, or error/empty/
|
|
7
7
|
loading handling changes and it already has (or should grow) a
|
|
8
8
|
`component.md`, or when asked to "add component.md for X" / "write the
|
|
9
|
-
screen-reader spec for X" / "why
|
|
9
|
+
screen-reader spec for X" / "why is check:component-md-fresh warning". NOT
|
|
10
10
|
the yaml prop/slot/event/token contract itself (primitive-authoring owns
|
|
11
11
|
that — this skill only owns the two authored yaml fields,
|
|
12
12
|
`screenReader`/`behavioral`, plus the optional `intent` field); NOT gen-ui
|
|
@@ -39,14 +39,16 @@ regenerated from them. This is deliberate, not incidental:
|
|
|
39
39
|
gaps — screen-reader and behavioral judgment — get the SAME treatment:
|
|
40
40
|
authored once, in yaml, transcluded everywhere else (component.md today;
|
|
41
41
|
gen-ui corpus derivation once a2ui-maintenance wires it in).
|
|
42
|
-
-
|
|
43
|
-
authored content lives in a yaml
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
42
|
+
- **`component.md` is Class R, derived on main, not authored in the PR
|
|
43
|
+
(gh#3172, ADR-0069).** Because the authored content lives in a yaml
|
|
44
|
+
field, `component.md` is 100% mechanically regenerable — a PR commits
|
|
45
|
+
only the `screenReader`/`behavioral` yaml edit; `check:component-md-fresh`
|
|
46
|
+
runs advisory-only inside `check:pr-ready` (WARN, never fails the run)
|
|
47
|
+
and the `push: main` `derived-resync` job regenerates `component.md`
|
|
48
|
+
itself once the PR merges. A hand-edit directly in `component.md` will
|
|
49
|
+
still be silently clobbered by the next `npm run docs:component-md` or
|
|
50
|
+
by `derived-resync` on main — that's the guard rail, not a bug, even
|
|
51
|
+
though nothing blocks the PR on it.
|
|
50
52
|
|
|
51
53
|
## Authoring a component's two sections
|
|
52
54
|
|
|
@@ -79,7 +81,7 @@ regenerated from them. This is deliberate, not incidental:
|
|
|
79
81
|
```bash
|
|
80
82
|
node scripts/build/components.mjs --validate # schema-valid yaml
|
|
81
83
|
npm run docs:component-md # regenerate component.md
|
|
82
|
-
npm run check:component-md-fresh #
|
|
84
|
+
npm run check:component-md-fresh # advisory gate (check:pr-ready); derived-resync owns main
|
|
83
85
|
```
|
|
84
86
|
|
|
85
87
|
6. If this is the component's FIRST component.md (yaml previously had
|
|
@@ -110,7 +112,9 @@ defeats the point of a rollout plan).
|
|
|
110
112
|
- `scripts/schemas/component.yaml.schema.json` — `intent`/`screenReader`/
|
|
111
113
|
`behavioral` field definitions (all optional; a component with a `.yaml`
|
|
112
114
|
but neither authored field simply has no `component.md` yet).
|
|
113
|
-
- `scripts/verify/check-component-md-fresh.mjs` — the
|
|
114
|
-
byte-freshness (component.md matches a fresh render)
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
- `scripts/verify/check-component-md-fresh.mjs` — the freshness gate:
|
|
116
|
+
byte-freshness (component.md matches a fresh render). Advisory-only in
|
|
117
|
+
`check:pr-ready` (gh#3172, ADR-0069) — a PR commits the yaml edit alone
|
|
118
|
+
and `derived-resync` regenerates `component.md` on `push: main`; the
|
|
119
|
+
same-PR coverage check this gate used to run was removed outright
|
|
120
|
+
(LLD-0020 §1c), not demoted.
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
name: demo-audit
|
|
3
3
|
description: >-
|
|
4
4
|
Seven-mode QA sweep of the monorepo's demo/app surfaces: visual probe,
|
|
5
|
-
app-shell QA, attr-quote typos, native-primitive leak, admin
|
|
6
|
-
composition, card anatomy, plus an aggregated token/contrast/lifecycle
|
|
5
|
+
app-shell QA, attr-quote typos, native-primitive leak, shell (admin/chat/
|
|
6
|
+
editor) composition, card anatomy, plus an aggregated token/contrast/lifecycle
|
|
7
7
|
drift battery (`npm run dogfood:status`). Use for "run a dogfood sweep",
|
|
8
8
|
"find broken demos", "audit native primitive leaks". NOT for gen-UI
|
|
9
9
|
gallery scoring (gen-ui-review) or authoring primitives (primitive-authoring).
|
|
@@ -33,7 +33,7 @@ below — load it before running or triaging.
|
|
|
33
33
|
| 2 | App-shell QA — after `apps/` structural sweeps; before a release | [app-shell-pitfalls](references/app-shell-pitfalls.md) |
|
|
34
34
|
| 3 | HTML attr-quote typo sweep — nested `"` broke an attribute boundary | [html-attr-sweep](references/html-attr-sweep.md) |
|
|
35
35
|
| 4 | Native-primitive leak — `<button>` where `<button-ui>` exists | [native-leak-annotations](references/native-leak-annotations.md) |
|
|
36
|
-
| 5 |
|
|
36
|
+
| 5 | Shell composition — incomplete `<admin-shell>` / `<chat-shell>` / `<editor-shell>` anatomy | [admin-shell-anatomy](references/admin-shell-anatomy.md), [chat-shell-anatomy](references/chat-shell-anatomy.md), [editor-shell-anatomy](references/editor-shell-anatomy.md) |
|
|
37
37
|
| 6 | Card structure + anatomy docs coverage | [card-anatomy-sweep](references/card-anatomy-sweep.md) |
|
|
38
38
|
| 7 | Token/contrast/lifecycle/yaml drift battery — independent of modes 1–6 | [mode7-status-battery](references/mode7-status-battery.md) |
|
|
39
39
|
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
interface:
|
|
2
2
|
display_name: "Demo Audit"
|
|
3
|
-
short_description: "Seven-mode QA sweep of the monorepo's demo/app surfaces: visual probe, app-shell QA, attr-quote typos, native-primitive leak,
|
|
3
|
+
short_description: "Seven-mode QA sweep of the monorepo's demo/app surfaces: visual probe, app-shell QA, attr-quote typos, native-primitive leak, shell (admin/chat/ editor) composition, card anatomy, plus an aggregated token/contrast/lifecycle drift battery (`npm run dogfood:status`)."
|
|
@@ -30,7 +30,15 @@ the live admin-dashboard example.
|
|
|
30
30
|
(there is no `<theme-picker-ui>`)
|
|
31
31
|
9. `<admin-scroll>` wrapping optional `<aside data-subnav hidden>` +
|
|
32
32
|
`<router-ui>` (or `<admin-page>` directly for non-routed)
|
|
33
|
+
**[deprecated 2026-09-01, ADR-0098]** `admin-scroll` is a wholesale
|
|
34
|
+
rename to `page-scroll` (both modes carried over); `admin-scroll` stays
|
|
35
|
+
as a working compat alias for the deprecation window only.
|
|
33
36
|
10. `<admin-page>` with `<admin-page-header>` + `<admin-page-body>`
|
|
37
|
+
**[deprecated 2026-09-01, ADR-0098]** The `admin-page` family is
|
|
38
|
+
retired deprecate-then-delete in favor of `page-ui[band]` — `page-ui`
|
|
39
|
+
is now the one canonical page-chrome primitive; this anatomy still
|
|
40
|
+
describes the pre-migration shape for auditing legacy surfaces during
|
|
41
|
+
the deprecation window.
|
|
34
42
|
11. `<admin-statusbar>` at content footer (version strip) — ★ commonly missing
|
|
35
43
|
12. Second `<admin-sidebar slot="trailing">` (inspector rail, hidden by
|
|
36
44
|
default) — strongly recommended
|
|
@@ -56,7 +64,7 @@ the live admin-dashboard example.
|
|
|
56
64
|
| content topbar missing `[data-spacer]` / `[data-actions]` | warning — part 7 |
|
|
57
65
|
| content missing trailing `<admin-statusbar>` | warning — part 11 |
|
|
58
66
|
| sidebar topbar contains only plain text | warning — part 3 context switcher |
|
|
59
|
-
| `<admin-scroll>` missing around `<admin-page>` | critical — part 9 (the enforcing script `audit-shell-composition.mjs` tiers this critical: without the scroll+page wrapper the content renders flush with the topbar, no margins) |
|
|
67
|
+
| `<admin-scroll>` missing around `<admin-page>` | critical — part 9 (the enforcing script `audit-shell-composition.mjs` tiers this critical: without the scroll+page wrapper the content renders flush with the topbar, no margins) — **[deprecated 2026-09-01, ADR-0098]** `admin-scroll`/`admin-page` describe the pre-migration shape; the successor is `page-scroll` wrapping `page-ui[band]` |
|
|
60
68
|
|
|
61
69
|
## Opt-out contract
|
|
62
70
|
|
|
@@ -4,7 +4,10 @@ Script: `node scripts/dev/audit-app-shells.mjs` (repo-local). Walks every
|
|
|
4
4
|
`apps/<name>/…/<page>.html` shell headlessly and checks console errors,
|
|
5
5
|
custom-element registration, collapsed heights, icon-ui presence, demo-root
|
|
6
6
|
flex, and network 4xx/5xx. Flags: `--only=NAME` · `--fail-fast` ·
|
|
7
|
-
`--compare-prod` (diff registered tags against the prod deploy)
|
|
7
|
+
`--compare-prod` (diff registered tags against the prod deploy) ·
|
|
8
|
+
`--playgrounds` (gh#3197 — also sweeps `playgrounds/<name>/app/<name>.html`,
|
|
9
|
+
same shell shape; opt-in because that root carries other pre-existing,
|
|
10
|
+
unaudited findings — combine with `--only=NAME` to scope to one playground).
|
|
8
11
|
|
|
9
12
|
Prerequisites: `npm run dev` running (vite `:5173`); `npm run proxy` only when
|
|
10
13
|
probing chat / gen-ui pages. If vite is mid dep-reoptimization the first sweep
|
|
@@ -20,7 +23,7 @@ may stall — wait 30s, re-run.
|
|
|
20
23
|
| 4 | Top-level `await` without async setup wrap | `[setup-failed]` console error | `export default async function setup(host) { … }` |
|
|
21
24
|
| 5 | Vite import-analysis 500 on dynamic import | `[network-4xx] 500` for `./<name>.contents.js` | add `/* @vite-ignore */` to the dynamic import |
|
|
22
25
|
| 6 | icon-ui not imported despite `<icon-ui>` / `[icon=…]` / icon-rendering composites | `[icon-ui-missing]` | `import "/packages/web-components/components/icon/icon.js"` |
|
|
23
|
-
| 7 | `<admin-page-body>` emitted without its `<admin-page>` ancestor (gh#981) | *(no audit-app-shells.mjs tag — apps/-only script, doesn't sweep this surface)* | wrap in `<admin-page>` — `admin-page > admin-page-body { flex:1; … }` (`admin-shell.bespoke.css:144`) is a direct-child selector; without that literal parent, `admin-page-body` falls back to UA `display:inline` |
|
|
26
|
+
| 7 | `<admin-page-body>` emitted without its `<admin-page>` ancestor (gh#981) | *(no audit-app-shells.mjs tag — apps/-only script, doesn't sweep this surface)* | wrap in `<admin-page>` — `admin-page > admin-page-body { flex:1; … }` (`admin-shell.bespoke.css:144`) is a direct-child selector; without that literal parent, `admin-page-body` falls back to UA `display:inline` — **[deprecated 2026-09-01, ADR-0098]** `admin-page`/`admin-page-body` are retired deprecate-then-delete; author new surfaces with `page-ui[band]` instead |
|
|
24
27
|
|
|
25
28
|
Secondary signals: `[collapsed-element]` (registered but 0px tall —
|
|
26
29
|
`audit-app-shells.mjs`'s own threshold is <4px, so a shallower-but-still-broken
|
|
@@ -42,6 +45,8 @@ with no console error, regardless of real content height.
|
|
|
42
45
|
| `button-ui` (with `icon=`) | `icon-ui` |
|
|
43
46
|
| `badge-ui` (with `icon=`) | `icon-ui` |
|
|
44
47
|
| `menu-item-ui` | `icon-ui`, `text-ui` |
|
|
48
|
+
| `admin-roster-ui` | `upload-ui`, `menu-item-ui` |
|
|
49
|
+
| `table-toolbar-ui` | `search-ui`, `select-ui`, `menu-ui`, `menu-item-ui` |
|
|
45
50
|
|
|
46
51
|
## Registration diagnosis rules
|
|
47
52
|
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Mode 5b — Chat-shell composition: the canonical parts
|
|
2
|
+
|
|
3
|
+
Script: `scripts/dev/audit-shell-composition.mjs` (repo-local), npm gates
|
|
4
|
+
`audit:shell-composition{,:strict,:all}`. Static AST walk over
|
|
5
|
+
`apps/**/*.html`, `playgrounds/**/*.html`, `catalog/page-shells/**/*.html` —
|
|
6
|
+
no browser needed; pre-commit fast. Shares one script and one output
|
|
7
|
+
contract with the `<admin-shell>` census
|
|
8
|
+
([admin-shell-anatomy](admin-shell-anatomy.md)) — the script's own `CHAT_PARTS`
|
|
9
|
+
array is the mechanical census; this file is the human review standard.
|
|
10
|
+
Canonical source: `packages/web-modules/chat/chat-shell/chat-shell.yaml`
|
|
11
|
+
(the behavioral contract) and `playgrounds/chat/app/chat.contents.html`
|
|
12
|
+
(the canonical rendered reference, cited by `apps/genui/PATTERNS.md`'s
|
|
13
|
+
chrome-decision table as chat-shell's canonical demo).
|
|
14
|
+
|
|
15
|
+
`gh#2909`/`apps/genui/PATTERNS.md:329-337` established that `apps/genui`
|
|
16
|
+
(gen-ui, factory-chat) is a real `<chat-shell>` consumer that a
|
|
17
|
+
`<admin-shell>`-only mode 5 sweep never scanned — this anatomy closes that
|
|
18
|
+
blind spot.
|
|
19
|
+
|
|
20
|
+
## The canonical parts
|
|
21
|
+
|
|
22
|
+
1. `<chat-shell provider="…" model="…" proxy-url="…">` outer.
|
|
23
|
+
2. `<chat-thread>` direct child — the message scroll surface. Required:
|
|
24
|
+
without it there is nowhere for the host's rendering pipeline to append
|
|
25
|
+
messages.
|
|
26
|
+
3. `<chat-thread> > <chat-empty>` as (typically first) child — the
|
|
27
|
+
empty-state placeholder shown via the `[empty]` reflected attribute
|
|
28
|
+
before any message exists.
|
|
29
|
+
4. `<chat-composer>` direct child — the input region.
|
|
30
|
+
5. `<chat-composer> > <chat-input-ui>` (or `<input-ui>`) inner child — the
|
|
31
|
+
actual input; a composer with no primitive input inside has nothing to
|
|
32
|
+
submit.
|
|
33
|
+
6. `<chat-header>` direct child — optional top chrome bar (name, status,
|
|
34
|
+
actions). When present, expected to carry `[slot="name"]` and
|
|
35
|
+
`[slot="status"]` (typically a `<chat-status>`) — a header with neither
|
|
36
|
+
is bare chrome with no identifying content.
|
|
37
|
+
7. `<chat-sidebar slot="leading"|"trailing">` — optional conversation-history
|
|
38
|
+
or inspector rail.
|
|
39
|
+
8. No generic layout primitive (`<col-ui>`, `<row-ui>`, `<stack-ui>`) as a
|
|
40
|
+
**direct child** of `<chat-shell>` — the shell's CSS lays out children by
|
|
41
|
+
tag selector (`chat-thread`, `chat-composer`, etc.); a generic wrapper
|
|
42
|
+
defeats that and the shell's `:has(chat-thread[streaming])` cross-cut
|
|
43
|
+
styling.
|
|
44
|
+
|
|
45
|
+
## Severity mapping
|
|
46
|
+
|
|
47
|
+
- **critical** — `<chat-shell>` present but missing `<chat-thread>` or
|
|
48
|
+
`<chat-composer>` (parts 2, 4). The shell can't render a usable
|
|
49
|
+
conversation surface without both.
|
|
50
|
+
- **warning** — `<chat-composer>` has no inner `<chat-input-ui>`/`<input-ui>`
|
|
51
|
+
(part 5); a `<chat-header>` present but missing both `[slot="name"]` and
|
|
52
|
+
`[slot="status"]` content (part 6); a generic layout primitive
|
|
53
|
+
(`col-ui`/`row-ui`/`stack-ui`) authored as a direct child (part 8).
|
|
54
|
+
- **info** — `<chat-thread>` missing its `<chat-empty>` first child (part 3;
|
|
55
|
+
a thread pre-seeded with real messages legitimately skips this);
|
|
56
|
+
`<chat-header>` absent entirely (part 6 is optional chrome);
|
|
57
|
+
`<chat-sidebar>` absent (part 7, forward-looking per the yaml — chat is
|
|
58
|
+
typically single-pane).
|
|
59
|
+
|
|
60
|
+
## What the script flags (mechanical subset)
|
|
61
|
+
|
|
62
|
+
| Symptom | Diagnosis |
|
|
63
|
+
|---|---|
|
|
64
|
+
| `<chat-shell>` with no `<chat-thread>` | critical — part 2 |
|
|
65
|
+
| `<chat-shell>` with no `<chat-composer>` | critical — part 4 |
|
|
66
|
+
| `<chat-composer>` with no `<chat-input-ui>`/`<input-ui>` child | warning — part 5 |
|
|
67
|
+
| `<chat-header>` present, no `[slot="name"]` and no `[slot="status"]`/`<chat-status>` | warning — part 6 |
|
|
68
|
+
| `<chat-shell>` direct child is `col-ui`/`row-ui`/`stack-ui` | warning — part 8 (legacy-generic-layout leak) |
|
|
69
|
+
| `<chat-thread>` with no `<chat-empty>` child | info — part 3 |
|
|
70
|
+
|
|
71
|
+
## Opt-out contract
|
|
72
|
+
|
|
73
|
+
Same annotation mechanism as admin-shell: `<chat-shell
|
|
74
|
+
data-shell-opt-out="reason">` downgrades every finding on that shell to
|
|
75
|
+
info and prints the reason for reviewers.
|
|
76
|
+
|
|
77
|
+
## Triage
|
|
78
|
+
|
|
79
|
+
- Canonical product surface (`apps/genui` chat/factory-chat pages,
|
|
80
|
+
`playgrounds/chat/*`) → fix mandatory.
|
|
81
|
+
- A narrow single-feature playground isolating one chat behavior → fix
|
|
82
|
+
optional; annotate the opt-out.
|
|
83
|
+
- Never point this audit at `packages/web-modules/chat/**/*.examples.html`
|
|
84
|
+
or `packages/web-components/components/*/*.html` (single-primitive
|
|
85
|
+
spotlights) — the script's `isShowcaseDemo`/showcase-path exclusion
|
|
86
|
+
already keeps those out of scope, same as admin-shell.
|
|
87
|
+
- `:strict` is the CI/publish posture; keep warn-only while iterating
|
|
88
|
+
locally.
|
|
89
|
+
|
|
90
|
+
## Legacy shapes — never re-authored
|
|
91
|
+
|
|
92
|
+
`chat-shell.yaml`'s own description lists the ADR-0024-retired legacy
|
|
93
|
+
data-attribute shapes (`<section data-chat-messages>`, `<chat-input-ui
|
|
94
|
+
data-chat-input>`, `<empty-state-ui data-chat-empty>`, `<header
|
|
95
|
+
data-chat-name>`) as silently unrecognized, not merely deprecated. This
|
|
96
|
+
audit does not re-detect them (a separate concern from anatomy
|
|
97
|
+
completeness) — `verify:no-legacy-shell-shapes` in `npm run check` already
|
|
98
|
+
covers that ground.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Mode 5c — Editor-shell composition: the canonical parts
|
|
2
|
+
|
|
3
|
+
Script: `scripts/dev/audit-shell-composition.mjs` (repo-local), npm gates
|
|
4
|
+
`audit:shell-composition{,:strict,:all}`. Static AST walk over
|
|
5
|
+
`apps/**/*.html`, `playgrounds/**/*.html`, `catalog/page-shells/**/*.html` —
|
|
6
|
+
no browser needed; pre-commit fast. Shares one script and one output
|
|
7
|
+
contract with the `<admin-shell>` census
|
|
8
|
+
([admin-shell-anatomy](admin-shell-anatomy.md)) — the script's own
|
|
9
|
+
`EDITOR_PARTS` array is the mechanical census; this file is the human
|
|
10
|
+
review standard. Canonical source:
|
|
11
|
+
`packages/web-modules/editor/editor-shell/editor-shell.yaml` (the
|
|
12
|
+
behavioral contract) and `apps/construct-canvas/app/construct-canvas.contents.html`
|
|
13
|
+
(the canonical rendered reference, cited by `apps/genui/PATTERNS.md`'s
|
|
14
|
+
chrome-decision table as editor-shell's canonical demo, alongside
|
|
15
|
+
`apps/genui`'s own a2ui-editor consumer).
|
|
16
|
+
|
|
17
|
+
`gh#2909`/`apps/genui/PATTERNS.md:329-337` established that `apps/genui`
|
|
18
|
+
(a2ui-editor) is a real `<editor-shell>` consumer that a
|
|
19
|
+
`<admin-shell>`-only mode 5 sweep never scanned — this anatomy closes that
|
|
20
|
+
blind spot.
|
|
21
|
+
|
|
22
|
+
## The canonical parts
|
|
23
|
+
|
|
24
|
+
1. `<editor-shell>` outer.
|
|
25
|
+
2. `<editor-canvas>` direct child — the central work surface. Required:
|
|
26
|
+
without it there is nowhere for artboards/document body/canvas content
|
|
27
|
+
to land, the editor equivalent of admin-shell's `<admin-content>`.
|
|
28
|
+
3. `<editor-toolbar>` direct child — the app-scope top chrome bar (document
|
|
29
|
+
title, run/save/undo/redo, focus-mode toggle). Recommended; an editor
|
|
30
|
+
with no toolbar has no document-wide action surface.
|
|
31
|
+
4. `<editor-canvas> > <editor-canvas-empty>` as (typically first) child —
|
|
32
|
+
the empty-state placeholder shown via the parent's `[empty]` reflected
|
|
33
|
+
attribute before any content exists.
|
|
34
|
+
5. `<editor-canvas> > <editor-canvas-toolbar>` — optional canvas-scope
|
|
35
|
+
chrome (view-mode tabs, breadcrumbs) sticky to the canvas top edge;
|
|
36
|
+
distinct from part 3's app-scope toolbar.
|
|
37
|
+
6. `<editor-statusbar>` direct child — bottom chrome bar (save/sync state,
|
|
38
|
+
zoom, cursor position). Recommended; loses the canonical status-strip
|
|
39
|
+
without it.
|
|
40
|
+
7. `<editor-sidebar slot="leading"|"trailing">` — optional navigator or
|
|
41
|
+
inspector rail.
|
|
42
|
+
8. When an `<editor-sidebar>` is present, it must wrap `<pane-ui
|
|
43
|
+
resizable>` (or at minimum `<pane-ui>`) — editor-sidebar is the one
|
|
44
|
+
bespoke shell child that **delegates** rather than duplicates a
|
|
45
|
+
primitive's resize behavior (per `shell-patterns.md`'s "FIRST bespoke
|
|
46
|
+
shell child that delegates" note); an editor-sidebar with no inner
|
|
47
|
+
`<pane-ui>` reimplements drag by hand instead of reusing the primitive.
|
|
48
|
+
9. No bare `<header>` / `<footer>` native elements as direct children of
|
|
49
|
+
`<editor-shell>` — these are the ADR-0024-retired legacy chrome shapes
|
|
50
|
+
that `<editor-toolbar>` / `<editor-statusbar>` replaced.
|
|
51
|
+
|
|
52
|
+
## Severity mapping
|
|
53
|
+
|
|
54
|
+
- **critical** — `<editor-shell>` present but missing `<editor-canvas>`
|
|
55
|
+
(part 2). The shell can't render usable content without it.
|
|
56
|
+
- **warning** — no `<editor-toolbar>` (part 3); no `<editor-statusbar>`
|
|
57
|
+
(part 6); an `<editor-sidebar>` present with no inner `<pane-ui>` (part
|
|
58
|
+
8); a bare native `<header>`/`<footer>` direct child (part 9, the
|
|
59
|
+
retired-legacy-shape leak).
|
|
60
|
+
- **info** — `<editor-canvas>` missing its `<editor-canvas-empty>` first
|
|
61
|
+
child (part 4; a canvas pre-seeded with real content legitimately skips
|
|
62
|
+
this); no `<editor-canvas-toolbar>` (part 5, optional canvas chrome); no
|
|
63
|
+
`<editor-sidebar>` at all (part 7 — `construct-canvas`'s own comment
|
|
64
|
+
notes "no leading pane today", a legitimately sidebar-less composition).
|
|
65
|
+
|
|
66
|
+
## What the script flags (mechanical subset)
|
|
67
|
+
|
|
68
|
+
| Symptom | Diagnosis |
|
|
69
|
+
|---|---|
|
|
70
|
+
| `<editor-shell>` with no `<editor-canvas>` | critical — part 2 |
|
|
71
|
+
| `<editor-shell>` with no `<editor-toolbar>` | warning — part 3 |
|
|
72
|
+
| `<editor-shell>` with no `<editor-statusbar>` | warning — part 6 |
|
|
73
|
+
| `<editor-sidebar>` present, no inner `<pane-ui>` | warning — part 8 (delegation contract violated) |
|
|
74
|
+
| `<editor-shell>` direct child is native `<header>`/`<footer>` | warning — part 9 (retired-legacy-shape leak) |
|
|
75
|
+
| `<editor-canvas>` with no `<editor-canvas-empty>` child | info — part 4 |
|
|
76
|
+
|
|
77
|
+
## Opt-out contract
|
|
78
|
+
|
|
79
|
+
Same annotation mechanism as admin-shell: `<editor-shell
|
|
80
|
+
data-shell-opt-out="reason">` downgrades every finding on that shell to
|
|
81
|
+
info and prints the reason for reviewers.
|
|
82
|
+
|
|
83
|
+
## Triage
|
|
84
|
+
|
|
85
|
+
- Canonical product surface (`apps/construct-canvas`, `apps/genui`'s
|
|
86
|
+
a2ui-editor) → fix mandatory.
|
|
87
|
+
- A narrow single-feature playground isolating one editor behavior → fix
|
|
88
|
+
optional; annotate the opt-out.
|
|
89
|
+
- Never point this audit at `packages/web-modules/editor/**/*.examples.html`
|
|
90
|
+
or `packages/web-components/components/*/*.html` (single-primitive
|
|
91
|
+
spotlights) — the script's `isShowcaseDemo`/showcase-path exclusion
|
|
92
|
+
already keeps those out of scope, same as admin-shell.
|
|
93
|
+
- **Don't nest `<editor-shell>` inside `<admin-shell>`** as page chrome —
|
|
94
|
+
`editor-shell.examples.html` documents them as sibling surfaces, not
|
|
95
|
+
nested; this audit doesn't mechanically flag the nesting mistake (a
|
|
96
|
+
cross-shell structural rule, not a within-shell anatomy gap), but a
|
|
97
|
+
reviewer seeing both tags in one file should treat it as a design smell.
|
|
98
|
+
- `:strict` is the CI/publish posture; keep warn-only while iterating
|
|
99
|
+
locally.
|
|
100
|
+
|
|
101
|
+
## Legacy shapes — never re-authored
|
|
102
|
+
|
|
103
|
+
`editor-shell.yaml`'s own description lists the ADR-0024-retired legacy
|
|
104
|
+
data-attribute shapes (`<header>`, `<div data-editor-body>`, `<pane-ui
|
|
105
|
+
data-left|data-right>`, `<div data-canvas>`, `<footer>`, `<span
|
|
106
|
+
data-spacer>`) as silently unrecognized, not merely deprecated. Part 9
|
|
107
|
+
above catches the two structural container tags (`<header>`/`<footer>`)
|
|
108
|
+
mechanically; the finer-grained data-attribute forms are already covered
|
|
109
|
+
by `verify:no-legacy-shell-shapes` in `npm run check`.
|
|
@@ -23,6 +23,7 @@ Two entry variants, converging at Step 5:
|
|
|
23
23
|
| 1 | Re-baseline (branch check + status + log + fetch) | No |
|
|
24
24
|
| 2 | Classify uncommitted files; stash strays | Stash only |
|
|
25
25
|
| 3 | Pre-flight gates (+ harvest preamble if source content changed) | No |
|
|
26
|
+
| 4a-pre | Assemble `changes/<pr>.md` fragments into the right `[Unreleased]` (REQ-W11-06) | Yes |
|
|
26
27
|
| 4 | (Variant B) Promote `[Unreleased]`; bump; lockfile | Yes |
|
|
27
28
|
| 4f | Pre-tag coverage `--fix` — authoritative F-N1 matcher, pre-PR | CHANGELOGs |
|
|
28
29
|
| 5 | Stage the release allowlist; commit on `release/vX.Y.Z` | Yes |
|
|
@@ -100,6 +101,8 @@ When only source *hashes* move and chunk content does not, `check:embeddings-fre
|
|
|
100
101
|
|
|
101
102
|
**Regen output supersedes working-tree state.** These outputs land in the release commit unconditionally, even when the same paths are also dirty from a peer — the fresh regen is authoritative; divergent uncommitted work rebases on top afterwards.
|
|
102
103
|
|
|
104
|
+
**Staging a read-only report without cutting** (gh#3063): `node scripts/release/preflight-dry-run.mjs --version X.Y.Z` runs this same roster (`gate-roster.mjs` SoT) inside a throwaway `npm ci` clone and prints per-gate PASS/FAIL plus a tail-of-log on failure — no bump, no tag, no CHANGELOG promotion, nothing lands on the real repo. This mechanizes the ad-hoc procedure the 0.8.59 staging pre-flight hand-drove (gh#2870 comments 5526330460 + addendum); use it whenever a "how healthy is main right now" report is wanted ahead of an actual cut. `--dry-run` lists the roster with no clone/npm ci; `--keep` preserves the throwaway clone for inspection.
|
|
105
|
+
|
|
103
106
|
### 3.1 The full roster — every gate runs; a subset = pre-flight failure
|
|
104
107
|
|
|
105
108
|
**Execution model (gh#2006): three phases, not one serial walk.** `step3PreFlight()` runs gate 4 solo first (see its own note below), then gates 16 → 27 → 28 strictly in order (the eval-health write-then-read dependency — gate 28 reads whichever `evals/mcp/runs/` directory sorts lexically LAST, so nothing else may write there between 27 and 28), concurrently with a bounded pool running every other gate at once (`PREFLIGHT_CONCURRENCY`, default 4 — override for a dedicated/idle host). Every gate still resolves the same command, still fails the whole pre-flight on a red result, and still reports its own number — only the WALL-CLOCK schedule changed, never the roster below or its numbering. `--dry` previews stay the original flat serial walk unchanged.
|
|
@@ -137,6 +140,11 @@ node scripts/release/check-estate-split-latch.mjs # 29 no lockstep cut
|
|
|
137
140
|
npm run check:catalog-tiers # 30 tier-index.json vs committed catalog (gh#1494 — ADR-0069 moved its PR-blocking half to derived-resync; the pre-cut roster re-asserts Class-R freshness before a tag. Gate 13 can't catch this: the harvester hashes tier-index.json as a SOURCE)
|
|
138
141
|
npm run check:codex-manifests-fresh # 31 Codex plugin.json + openai.yaml vs .claude-plugin/plugin.json SoT (gh#1888)
|
|
139
142
|
npm run check:harness-manifests-fresh # 32 Hermes/Pi plugin.yaml + __init__.py + prompts vs .claude-plugin/plugin.json + commands SoT (gh#1954)
|
|
143
|
+
npm run verify:patterns-index # 33 pattern-index.md (mcp + adia-ui-factory) vs corpus source
|
|
144
|
+
node scripts/release/check-yaml-events-vs-runtime.mjs --strict --strict-details # 34 yaml events: blocks vs runtime dispatch — no phantom/missing events (gh#2829)
|
|
145
|
+
node scripts/release/check-yaml-impl-coverage.mjs --strict # 35 yaml schema fields vs implementation coverage (gh#2829)
|
|
146
|
+
npm run check:treeshake # 36 single-import build matrix (esbuild+rollup) — byte budgets + marker-leak + CSS purity + whole-lib delta + docs grep-gate (gh#2912)
|
|
147
|
+
npm run check:lint-efficacy # 37 lint rule bank: seeded catch rate 100% + golden-set 0 error FPs + mutation hardening (gh#2911 — not in `npm run check`, ~100s over the <60s bar)
|
|
140
148
|
```
|
|
141
149
|
|
|
142
150
|
**Gate 29 was the ADR-0048 latch; since P5 it is a permanent invariant.** Between P1 and P5 the repo was correct in-repo but deliberately **not publishable** (old-name stubs marked `private: true` that the roster still mapped, plus dependency edges onto workspace packages no cut published), and a cut in that window would have shipped broken packages that npm cannot unpublish. **P5 cleared it by landing the real thing** — the six stubs became publishable shims and `PACKAGE_ROSTER` gained the three remaining new names, at which point all 9 offending edges resolved and the gate went green on its own. No gate logic was changed.
|
|
@@ -154,10 +162,45 @@ Any red → route via [`gates-catalog.md`](gates-catalog.md); fix at the source,
|
|
|
154
162
|
|
|
155
163
|
## §Step 4 — (Variant B, or ANY variant with uncommitted `[Unreleased]` content) Promote, bump, lockfile
|
|
156
164
|
|
|
165
|
+
**4a-pre. Assemble `changes/<pr>.md` fragments (REQ-W11-06, gh#2931), BEFORE promotion.** This
|
|
166
|
+
repo's PRs land a `changes/<pr>.md` fragment instead of hand-editing a CHANGELOG directly —
|
|
167
|
+
`check-changelog-pr-gate.mjs`'s own PR-time gate now REQUIRES a fragment for a roster-package
|
|
168
|
+
change and refuses the direct edit outright (gh#3123; the root `CHANGELOG.md` was already
|
|
169
|
+
fragment-only in practice before that ticket). Those fragments accumulate
|
|
170
|
+
unreleased until something folds them into the right CHANGELOG's `[Unreleased]` section — that's
|
|
171
|
+
this step, and it must run before 4a promotes `[Unreleased]` to a versioned heading, or a
|
|
172
|
+
fragment folded in afterward would land under the WRONG (already-promoted) heading.
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
node scripts/release/assemble-changelog-fragments.mjs # writes, deletes consumed fragments
|
|
176
|
+
node scripts/release/assemble-changelog-fragments.mjs --verify # must print PASS afterward
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Routing rule (`scripts/release/assemble-changelog-fragments.mjs`'s own header, full detail
|
|
180
|
+
there): a fragment's first line is `- <kind>: <sentence>` (kind in fix|feature|chore|docs,
|
|
181
|
+
unchanged from `changelog_fragments.py`'s schema) or, this repo's own addition, `- <kind>
|
|
182
|
+
(<package>): <sentence>` naming a `PACKAGE_ROSTER` (`package-paths.mjs`) entry. The
|
|
183
|
+
parenthetical-package form routes to that package's own `packages/<dir>/CHANGELOG.md` — the
|
|
184
|
+
norm for package-scoped fragments as of gh#3123, not a hypothetical; the plain form routes to
|
|
185
|
+
the repo-root `CHANGELOG.md`, whose own header scopes
|
|
186
|
+
it to exactly that shape of change ("tooling, CI, build scripts, cross-package work, docs").
|
|
187
|
+
`kind` maps to a Keep-a-Changelog subsection: `feature`→Added, `fix`→Fixed, `chore`→Changed,
|
|
188
|
+
`docs`→Docs — created under `## [Unreleased]` in that canonical order if the subsection doesn't
|
|
189
|
+
already exist, otherwise appended to the existing one.
|
|
190
|
+
|
|
191
|
+
**Deliberately NOT a pre-flight roster gate (§3.1).** Pending fragments are a NORMAL state
|
|
192
|
+
between PRs, not a defect — a `--verify`-shaped freshness gate added to the pre-cut roster (which
|
|
193
|
+
runs before this step, in Step 3) would fail on every cut that has any recent chore/fix/feature
|
|
194
|
+
PR queued, which is the common case. The `--verify` invocation above is a post-assembly
|
|
195
|
+
self-check (proves the assemble actually consumed everything it found), not a standing gate;
|
|
196
|
+
`gate-roster.mjs`'s count is unchanged by this ticket.
|
|
197
|
+
|
|
157
198
|
**Run 4a whenever a hand-authored `## [Unreleased]` section is still sitting uncommitted, not only on a strict Variant B.** `release-pack.mjs --mode cut` (a peer's pre-staged content, not yet promoted) needs it exactly as much as `--mode from-scratch` does — the v0.8.4 near-miss was `--mode cut` skipping this step entirely because the doc (and the script) only associated promotion with "from scratch". Both modes now run it and both hard-fail before the bump if any roster package still carries non-empty `[Unreleased]` content afterward.
|
|
158
199
|
|
|
159
200
|
**4a. Promote** `## [Unreleased]` → `## [vX.Y.Z] — YYYY-MM-DD` per package (`` `<plugin-root>/skills/package-release/scripts/promote-unreleased.mjs` ``); author fresh blocks for changed-but-unlogged packages; stub the pure ride-alongs (`` `<plugin-root>/skills/package-release/scripts/insert-stub.mjs` ``). Classification recipe + shapes: [`changelog-discipline.md`](changelog-discipline.md).
|
|
160
201
|
|
|
202
|
+
`release-pack.mjs` (both `--mode cut` and `--mode from-scratch`) now rejects any `--substantive-packages`/`--stub-packages` name whose entry in `scripts/package-paths.mjs`'s `PACKAGE_ROSTER` is unknown or `lockstep: false`, at parse time, before Step 1 runs (gh#2894) — the 0.8.58 cut passed `adia-plugins` (lockstep:false) in `--substantive-packages` and let `promote-unreleased.mjs` rewrite its `[Unreleased]` header to a version that package never ships, caught only at Step 5.6 after the full pre-flight had already run.
|
|
203
|
+
|
|
161
204
|
**4b. Bump.** PATCH vs MINOR: **MINOR is reserved for API-surface breaks only** (removed/renamed prop, attribute, slot, event, token, or tag). Visible behavior changes, re-scalings, and opt-in features stay PATCH; a CHANGELOG bullet saying "(MINOR behavior change)" is prose, not a semver directive. Unqualified "bump version" = PATCH; don't round-trip to ask. `node "<plugin-root>/skills/package-release/scripts/bump.mjs" --from X.Y.Z-1 --to X.Y.Z`. On a MINOR cut, also bump the internal `@adia-ai/*` `^ranges` separately (bump.mjs touches `"version"` fields only) — and a MINOR cut owes a MIGRATION GUIDE section ([`migration-guide-authoring.md`](migration-guide-authoring.md)).
|
|
162
205
|
|
|
163
206
|
**4c. Lockfile.** `npm install --package-lock-only --no-audit --no-fund` — must land in the release commit. The publish workflows open with `npm ci`, which hard-fails on a version/lockfile mismatch: a bump without the regenerated lockfile passes locally and breaks **every** publish at clean-install.
|
|
@@ -226,6 +269,7 @@ stub sections exist leaves it nothing to append to, and the gap resurfaces
|
|
|
226
269
|
as F-N1 warns at the push boundary, costing a tag move:
|
|
227
270
|
|
|
228
271
|
```bash
|
|
272
|
+
node scripts/release/assemble-changelog-fragments.mjs # 4a-pre (idempotent — safe to re-run; no-op if already assembled)
|
|
229
273
|
node "<plugin-root>/skills/package-release/scripts/insert-stub.mjs" \
|
|
230
274
|
--version X.Y.Z --date YYYY-MM-DD --previous-version X.Y.Z-1 \
|
|
231
275
|
--substantive "<one-line>" --xref "<anchor>" --packages <missing-stubs> # 4a-stub — FIRST, only the missing ones (hard-errors on existing sections)
|
|
@@ -437,6 +481,28 @@ Deploy discipline (the release tenant of the demo-site host; VM/service ops belo
|
|
|
437
481
|
|
|
438
482
|
- Any docs **route** cited to the operator or in notes must exist in `site/sitemap.json` (`grep '"path":'`) — a plausible-looking route that isn't in the sitemap renders blank.
|
|
439
483
|
|
|
484
|
+
**Milestone close (ADR-0103, gh#2729, dated addendum 2026-09-01).** Every
|
|
485
|
+
lockstep cut has an open GitHub Milestone named `vX.Y.Z` (one per cut,
|
|
486
|
+
created ahead of time or by the first PR scheduled into it). Close it here,
|
|
487
|
+
after the GH releases above and before release notes:
|
|
488
|
+
|
|
489
|
+
```bash
|
|
490
|
+
number=$(gh api repos/adiahealth/gen-ui-kit/milestones --jq \
|
|
491
|
+
'.[] | select(.title == "vX.Y.Z") | .number')
|
|
492
|
+
gh api -X PATCH "repos/adiahealth/gen-ui-kit/milestones/$number" -f state=closed
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
Any issue still open in that milestone at close time either ships anyway
|
|
496
|
+
(re-tag it into the milestone that actually shipped it — never leave an
|
|
497
|
+
already-shipped issue's milestone wrong) or slips to the next milestone
|
|
498
|
+
(re-tag now, don't leave the closed milestone showing open issues). Create
|
|
499
|
+
the NEXT cut's milestone here too, so scheduling work for it doesn't wait on
|
|
500
|
+
this cut's tag:
|
|
501
|
+
|
|
502
|
+
```bash
|
|
503
|
+
gh api repos/adiahealth/gen-ui-kit/milestones -f title="vNEXT.Y.Z" -f state=open
|
|
504
|
+
```
|
|
505
|
+
|
|
440
506
|
Any Step-2 stashes: `git stash pop`; flag conflicts to the operator.
|
|
441
507
|
|
|
442
508
|
## §Step 11 — Author release notes (default)
|
|
@@ -88,6 +88,23 @@ const PINNED_REFS = {
|
|
|
88
88
|
new RegExp(`("@adia-ai/[a-z0-9-]+":\\s*")${from.replace(/\./g, '\\.')}(?![\\d.])`, 'g'),
|
|
89
89
|
replace: (to) => `$1${to}`,
|
|
90
90
|
}],
|
|
91
|
+
// icons-cdn.js's hand-typed PACKAGE_VERSION literal (gh#3228's jsDelivr
|
|
92
|
+
// manifest-fallback URL pin) must move with web-components' OWN version
|
|
93
|
+
// every cut — unlike the file's other literal (PINNED_VERSION, which
|
|
94
|
+
// tracks @phosphor-icons/core's independent release cadence and is
|
|
95
|
+
// updated by hand only when Phosphor cuts), this one pins the very
|
|
96
|
+
// package it lives in. Left unmoved by bump.mjs through the 0.8.58 cut,
|
|
97
|
+
// it would leave MANIFEST_CDN_FALLBACK_URL naming a stale version with
|
|
98
|
+
// check:lockstep staying green — no coherence source watched it until
|
|
99
|
+
// lockstep-checks.mjs's invariant 9 (gh#3240) and this pin closed the
|
|
100
|
+
// loop together.
|
|
101
|
+
'packages/web-components': [{
|
|
102
|
+
file: 'core/icons-cdn.js',
|
|
103
|
+
label: 'icons-cdn.js PACKAGE_VERSION literal (jsDelivr manifest fallback pin)',
|
|
104
|
+
pattern: (from) =>
|
|
105
|
+
new RegExp(`(const PACKAGE_VERSION = ')${from.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(?![\\d.])(')`),
|
|
106
|
+
replace: (to) => `$1${to}$2`,
|
|
107
|
+
}],
|
|
91
108
|
};
|
|
92
109
|
|
|
93
110
|
// Repo-level version references (path relative to REPO ROOT, not a package) —
|
|
@@ -274,10 +291,14 @@ function main() {
|
|
|
274
291
|
// script never calls fs.writeFileSync by pointing at a path whose directory
|
|
275
292
|
// doesn't exist; a latent write bug would throw ENOENT instead of passing.
|
|
276
293
|
function selftest() {
|
|
294
|
+
// A fixture pkg name deliberately NOT in PINNED_REFS/SIBLING_MANIFESTS —
|
|
295
|
+
// this proof exercises bumpAll's core version-field transform in
|
|
296
|
+
// isolation, so it must not collide with (and pull in the file reads for)
|
|
297
|
+
// any real package's pin config.
|
|
277
298
|
const fake = [{
|
|
278
|
-
pkg: 'packages/
|
|
299
|
+
pkg: 'packages/fixture-pkg',
|
|
279
300
|
path: '/nonexistent-fixture-dir/package.json',
|
|
280
|
-
txt: '{\n "name": "@adia-ai/
|
|
301
|
+
txt: '{\n "name": "@adia-ai/fixture-pkg",\n "version": "0.8.4"\n}\n',
|
|
281
302
|
version: '0.8.4',
|
|
282
303
|
}];
|
|
283
304
|
if (!validateAllAtFrom(fake, '0.8.4')) {
|
|
@@ -341,6 +362,24 @@ function selftest() {
|
|
|
341
362
|
console.error('selftest FAIL: peer-pin pattern prefix-matched a longer version'); process.exit(1);
|
|
342
363
|
}
|
|
343
364
|
|
|
365
|
+
// icons-cdn.js PACKAGE_VERSION literal (gh#3240, invariant 9) — must move
|
|
366
|
+
// with web-components' own version, and must not touch the file's OTHER
|
|
367
|
+
// literal-looking pin (PINNED_VERSION, @phosphor-icons/core's version,
|
|
368
|
+
// updated by hand on its own independent cadence).
|
|
369
|
+
const [iconsCdnCfg] = PINNED_REFS['packages/web-components'];
|
|
370
|
+
const iconsCdnBefore =
|
|
371
|
+
"const PINNED_VERSION = '2.1.1';\n\nconst PACKAGE_VERSION = '0.8.58';\n";
|
|
372
|
+
const iconsCdnAfter = bumpPinnedRef(iconsCdnBefore, iconsCdnCfg, '0.8.58', '0.8.59');
|
|
373
|
+
if (!iconsCdnAfter.includes("PACKAGE_VERSION = '0.8.59'") || iconsCdnAfter.includes("PACKAGE_VERSION = '0.8.58'")) {
|
|
374
|
+
console.error('selftest FAIL: PINNED_REFS did not bump the icons-cdn.js PACKAGE_VERSION literal'); process.exit(1);
|
|
375
|
+
}
|
|
376
|
+
if (!iconsCdnAfter.includes("PINNED_VERSION = '2.1.1'")) {
|
|
377
|
+
console.error('selftest FAIL: icons-cdn.js pin bump touched the unrelated PINNED_VERSION (phosphor) literal'); process.exit(1);
|
|
378
|
+
}
|
|
379
|
+
if (bumpPinnedRef("const PACKAGE_VERSION = '0.8.580';", iconsCdnCfg, '0.8.58', '0.8.59') !== "const PACKAGE_VERSION = '0.8.580';") {
|
|
380
|
+
console.error('selftest FAIL: icons-cdn.js pin pattern prefix-matched a longer version'); process.exit(1);
|
|
381
|
+
}
|
|
382
|
+
|
|
344
383
|
// validatePinsAtFrom — the mutation-free pre-flight (reviewer finding: the
|
|
345
384
|
// mid-loop pin check fired only after two files were already written).
|
|
346
385
|
const goodPin = [{ pkg: 'packages/plugins/adia-ui-factory', cfg: pinCfg, path: '/nonexistent/.mcp.json', txt: pinBefore }];
|
|
@@ -155,6 +155,41 @@ export const GATE_ROSTER = [
|
|
|
155
155
|
// manifest trees. Appended, not inserted — same numbering discipline as
|
|
156
156
|
// gate 30/31/32.
|
|
157
157
|
{ n: 33, cmd: 'npm run verify:patterns-index', what: 'pattern-index.md (mcp + adia-ui-factory) vs corpus source' },
|
|
158
|
+
// gh#2829: gh#2808/PR #2815 (ADR-0108 ticket 3) promoted both yaml gates
|
|
159
|
+
// below into `npm run check` but deliberately left this pre-cut roster
|
|
160
|
+
// untouched — a cut could still ship a yaml `events:` block that phantoms
|
|
161
|
+
// or misses a runtime dispatch, or a schema field with no implementation
|
|
162
|
+
// coverage, without either failing the pre-flight. Appended, not
|
|
163
|
+
// inserted — same numbering discipline as gate 30/31/32/33.
|
|
164
|
+
{ n: 34, cmd: 'node scripts/release/check-yaml-events-vs-runtime.mjs --strict --strict-details', what: 'yaml events: blocks vs runtime dispatch (no phantom/missing events)' },
|
|
165
|
+
{ n: 35, cmd: 'node scripts/release/check-yaml-impl-coverage.mjs --strict', what: 'yaml schema fields vs implementation coverage' },
|
|
166
|
+
// gh#2912, plan-top-priority-verification.md item 4 (G1): the full
|
|
167
|
+
// 10-component x 2-bundler single-import build matrix — byte budgets +
|
|
168
|
+
// 0-foreign-marker-leak + paired-CSS-purity + whole-lib-delta + docs
|
|
169
|
+
// grep-gate. Too slow/heavy to gate every `npm run check` run (it spins
|
|
170
|
+
// up real esbuild AND rollup builds per cell); a 3-cell fast canary is
|
|
171
|
+
// wired into `npm run check` instead (check:treeshake:canary) as a
|
|
172
|
+
// regression tripwire, with the full matrix reserved for cut time. The
|
|
173
|
+
// matrix surfaced 14 real, pre-existing cross-component marker leaks
|
|
174
|
+
// (tracked as gh#2922, not fixed by this ticket) that are held under a
|
|
175
|
+
// known-red allowlist in check-treeshake.mjs itself — a cell diverging
|
|
176
|
+
// from its allowlisted finding, or any non-allowlisted cell failing,
|
|
177
|
+
// still reds this gate; the script also reports an allowlisted cell that
|
|
178
|
+
// comes back clean as promotable rather than staying silent about it.
|
|
179
|
+
// With the allowlist, this gate is currently all-green. Appended, not
|
|
180
|
+
// inserted — same numbering discipline as gate 30/31/32/33/34/35.
|
|
181
|
+
{ n: 36, cmd: 'npm run check:treeshake', what: 'single-import build matrix (esbuild+rollup) — byte budgets + marker-leak + CSS purity + whole-lib delta + docs grep-gate' },
|
|
182
|
+
// gh#2911 (plan-top-priority-verification.md item 3 G1): the lint rule
|
|
183
|
+
// bank's seeded-violation catch-rate + false-positive golden-set sweep +
|
|
184
|
+
// 5-rule mutation hardening. NOT in `npm run check` — the golden-set FP
|
|
185
|
+
// sweep alone measured ~100s (every rule in the bank re-parses every one
|
|
186
|
+
// of ~440 `*.examples.html`/`*.contents.html` files; the generated
|
|
187
|
+
// composition rules each call `tagTree()` independently rather than
|
|
188
|
+
// sharing one parse per file — a real perf gap, filed as gh#2937,
|
|
189
|
+
// not fixed here), over AGENTS.md's <60s bar for the PR-blocking
|
|
190
|
+
// aggregate. Appended, not inserted — same numbering discipline as gate
|
|
191
|
+
// 30/31/32/33/34/35/36.
|
|
192
|
+
{ n: 37, cmd: 'npm run check:lint-efficacy', what: 'lint rule bank: seeded catch rate 100% + golden-set 0 error FPs + mutation hardening' },
|
|
158
193
|
];
|
|
159
194
|
|
|
160
195
|
// -- CLI ------------------------------------------------------------------
|