@adia-ai/adia-ui-forge 0.8.55 → 0.8.57
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 +3 -2
- package/.codex-plugin/plugin.json +1 -1
- package/CHANGELOG.md +40 -0
- package/README.md +1 -1
- package/__init__.py +5 -0
- package/commands/demo-audit.md +1 -1
- package/commands/gen-ui-review.md +1 -1
- package/commands/package-release.md +1 -1
- package/commands/site-deployment.md +1 -1
- package/package.json +1 -1
- package/plugin.yaml +1 -1
- package/prompts/demo-audit.md +1 -1
- package/prompts/gen-ui-review.md +1 -1
- package/prompts/package-release.md +1 -1
- package/prompts/site-deployment.md +1 -1
- package/scripts/forge-lint.mjs +168 -0
- package/scripts/lint-rules.generated.mjs +1700 -0
- package/scripts/site-postwrite-derivation-gate +23 -127
- package/skills/a2ui-maintenance/SKILL.md +1 -1
- package/skills/a2ui-maintenance/references/data-model-reactivity.md +49 -29
- package/skills/a2ui-maintenance/references/pipeline-overview.md +58 -22
- package/skills/a2ui-maintenance/references/surface-lifecycle.md +14 -7
- package/skills/component-md-authoring/SKILL.md +116 -0
- package/skills/component-md-authoring/agents/openai.yaml +3 -0
- package/skills/demo-audit/references/visual-probe-triage.md +4 -1
- package/skills/gen-ui-review/SKILL.md +4 -1
- package/skills/gen-ui-review/references/loop-protocol.md +6 -5
- package/skills/package-release/references/changelog-discipline.md +6 -3
- package/skills/package-release/references/cut-procedure.md +61 -14
- package/skills/package-release/references/gates-catalog.md +6 -2
- package/skills/package-release/references/recovery-paths.md +6 -3
- package/skills/package-release/scripts/gate-roster.mjs +10 -7
- package/skills/package-release/scripts/release-pack.mjs +289 -17
- package/skills/primitive-authoring/references/anti-patterns.md +2 -2
- package/skills/primitive-authoring/references/api-contract.md +17 -4
- package/skills/primitive-authoring/references/authoring-cycle.md +1 -1
- package/skills/primitive-authoring/references/code-style.md +1 -1
- package/skills/primitive-authoring/references/common-gotchas.md +6 -6
- package/skills/primitive-authoring/references/form-control-sizing.md +22 -7
- package/skills/primitive-authoring/references/token-contract.md +5 -0
- package/skills/primitive-authoring/references/yaml-contract.md +132 -14
- package/skills/site-docs-authoring/SKILL.md +7 -9
- package/hooks/hooks.json +0 -44
- package/scripts/forge-lint +0 -315
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# Loop Protocol — one full review cycle
|
|
2
2
|
|
|
3
3
|
Five phases per prompt; human QA gate at cycle close; Phase 5 runs for FAILING
|
|
4
|
-
prompts only.
|
|
5
|
-
|
|
4
|
+
prompts only. `<plugin-root>` below is `$CLAUDE_PLUGIN_ROOT` in Claude Code; the plugin's
|
|
5
|
+
installed directory in Codex. Scripts ship in this skill at
|
|
6
|
+
`<plugin-root>/skills/gen-ui-review/scripts/` and are run from the
|
|
6
7
|
monorepo root (they read `apps/genui/…/gallery-latest.json` and write the
|
|
7
8
|
`review/` tree there). Corpus-pattern doctrine consumed by Phase 5:
|
|
8
9
|
[corpus-html-patterns.md](corpus-html-patterns.md).
|
|
@@ -79,7 +80,7 @@ primitive lookup (`TAG_TO_COMPONENT`, the authoritative table), attr
|
|
|
79
80
|
sanitization, overflow gate:
|
|
80
81
|
|
|
81
82
|
```text
|
|
82
|
-
node
|
|
83
|
+
node <plugin-root>/skills/gen-ui-review/scripts/gen-review-decompose.mjs
|
|
83
84
|
--cycle N [--group <slug>] [--prompt <slug>] [--port 5300] [--settle 2500] [--dry-run]
|
|
84
85
|
```
|
|
85
86
|
|
|
@@ -190,7 +191,7 @@ never get fix plans. Reads ONLY the decomposed file.
|
|
|
190
191
|
5. **Schema gate** (must exit 0 before touching the ledger):
|
|
191
192
|
|
|
192
193
|
```bash
|
|
193
|
-
node
|
|
194
|
+
node <plugin-root>/skills/gen-ui-review/scripts/validate-cycle-scores.mjs --cycle N --strict
|
|
194
195
|
```
|
|
195
196
|
|
|
196
197
|
6. **Update ledger** (`review/cycle-ledger.json`): `cycleNumber`,
|
|
@@ -203,7 +204,7 @@ never get fix plans. Reads ONLY the decomposed file.
|
|
|
203
204
|
7. **Exit condition**:
|
|
204
205
|
|
|
205
206
|
```bash
|
|
206
|
-
node
|
|
207
|
+
node <plugin-root>/skills/gen-ui-review/scripts/gen-review-status.mjs --check-exit
|
|
207
208
|
```
|
|
208
209
|
|
|
209
210
|
Exit 0 → `status: COMPLETE`; exit 1 → `status: OPEN` (the script lists the
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# `changelog-discipline.md` — Keep-a-Changelog mechanics + F-N1 enrichment
|
|
2
2
|
|
|
3
|
+
`<plugin-root>` below is `$CLAUDE_PLUGIN_ROOT` in Claude Code; the plugin's installed directory
|
|
4
|
+
in Codex.
|
|
5
|
+
|
|
3
6
|
> Load whenever a cut touches CHANGELOGs (always for author-from-scratch; for a
|
|
4
7
|
> handoff only if F-N1 warns). The monorepo uses Keep-a-Changelog per package;
|
|
5
8
|
> the cut **promotes** `## [Unreleased]` into `## [vX.Y.Z] — YYYY-MM-DD`.
|
|
@@ -18,7 +21,7 @@
|
|
|
18
21
|
The heading swap is all that happens; content under it stays:
|
|
19
22
|
|
|
20
23
|
```bash
|
|
21
|
-
node "
|
|
24
|
+
node "<plugin-root>/skills/package-release/scripts/promote-unreleased.mjs" \
|
|
22
25
|
--version 0.X.Y --date YYYY-MM-DD --packages web-components,web-modules,a2ui/corpus
|
|
23
26
|
```
|
|
24
27
|
|
|
@@ -70,7 +73,7 @@ Why this recurs: cross-package sweeps leave 1–3 incidental touches (a docstrin
|
|
|
70
73
|
## §Stubs — ride-along lockstep
|
|
71
74
|
|
|
72
75
|
```bash
|
|
73
|
-
node "
|
|
76
|
+
node "<plugin-root>/skills/package-release/scripts/insert-stub.mjs" \
|
|
74
77
|
--version 0.X.Y --date YYYY-MM-DD \
|
|
75
78
|
--substantive "<one-line> in @adia-ai/<pkg>" \
|
|
76
79
|
--xref "packages/web-modules/CHANGELOG.md#0XY--YYYY-MM-DD" \
|
|
@@ -111,7 +114,7 @@ This is cut-procedure §Step 4f: the SAME matcher F-N1 uses at tag time (every r
|
|
|
111
114
|
**Recovery — a warn AFTER tagging** (Step 4f skipped, or an interleaved merge added uncovered changes): the release commit is already merged via PR, so `--amend` is not possible —
|
|
112
115
|
|
|
113
116
|
1. Run `--pending-version X.Y.Z --fix`; `git add` the CHANGELOGs; `git commit -m "fix(release): F-N1 enrichment — vX.Y.Z"`; push the branch → PR → CI → merge.
|
|
114
|
-
2. The SHA moved: `node "
|
|
117
|
+
2. The SHA moved: `node "<plugin-root>/skills/package-release/scripts/tag-lockstep.mjs" --version X.Y.Z --delete`, then re-tag at `main`'s new post-merge HEAD.
|
|
115
118
|
3. Re-run F-N1; expect per-package clean (umbrella error stays, ignored). ONE recovery round — if a second warn appears, the cause is upstream (find what keeps merging into the window), not another enrichment.
|
|
116
119
|
|
|
117
120
|
## §Dating and anchors
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# `cut-procedure.md` — the standard lockstep cut
|
|
2
2
|
|
|
3
|
+
`<plugin-root>` below is `$CLAUDE_PLUGIN_ROOT` in Claude Code; the plugin's installed directory
|
|
4
|
+
in Codex.
|
|
5
|
+
|
|
3
6
|
> Load for any class-A lockstep cut (cut & ship · author from scratch · deploy
|
|
4
7
|
> handoff). Companions: [`gates-catalog.md`](gates-catalog.md) (gate roster +
|
|
5
8
|
> failure routing), [`changelog-discipline.md`](changelog-discipline.md) (promotion
|
|
@@ -13,7 +16,7 @@ Two entry variants, converging at Step 5:
|
|
|
13
16
|
- **Variant A — deploy handoff:** a peer pre-cut the release commit + CHANGELOG + bump + lockfile. Re-baseline, verify, run **Step 4e** (release docs + team notes — the peer's cut may not have generated them, and the pretag gate blocks Step 6 without them), then resume at Step 6 (tag).
|
|
14
17
|
- **Variant B — author from scratch:** source landed under `## [Unreleased]` with no bump. Do Step 4 (promotion + bump + lockfile), then the full tail.
|
|
15
18
|
|
|
16
|
-
``
|
|
19
|
+
`` `<plugin-root>/skills/package-release/scripts/release-pack.mjs` `` (bundled) mechanizes the sequence in two phases per invariant 3 — the cut modes stop at the release commit (PR → CI → merge happens between), `--mode handoff` runs tag→publish→deploy from post-merge main. **Run with `--go` for an operator-initiated release** (single authorization, §below); the steps below are the manual/diagnostic form and run straight through on the same one-go model.
|
|
17
20
|
|
|
18
21
|
| Step | Action | Mutates? |
|
|
19
22
|
| --- | --- | --- |
|
|
@@ -31,6 +34,7 @@ Two entry variants, converging at Step 5:
|
|
|
31
34
|
| 9 | Dispatch publish workflows; wait; verify registry | Publish |
|
|
32
35
|
| 10 | GH releases + site deploy dispatch | Deploy |
|
|
33
36
|
| 11 | Author release notes (default, not optional) | No |
|
|
37
|
+
| 12 | Restore the pnpm dev layout (`npm ci` left it npm-shaped) | node_modules only |
|
|
34
38
|
|
|
35
39
|
---
|
|
36
40
|
|
|
@@ -44,8 +48,18 @@ git -C "$REPO" status --short
|
|
|
44
48
|
git -C "$REPO" log --oneline -8
|
|
45
49
|
git -C "$REPO" fetch && git -C "$REPO" log HEAD..origin/main --oneline # must be empty
|
|
46
50
|
git -C "$REPO" tag --list 'vX.Y.Z' '*-vX.Y.Z' # must NOT exist yet
|
|
51
|
+
[ -d "$REPO/node_modules/.pnpm" ] && echo "STOP: pnpm-shaped node_modules — run npm ci first" # gate 9 precondition, see §3.1 layout note
|
|
47
52
|
```
|
|
48
53
|
|
|
54
|
+
**Check the `node_modules` layout here, not at gate 9.** The §3.1 layout note (gh#1359)
|
|
55
|
+
already says gate 9 (`check:js-bundles-fresh`) needs the npm-ci layout, but it sits AFTER
|
|
56
|
+
the gate roster and is easy to read past — the v0.8.55 cut (2026-08-28) ran the full
|
|
57
|
+
33-gate pre-flight under a pnpm-shaped tree, lost ~12 minutes to gates 1-8 and 10-33
|
|
58
|
+
passing, then failed gate 9 with phantom bundle drift (1.24 MB on disk vs 1.52 MB fresh
|
|
59
|
+
on every JS entry — the Phosphor icon glob resolving differently, not a real source
|
|
60
|
+
change). The one-line check above fails in under a second instead. `npm ci` to recover;
|
|
61
|
+
`npm install` alone does NOT reshape an existing pnpm tree.
|
|
62
|
+
|
|
49
63
|
`branch --show-current` ≠ `main` → stop; cutting on a feature branch pushes a stale `main` ref while the tags point at the feature tip. Recovery: [`recovery-paths.md`](recovery-paths.md) §Scenario 8. If multiple unpushed `release(*):` commits exist → this is a batch push, [`recovery-paths.md`](recovery-paths.md) §Scenario 2.
|
|
50
64
|
|
|
51
65
|
## §Step 2 — Classify uncommitted files; stash strays
|
|
@@ -67,7 +81,6 @@ If `git diff <prev-tag>..HEAD --name-only` touches component yaml / `.a2ui.json`
|
|
|
67
81
|
```bash
|
|
68
82
|
node scripts/build/components.mjs # catalog + per-component sidecars
|
|
69
83
|
node scripts/build/generate-examples-md.mjs # .examples.md from .examples.html
|
|
70
|
-
node scripts/build/site-a2ui.mjs --stale # /site/components/* converted rows
|
|
71
84
|
npm run harvest:chunks # chunk corpus from site/apps/playgrounds/catalog
|
|
72
85
|
npm run check:embeddings-fresh # ← run this FIRST; if it passes, SKIP the rebuild below
|
|
73
86
|
npm run build:embeddings:chunks # ONLY if the line above failed (needs OPENAI_API_KEY)
|
|
@@ -78,8 +91,8 @@ npm run build:bundles # dist CSS+JS bundles
|
|
|
78
91
|
|
|
79
92
|
**The `data-chunk-*` qualifier was the trap** (gh#421). Two separate cuts lost a CI round-trip to it:
|
|
80
93
|
|
|
81
|
-
- **v0.8.14** edited two components' `*.examples.html` — not yaml, not `.contents.html`, no annotation — so it read as out of scope. It isn't: `.examples.html` feeds **
|
|
82
|
-
- **The 0.8.16 cycle** then added a brand-new `site/pages/guides/theming.html` with *no* annotations, ran `
|
|
94
|
+
- **v0.8.14** edited two components' `*.examples.html` — not yaml, not `.contents.html`, no annotation — so it read as out of scope. It isn't: `.examples.html` feeds **two** generators (`.examples.md` and the chunk harvest's source hashes; a third, the retired site-a2ui converted rows, applied historically). Every freshness gate this doc named came back clean, and CI still failed on `🔴 stale /site/components/{menu,popover}` plus `2 source file(s) changed since harvest`.
|
|
95
|
+
- **The 0.8.16 cycle** then added a brand-new `site/pages/guides/theming.html` with *no* annotations, ran `check:links`, `verify:llms`, and `verify:patterns-index` — all clean — and CI failed anyway: `1 source file(s) NEW since harvest`.
|
|
83
96
|
|
|
84
97
|
Root cause of both: `check-chunks-fresh` hashes **every** source file under the harvest globs and compares the set against the corpus record, so a new or changed file trips it whether or not the harvester extracts a chunk from it. The annotation governs what gets *harvested*, never what gets *hashed*. Hence the trigger list above names the directories, not the annotation.
|
|
85
98
|
|
|
@@ -110,7 +123,7 @@ npm run check:links # 15 intra-repo links
|
|
|
110
123
|
npm run eval:diff -- --engine zettel # 16 eval floors
|
|
111
124
|
npm run dogfood:status # 17 P0/P1 dogfood floor (static-only under npm-ci; run once more under bootstrap layout for full coverage, gh#1359)
|
|
112
125
|
npm run check:examples-md-fresh # 18 .examples.md vs .examples.html
|
|
113
|
-
|
|
126
|
+
# gate 19 (verify:site-a2ui) retired with the site-a2ui mechanism — ADR-0072 Decision 2 / gh#2410
|
|
114
127
|
npm run verify:contrast # 20 WCAG AA — canvas-text AND text-on-fill
|
|
115
128
|
npm run check:token-semantics-sync # 21 token-selection generated refs vs token sources
|
|
116
129
|
npm run check:demo-routes # 22 demo surfaces routed + patterns indexed
|
|
@@ -143,9 +156,9 @@ Any red → route via [`gates-catalog.md`](gates-catalog.md); fix at the source,
|
|
|
143
156
|
|
|
144
157
|
**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.
|
|
145
158
|
|
|
146
|
-
**4a. Promote** `## [Unreleased]` → `## [vX.Y.Z] — YYYY-MM-DD` per package (``
|
|
159
|
+
**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).
|
|
147
160
|
|
|
148
|
-
**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 "
|
|
161
|
+
**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)).
|
|
149
162
|
|
|
150
163
|
**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.
|
|
151
164
|
|
|
@@ -213,10 +226,10 @@ stub sections exist leaves it nothing to append to, and the gap resurfaces
|
|
|
213
226
|
as F-N1 warns at the push boundary, costing a tag move:
|
|
214
227
|
|
|
215
228
|
```bash
|
|
216
|
-
node "
|
|
229
|
+
node "<plugin-root>/skills/package-release/scripts/insert-stub.mjs" \
|
|
217
230
|
--version X.Y.Z --date YYYY-MM-DD --previous-version X.Y.Z-1 \
|
|
218
231
|
--substantive "<one-line>" --xref "<anchor>" --packages <missing-stubs> # 4a-stub — FIRST, only the missing ones (hard-errors on existing sections)
|
|
219
|
-
node "
|
|
232
|
+
node "<plugin-root>/skills/package-release/scripts/bump.mjs" --from X.Y.Z-1 --to X.Y.Z # 4b (skip if versions already moved)
|
|
220
233
|
npm install --package-lock-only --no-audit --no-fund # 4c
|
|
221
234
|
npm run check:lockstep # 4d
|
|
222
235
|
node scripts/build/derive-genui-catalog.mjs # 4d.5 — catalogId carries the bumped version (gh#617)
|
|
@@ -244,7 +257,9 @@ git -C "$REPO" checkout -b "release/vX.Y.Z"
|
|
|
244
257
|
git -C "$REPO" reset HEAD >/dev/null 2>&1
|
|
245
258
|
git -C "$REPO" add package-lock.json packages/*/package.json packages/*/CHANGELOG.md \
|
|
246
259
|
packages/gen-ui/a2ui/*/package.json packages/gen-ui/a2ui/*/CHANGELOG.md \
|
|
247
|
-
packages/genui/adia-catalog/
|
|
260
|
+
packages/genui/adia-catalog/adia.core.json packages/genui/adia-catalog/adia.navigation.json \
|
|
261
|
+
packages/genui/adia-catalog/adia.data.json packages/genui/adia-catalog/adia.agent.json \
|
|
262
|
+
packages/genui/adia-catalog/adia.shells.json \
|
|
248
263
|
docs/ops/releases/vX.Y.Z.md # + in-scope source + Step-3.0 regen outputs
|
|
249
264
|
git -C "$REPO" diff --cached --stat | tail -3 # count must match the allowlist
|
|
250
265
|
```
|
|
@@ -261,6 +276,19 @@ node scripts/build/components.mjs --verify && npm run check:chunks-fresh && npm
|
|
|
261
276
|
|
|
262
277
|
Drift here means a regen output was left out of the allowlist — stage it and re-run. <2s now vs ~5min of tag-move recovery after CI catches it. Do not proceed to tag with drift.
|
|
263
278
|
|
|
279
|
+
## §Step 5.6 — Unstaged-tracked-files guard (`release-pack.mjs`, gh#2473)
|
|
280
|
+
|
|
281
|
+
`release-pack.mjs`'s Step 5 mechanizes this: right after its own `git add`
|
|
282
|
+
(the allowlist above, as automated), it runs `git status --porcelain` and
|
|
283
|
+
fails the cut if any tracked file is still modified-in-the-worktree —
|
|
284
|
+
proof the allowlist covered everything bump.mjs / cut-hygiene touched this
|
|
285
|
+
cut, not just what §Step 5.5's three named freshness gates happen to check.
|
|
286
|
+
This is the fourth time the allowlist itself went stale (gh#1198, gh#1899,
|
|
287
|
+
gh#1954, gh#2473 — most recently the factory README's generation-MCP pin
|
|
288
|
+
prose), so the guard is generic rather than another named file. A manual
|
|
289
|
+
cut should run the equivalent check by hand: `git status --porcelain`
|
|
290
|
+
after staging must be empty of `M`/`D` lines.
|
|
291
|
+
|
|
264
292
|
## §Step 5.7 — Release PR: push the branch, merge, re-baseline
|
|
265
293
|
|
|
266
294
|
The release commit reaches `main` through the standard PR flow. Mechanized
|
|
@@ -270,7 +298,7 @@ unresolved AND no review requests changes; any other state stops with the
|
|
|
270
298
|
evidence, never force-merges):
|
|
271
299
|
|
|
272
300
|
```bash
|
|
273
|
-
node "
|
|
301
|
+
node "<plugin-root>/skills/package-release/scripts/pr-bridge.mjs" \
|
|
274
302
|
--branch "release/vX.Y.Z" --title "release: vX.Y.Z lockstep" --body-file <path>
|
|
275
303
|
```
|
|
276
304
|
|
|
@@ -318,7 +346,7 @@ Stage its CHANGELOG edits into the release commit (the Step-5 allowlist already
|
|
|
318
346
|
Log the planned tag list (evidence table above), then tag **at `main`'s post-merge HEAD** (post-bump fixes belong in the tarball; the window's last merge is the tag point — exception: batch push tags each version at its own release-merge SHA):
|
|
319
347
|
|
|
320
348
|
```bash
|
|
321
|
-
node "
|
|
349
|
+
node "<plugin-root>/skills/package-release/scripts/tag-lockstep.mjs" \
|
|
322
350
|
--version X.Y.Z # umbrella vX.Y.Z + 10 <pkg>-vX.Y.Z (8 npm + 2 plugins)
|
|
323
351
|
```
|
|
324
352
|
|
|
@@ -344,7 +372,7 @@ a 14-package roster (`agent`, `persona` and `a2ui-protocol-mcp` missing), which
|
|
|
344
372
|
is three packages that would simply never publish.
|
|
345
373
|
|
|
346
374
|
```bash
|
|
347
|
-
PKGS=$(node -e "import('
|
|
375
|
+
PKGS=$(node -e "import('<plugin-root>/skills/package-release/scripts/package-paths.mjs')
|
|
348
376
|
.then(m => console.log(m.PACKAGE_ROSTER.filter(p => p.lockstep !== false).map(p => p.name).join(' ')))")
|
|
349
377
|
echo "$PKGS" # log it — this IS the tag list evidence
|
|
350
378
|
|
|
@@ -359,7 +387,7 @@ git -C "$REPO" push origin vX.Y.Z # umbrella last; triggers nothing
|
|
|
359
387
|
Log the current registry snapshot (per-package versions + `dist-tags.latest`) before dispatching. For batch pushes, verify ordering against that snapshot: **oldest version publishes and settles first** — `npm dist-tag latest` is set by publish order. Then:
|
|
360
388
|
|
|
361
389
|
```bash
|
|
362
|
-
node "
|
|
390
|
+
node "<plugin-root>/skills/package-release/scripts/dispatch-publish.mjs" \
|
|
363
391
|
--version X.Y.Z --verify-triggered # re-dispatches missing/dead runs; registry-gated (gh#763)
|
|
364
392
|
```
|
|
365
393
|
|
|
@@ -415,6 +443,25 @@ Any Step-2 stashes: `git stash pop`; flag conflicts to the operator.
|
|
|
415
443
|
|
|
416
444
|
Always author notes at end-of-cycle without being asked — context is freshest now. Single version → [`notes-authoring.md`](notes-authoring.md); ≥2 versions since the last broadcast → its §Rollup section. Surface the draft inline for copy-paste; the operator owns posting. Skip only on an explicit "no notes".
|
|
417
445
|
|
|
446
|
+
## §Step 12 — Restore the dev layout
|
|
447
|
+
|
|
448
|
+
The cut runs under `npm ci` (Step 1's layout check, gate 9), and that leaves
|
|
449
|
+
`node_modules` npm-shaped. The dev server refuses to start on that tree:
|
|
450
|
+
`npm run dev`'s `predev` hook (`scripts/dev/check-pnpm-layout.mjs`) hard-stops
|
|
451
|
+
because the Phosphor icon glob matches zero files under the hoisted layout and
|
|
452
|
+
every `<icon-ui>` would render empty (gh#340). Put the tree back before handing
|
|
453
|
+
the checkout to anyone, including yourself:
|
|
454
|
+
|
|
455
|
+
```bash
|
|
456
|
+
pnpm install # single checkout
|
|
457
|
+
node scripts/dev/bootstrap-worktree.mjs # inside a linked worktree
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
Both are idempotent and touch no committed file (`pnpm-lock.yaml` is
|
|
461
|
+
gitignored). Live cost of skipping this: the v0.8.55 cut (2026-08-28) left the
|
|
462
|
+
operator's primary checkout unable to run `npm run dev` until the layout was
|
|
463
|
+
restored by hand.
|
|
464
|
+
|
|
418
465
|
## §The 0.8.38 cut (the clean-world cut — delete this section after it lands)
|
|
419
466
|
|
|
420
467
|
The first cut AFTER the estate-split bridge. Pre-conditions, all verifiable
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# `gates-catalog.md` — pre-flight gate roster + failure → recovery map
|
|
2
2
|
|
|
3
|
+
`<plugin-root>` below is `$CLAUDE_PLUGIN_ROOT` in Claude Code; the plugin's installed directory
|
|
4
|
+
in Codex.
|
|
5
|
+
|
|
3
6
|
> Load for a verify-only run or on any gate failure during a cut. Maps every
|
|
4
7
|
> release-flow gate × what it checks × typical failure × recovery. Gates are
|
|
5
8
|
> grouped by **failure category** — how the operator routes when one goes red —
|
|
@@ -16,7 +19,7 @@ Row layout per gate: **What** · **Typical failure** · **Recovery**.
|
|
|
16
19
|
|
|
17
20
|
- **What:** all 10 lockstep `@adia-ai/*` packages declare the same `version` (the class-B `adia-plugins` package is excluded — `lockstep: false`, `scripts/package-paths.mjs`); internal `@adia-ai/*` dep ranges match policy (`^X.Y.0` during PATCH cycles, bumped at MINOR).
|
|
18
21
|
- **Typical failure:** one package forgot to bump; a peer edited an internal range mid-PATCH; a `^0.0.x` range slipped in.
|
|
19
|
-
- **Recovery:** version drift → ``
|
|
22
|
+
- **Recovery:** version drift → `` `<plugin-root>/skills/package-release/scripts/bump.mjs` ``; range drift → `npm run check:lockstep:fix` auto-aligns, then re-run.
|
|
20
23
|
- **Why `^0.0.x` is forbidden:** npm pre-1.0 semver only widens the caret when major+minor aren't both zero — `^0.0.6` resolves to `>=0.0.6 <0.0.7`, locked to exactly 0.0.6. An internal dep pinned that way silently installs a *stale* sibling on every fresh `npm i` (this shipped a real ~4-day-latent bug before the lockstep policy). The `^X.Y.0` floor (Y≥1) widens correctly across patches; trust the gate, don't reason about caret semantics by hand. Moot at 1.0.0.
|
|
21
24
|
|
|
22
25
|
### `node scripts/release/check-release.mjs --all-pending` (F-N1, the release trip-wire)
|
|
@@ -159,6 +162,7 @@ The two `audit:*` probes are soft-fail pre-cut (exit-1 only on criticals); findi
|
|
|
159
162
|
- **What:** the vitest suite (~1000+ tests).
|
|
160
163
|
- **Stale-test failure:** the test asserts a behavior a peer deliberately changed (CHANGELOG-documented) without updating the assertion. Tell it apart by reading assertion vs CHANGELOG vs source: if the code matches the CHANGELOG's described behavior, the test is stale — update the assertion (see [`recovery-paths.md`](recovery-paths.md) §Scenario 5). Real regression → fix the regression.
|
|
161
164
|
- **Parallel-contention flake:** heavy web-modules composite suites can fail under full parallelism on a loaded machine (`signals: drain loop exceeded 100 iterations`). Load-dependent, not a code defect. Sequential is the source of truth, and **the roster gate now runs it directly** (`npm run test:unit:serial` = `vitest run --no-file-parallelism`, gate 4 since 2026-07-19) — a parallel `test:unit` flake outside the roster still isn't a blocker, and don't raise the drain guard.
|
|
165
|
+
- **Same-host contention timeout (gh#2195):** gate 4 running solo (Phase 1, see the execution-model note above) isolates it from every OTHER pre-flight gate, but not from unrelated concurrent load on the same shared, multi-tenant host — another agent's build, a peer's own `npm run check`. gh#2195's diagnosis found this surfaces as a genuine 45s per-test timeout on a DIFFERENT single file each run, with no repeat culprit (the contention signature, not an order-dependent leak) — and found no separate "release pre-flight runner" with its own core count exists to recalibrate `worker-cap.mjs` against; it's the same operator/agent host either way. `release-pack.mjs`'s `runSoloGateWithRetry()` now retries gate 4 exactly once, scoped to only the file(s) it named as failed, when the failure output has a parseable `FAIL <file>` list — a file that fails once and passes clean on that immediate re-run was contention, not a regression; a file that fails twice is treated as a real one and the pre-flight still aborts. No other gate, and no OTHER invocation of `test:unit:serial` (CI, local dev, `npm run check`), gets this retry.
|
|
162
166
|
- **Exit 143 (SIGTERM):** the vitest process was KILLED (resource pressure / a stray terminator), not a test failure — re-run the gate directly (`npx vitest run --no-file-parallelism`) before diagnosing anything; a clean re-run means transient, proceed (v0.8.34 handoff hit this).
|
|
163
167
|
- **First-time-at-cut failures are REAL (v0.8.34):** this serial suite runs tests PR CI never does — `exit-gate.corpus` (dialect-catalog conformance over real harvested chunks) surfaces yaml-schema drift (e.g. an array prop missing `items.type`, the command/combobox `DynamicStringList` mis-map) only HERE, potentially weeks after the yaml edit merged green. Treat such a failure as a genuine latent defect to root-cause at the yaml SoT, never as release-blocking noise. (Structural fix — promoting the corpus batch into PR CI — tracked as a follow-up.)
|
|
164
168
|
|
|
@@ -211,7 +215,7 @@ npm run check:demo-shells
|
|
|
211
215
|
|
|
212
216
|
Add `verify:corpus` + `check:embeddings-fresh` if chunks were touched; `check:lightningcss-build` if CSS was touched; F-N1 if unpushed release tags exist.
|
|
213
217
|
|
|
214
|
-
**Full pre-cut sweep** — the 30-gate roster in [`cut-procedure.md`](cut-procedure.md) §Step 3, sourced from ``
|
|
218
|
+
**Full pre-cut sweep** — the 30-gate roster in [`cut-procedure.md`](cut-procedure.md) §Step 3, sourced from `` `<plugin-root>/skills/package-release/scripts/gate-roster.mjs` `` (the ONE list; `release-pack.mjs` imports and runs it in full — a subset run is impossible without editing that file). ~90s wall time.
|
|
215
219
|
|
|
216
220
|
**Omnibus** — `npm run check` invokes everything. Heavy; use when re-baselining a stale checkout.
|
|
217
221
|
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# `recovery-paths.md` — the 8 recovery scenarios
|
|
2
2
|
|
|
3
|
+
`<plugin-root>` below is `$CLAUDE_PLUGIN_ROOT` in Claude Code; the plugin's installed directory
|
|
4
|
+
in Codex.
|
|
5
|
+
|
|
3
6
|
> Load on any F-N1 / pre-flight failure, for a batch push, or for post-release
|
|
4
7
|
> recovery. Each scenario: the **shape** (what the repo state looks like), the
|
|
5
8
|
> **resolution** (commands + judgment calls), and what to record. Every scenario
|
|
@@ -48,7 +51,7 @@ Ambiguous → surface it, don't guess.
|
|
|
48
51
|
|
|
49
52
|
**Shape:** source + CHANGELOG entries landed under `## [Unreleased]`, no bump, no release commit.
|
|
50
53
|
|
|
51
|
-
**Resolution:** [`cut-procedure.md`](cut-procedure.md) Variant B; ``
|
|
54
|
+
**Resolution:** [`cut-procedure.md`](cut-procedure.md) Variant B; `` `<plugin-root>/skills/package-release/scripts/promote-unreleased.mjs` `` mechanizes the heading swap; fresh blocks per [`changelog-discipline.md`](changelog-discipline.md) §Authoring.
|
|
52
55
|
|
|
53
56
|
## §Scenario 4 — `[Unreleased]` extension (early cut + entangled fix)
|
|
54
57
|
|
|
@@ -80,11 +83,11 @@ Ambiguous → surface it, don't guess.
|
|
|
80
83
|
**Resolution:**
|
|
81
84
|
|
|
82
85
|
```bash
|
|
83
|
-
node "
|
|
86
|
+
node "<plugin-root>/skills/package-release/scripts/dispatch-publish.mjs" \
|
|
84
87
|
--version X.Y.Z --verify-triggered # re-dispatches packages with no run OR a dead (cancelled/failed/timed-out) run; registry-gated; idempotent
|
|
85
88
|
```
|
|
86
89
|
|
|
87
|
-
For a batch, preserve npm-latest ordering (`--after <prev>`). Verify against the registry, not the workflows. **Prevention:** push tags one-at-a-time ([`cut-procedure.md`](cut-procedure.md) §Step 8); ``
|
|
90
|
+
For a batch, preserve npm-latest ordering (`--after <prev>`). Verify against the registry, not the workflows. **Prevention:** push tags one-at-a-time ([`cut-procedure.md`](cut-procedure.md) §Step 8); `` `<plugin-root>/skills/package-release/scripts/release-pack.mjs` `` does this automatically and follows with `--verify-triggered`.
|
|
88
91
|
|
|
89
92
|
## §Scenario 8 — Cut on the wrong branch
|
|
90
93
|
|
|
@@ -56,14 +56,17 @@ export const GATE_ROSTER = [
|
|
|
56
56
|
// worktree.mjs && npm run dogfood:status` once under the pnpm layout too
|
|
57
57
|
// before cutting (cut-procedure.md §3.1 states the per-gate layout need).
|
|
58
58
|
{ n: 17, cmd: 'npm run dogfood:status', what: 'P0/P1 dogfood floor (static-only under npm-ci; run once more under bootstrap layout for full coverage, gh#1359)' },
|
|
59
|
-
// gh#421: these
|
|
60
|
-
//
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
//
|
|
59
|
+
// gh#421: these live in the `npm run check` aggregate but were never in
|
|
60
|
+
// the pre-cut roster, so a gate added to CI silently never reached a cut.
|
|
61
|
+
// examples-md is the generator an `.examples.html` edit invalidates (the
|
|
62
|
+
// v0.8.14 cut lost a CI round-trip to exactly that); contrast is the AA
|
|
63
|
+
// gate that gh#427 widened from 42 to 90 pairs; token-semantics-sync keeps
|
|
64
|
+
// the token-selection pack's generated half honest.
|
|
65
|
+
// (Gate 19 was `verify:site-a2ui` — retired with the site-a2ui mechanism
|
|
66
|
+
// itself, ADR-0072 Decision 2 / gh#2410. Number left unassigned rather
|
|
67
|
+
// than renumbering 20+ — gate numbers are cited as identities in shipped
|
|
68
|
+
// release notes, same discipline gate 29's note states.)
|
|
65
69
|
{ n: 18, cmd: 'npm run check:examples-md-fresh', what: '.examples.md vs .examples.html' },
|
|
66
|
-
{ n: 19, cmd: 'npm run verify:site-a2ui', what: 'site-a2ui converted rows vs source fragments' },
|
|
67
70
|
{ n: 20, cmd: 'npm run verify:contrast', what: 'WCAG AA — canvas-text + text-on-fill pairs' },
|
|
68
71
|
{ n: 21, cmd: 'npm run check:token-semantics-sync', what: 'token-selection generated references vs token sources' },
|
|
69
72
|
// Operator directive 2026-07-27: demo surfaces must be discoverable —
|