@adia-ai/adia-ui-forge 0.1.2 → 0.8.0
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 -6
- package/CHANGELOG.md +27 -26
- package/README.md +35 -40
- package/agents/a2ui-engineer.md +26 -0
- package/agents/component-author.md +29 -0
- package/agents/framework-verifier.md +26 -0
- package/agents/release-engineer.md +25 -0
- package/agents/routing-corpus.json +318 -0
- package/bin/demo-postwrite-pattern-gate +94 -0
- package/bin/forge-lint +17 -2
- package/bin/sidecar-prewrite-guard +104 -0
- package/commands/deploy.md +9 -0
- package/commands/dogfood.md +10 -0
- package/commands/gen-review.md +9 -0
- package/commands/release.md +10 -0
- package/hooks/hooks.json +15 -0
- package/package.json +3 -5
- package/references/contracts/a2ui-mcp-surface.md +35 -0
- package/references/contracts/migration-guide-format.md +34 -0
- package/references/shared/content-trust.md +19 -74
- package/skills/adia-a2ui/SKILL.md +99 -0
- package/skills/{adia-ui-a2ui → adia-a2ui}/evals/routing-corpus.json +10 -10
- package/skills/adia-a2ui/references/anti-patterns.md +27 -0
- package/skills/adia-a2ui/references/chunk-authoring.md +71 -0
- package/skills/adia-a2ui/references/corpus-discipline.md +68 -0
- package/skills/adia-a2ui/references/eval-diagnostics.md +86 -0
- package/skills/adia-a2ui/references/format-extension-decisions.md +66 -0
- package/skills/adia-a2ui/references/leverage-rules.md +52 -0
- package/skills/adia-a2ui/references/mcp-pipeline-ops.md +83 -0
- package/skills/adia-a2ui/references/mcp-tool-reference.md +59 -0
- package/skills/adia-a2ui/references/pipeline-overview.md +115 -0
- package/skills/adia-a2ui/references/semantic-fail-lifting.md +74 -0
- package/skills/adia-a2ui/references/strategy-engines.md +109 -0
- package/skills/adia-a2ui/references/zettel-calibration.md +104 -0
- package/skills/adia-author/SKILL.md +112 -0
- package/skills/adia-author/evals/routing-corpus.json +222 -0
- package/skills/{adia-ui-authoring → adia-author}/references/anti-patterns.md +33 -4
- package/skills/{adia-ui-authoring → adia-author}/references/authoring-cycle.md +9 -11
- package/skills/adia-author/references/canonical-pattern-index.md +243 -0
- package/skills/{adia-ui-authoring → adia-author}/references/code-style.md +19 -21
- package/skills/adia-author/references/common-gotchas.md +129 -0
- package/skills/adia-author/references/composite-demo-protocol.md +271 -0
- package/skills/{adia-ui-authoring → adia-author}/references/css-patterns.md +19 -6
- package/skills/{adia-ui-authoring → adia-author}/references/lifecycle-patterns.md +1 -0
- package/skills/{adia-ui-authoring → adia-author}/references/llm-bridge.md +3 -5
- package/skills/{adia-ui-authoring → adia-author}/references/module-promotion.md +22 -40
- package/skills/{adia-ui-authoring → adia-author}/references/primitive-audit.md +2 -4
- package/skills/{adia-ui-authoring → adia-author}/references/shell-patterns.md +12 -18
- package/skills/{adia-ui-authoring → adia-author}/references/token-contract.md +5 -7
- package/skills/{adia-ui-authoring → adia-author}/references/worked-example.md +3 -3
- package/skills/{adia-ui-authoring → adia-author}/references/yaml-contract.md +3 -3
- package/skills/{adia-ui-authoring → adia-author}/scripts/build-canonical-pattern-index.mjs +3 -3
- package/skills/adia-deploy/SKILL.md +128 -0
- package/skills/adia-deploy/references/deploy-playbooks.md +276 -0
- package/skills/adia-dogfood/SKILL.md +124 -0
- package/skills/adia-dogfood/references/admin-shell-anatomy.md +77 -0
- package/skills/adia-dogfood/references/app-shell-pitfalls.md +66 -0
- package/skills/adia-dogfood/references/card-anatomy-sweep.md +66 -0
- package/skills/adia-dogfood/references/html-attr-sweep.md +63 -0
- package/skills/adia-dogfood/references/native-leak-annotations.md +73 -0
- package/skills/adia-dogfood/references/visual-probe-triage.md +80 -0
- package/skills/{adia-ui-dogfood → adia-dogfood}/scripts/analyze.mjs +30 -14
- package/skills/adia-gen-review/SKILL.md +127 -0
- package/skills/adia-gen-review/references/corpus-html-patterns.md +279 -0
- package/skills/adia-gen-review/references/loop-protocol.md +216 -0
- package/skills/adia-gen-review/references/rubric-cosmetic.md +100 -0
- package/skills/adia-gen-review/references/rubric-decompose.md +101 -0
- package/skills/adia-gen-review/references/rubric-score.md +214 -0
- package/skills/{adia-ui-gen-review → adia-gen-review}/references/scores.schema.json +2 -2
- package/skills/{adia-ui-gen-review → adia-gen-review}/scripts/gen-review-coverage-audit.mjs +4 -4
- package/skills/{adia-ui-gen-review → adia-gen-review}/scripts/gen-review-decompose.mjs +10 -6
- package/skills/{adia-ui-gen-review → adia-gen-review}/scripts/gen-review-status.mjs +5 -5
- package/skills/{adia-ui-gen-review → adia-gen-review}/scripts/validate-cycle-scores.mjs +5 -5
- package/skills/adia-llm-internals/SKILL.md +77 -0
- package/skills/{adia-ui-llm → adia-llm-internals}/references/adapter-contract.md +4 -2
- package/skills/{adia-ui-llm → adia-llm-internals}/references/add-a-provider.md +4 -5
- package/skills/{adia-ui-llm → adia-llm-internals}/references/bridge-facade.md +10 -3
- package/skills/{adia-ui-llm → adia-llm-internals}/references/browser-proxy-boundary.md +1 -1
- package/skills/{adia-ui-llm → adia-llm-internals}/references/model-registry.md +5 -3
- package/skills/{adia-ui-llm → adia-llm-internals}/references/streaming-sse.md +2 -2
- package/skills/adia-release/SKILL.md +72 -0
- package/skills/adia-release/references/changelog-discipline.md +119 -0
- package/skills/adia-release/references/cut-procedure.md +247 -0
- package/skills/adia-release/references/gates-catalog.md +222 -0
- package/skills/adia-release/references/independent-package-release.md +52 -0
- package/skills/adia-release/references/migration-guide-authoring.md +86 -0
- package/skills/adia-release/references/notes-authoring.md +90 -0
- package/skills/adia-release/references/recovery-paths.md +106 -0
- package/skills/{adia-ui-release → adia-release}/scripts/bump.mjs +27 -2
- package/skills/{adia-ui-release → adia-release}/scripts/dispatch-publish.mjs +72 -6
- package/skills/{adia-ui-release → adia-release}/scripts/insert-stub.mjs +6 -4
- package/skills/adia-release/scripts/package-paths.mjs +50 -0
- package/skills/{adia-ui-release → adia-release}/scripts/promote-unreleased.mjs +4 -3
- package/skills/{adia-ui-release → adia-release}/scripts/release-pack.mjs +48 -27
- package/skills/{adia-ui-release → adia-release}/scripts/tag-lockstep.mjs +15 -3
- package/skills/adia-site-docs/SKILL.md +68 -0
- package/skills/adia-site-docs/evals/audit-report.md +30 -0
- package/skills/adia-site-docs/evals/routing-corpus.json +176 -0
- package/skills/adia-site-docs/intent.md +72 -0
- package/bin/lib/audit-axes.mjs +0 -555
- package/bin/lib/dry-run-irreversible.mjs +0 -236
- package/bin/lib/run-skill-evals.mjs +0 -487
- package/bin/lib/teach-router.mjs +0 -250
- package/commands/adia-forge-a2ui.md +0 -10
- package/commands/adia-forge-author.md +0 -10
- package/commands/adia-forge-dogfood.md +0 -8
- package/commands/adia-forge-llm.md +0 -8
- package/commands/adia-forge-orient.md +0 -10
- package/commands/adia-forge-release.md +0 -8
- package/commands/adia-forge-review.md +0 -10
- package/references/shared/pev-rationale.md +0 -64
- package/references/shared/skill-conventions.md +0 -133
- package/skills/adia-ui-a2ui/CHANGELOG.md +0 -32
- package/skills/adia-ui-a2ui/SKILL.md +0 -243
- package/skills/adia-ui-a2ui/evals/adversarial-corpus.json +0 -75
- package/skills/adia-ui-a2ui/evals/teach-routing-cases.json +0 -100
- package/skills/adia-ui-a2ui/references/anti-patterns.md +0 -24
- package/skills/adia-ui-a2ui/references/chunk-authoring.md +0 -88
- package/skills/adia-ui-a2ui/references/corpus-discipline.md +0 -56
- package/skills/adia-ui-a2ui/references/eval-diagnostics.md +0 -127
- package/skills/adia-ui-a2ui/references/fragment-graph.md +0 -91
- package/skills/adia-ui-a2ui/references/mcp-pipeline-ops.md +0 -106
- package/skills/adia-ui-a2ui/references/mcp-tool-reference.md +0 -398
- package/skills/adia-ui-a2ui/references/pipeline-overview.md +0 -175
- package/skills/adia-ui-a2ui/references/semantic-fail-lifting.md +0 -120
- package/skills/adia-ui-a2ui/references/strategy-engines.md +0 -111
- package/skills/adia-ui-a2ui/references/teach-protocol.md +0 -220
- package/skills/adia-ui-a2ui/references/zettel-calibration.md +0 -93
- package/skills/adia-ui-a2ui/scripts/audit-a2ui-roster.mjs +0 -96
- package/skills/adia-ui-a2ui/scripts/teach-route.mjs +0 -157
- package/skills/adia-ui-a2ui/skill.json +0 -38
- package/skills/adia-ui-authoring/CHANGELOG.md +0 -32
- package/skills/adia-ui-authoring/SKILL.md +0 -256
- package/skills/adia-ui-authoring/assets/case-studies/admin-shell-decomposition.md +0 -101
- package/skills/adia-ui-authoring/assets/case-studies/maxtokens-32768-discovery.md +0 -109
- package/skills/adia-ui-authoring/assets/case-studies/theme-panel-promotion.md +0 -113
- package/skills/adia-ui-authoring/evals/adversarial-design-plan-gates.json +0 -138
- package/skills/adia-ui-authoring/evals/routing-corpus.json +0 -245
- package/skills/adia-ui-authoring/references/canonical-pattern-index.md +0 -179
- package/skills/adia-ui-authoring/references/common-gotchas.md +0 -93
- package/skills/adia-ui-authoring/references/composite-demo-protocol.md +0 -1084
- package/skills/adia-ui-authoring/references/teach-protocol.md +0 -428
- package/skills/adia-ui-authoring/scripts/audit-authoring-roster.mjs +0 -148
- package/skills/adia-ui-authoring/skill.json +0 -45
- package/skills/adia-ui-dogfood/CHANGELOG.md +0 -17
- package/skills/adia-ui-dogfood/README.md +0 -62
- package/skills/adia-ui-dogfood/SKILL.md +0 -866
- package/skills/adia-ui-dogfood/skill.json +0 -40
- package/skills/adia-ui-forge/SKILL.md +0 -88
- package/skills/adia-ui-forge/evals/routing-corpus.json +0 -30
- package/skills/adia-ui-gen-review/CHANGELOG.md +0 -108
- package/skills/adia-ui-gen-review/SKILL.md +0 -266
- package/skills/adia-ui-gen-review/references/loop-protocol.md +0 -712
- package/skills/adia-ui-gen-review/references/rubric-cosmetic.md +0 -144
- package/skills/adia-ui-gen-review/references/rubric-decompose.md +0 -117
- package/skills/adia-ui-gen-review/references/rubric-score.md +0 -249
- package/skills/adia-ui-gen-review/references/teach-protocol.md +0 -214
- package/skills/adia-ui-gen-review/skill.json +0 -22
- package/skills/adia-ui-llm/CHANGELOG.md +0 -25
- package/skills/adia-ui-llm/SKILL.md +0 -165
- package/skills/adia-ui-llm/evals/adversarial-corpus.json +0 -75
- package/skills/adia-ui-llm/evals/routing-corpus.json +0 -30
- package/skills/adia-ui-llm/evals/teach-routing-cases.json +0 -73
- package/skills/adia-ui-llm/references/teach-protocol.md +0 -78
- package/skills/adia-ui-llm/scripts/audit-llm-roster.mjs +0 -93
- package/skills/adia-ui-llm/scripts/teach-route.mjs +0 -119
- package/skills/adia-ui-llm/skill.json +0 -33
- package/skills/adia-ui-release/CHANGELOG.md +0 -23
- package/skills/adia-ui-release/SKILL.md +0 -295
- package/skills/adia-ui-release/assets/case-studies/2026-05-20-batch-push-v0.6.14-v0.6.15.md +0 -144
- package/skills/adia-ui-release/assets/case-studies/2026-05-20-corpus-drift-remediation-v0.6.15.md +0 -155
- package/skills/adia-ui-release/assets/case-studies/2026-05-20-version-skip-correction-v0.6.12.md +0 -114
- package/skills/adia-ui-release/assets/case-studies/2026-05-21-author-from-scratch-v0.6.18.md +0 -139
- package/skills/adia-ui-release/assets/case-studies/2026-05-21-feedback37-retraction-v0.6.21.md +0 -124
- package/skills/adia-ui-release/assets/case-studies/2026-05-21-fn1-enrichment-pass-v0.6.19.md +0 -125
- package/skills/adia-ui-release/assets/case-studies/2026-05-21-stale-test-detection-v0.6.20.md +0 -142
- package/skills/adia-ui-release/assets/case-studies/2026-05-23-freshness-gate-recovery-v0.6.32.md +0 -97
- package/skills/adia-ui-release/assets/case-studies/2026-05-26-catalog-drift-recurring-v0.6.40.md +0 -147
- package/skills/adia-ui-release/assets/templates/stub-changelog.template.md +0 -22
- package/skills/adia-ui-release/evals/evals.json +0 -164
- package/skills/adia-ui-release/references/changelog-discipline.md +0 -250
- package/skills/adia-ui-release/references/cycle-happy-path.md +0 -520
- package/skills/adia-ui-release/references/exe-deploy.md +0 -149
- package/skills/adia-ui-release/references/gates-catalog.md +0 -778
- package/skills/adia-ui-release/references/ledger-discipline.md +0 -232
- package/skills/adia-ui-release/references/migration-guide-authoring.md +0 -174
- package/skills/adia-ui-release/references/multi-agent-baseline.md +0 -207
- package/skills/adia-ui-release/references/notes-authoring.md +0 -212
- package/skills/adia-ui-release/references/recovery-paths.md +0 -215
- package/skills/adia-ui-release/references/rollup-notes.md +0 -208
- package/skills/adia-ui-release/references/teach-protocol.md +0 -468
- package/skills/adia-ui-release/scripts/audit-gate-roster.mjs +0 -196
- package/skills/adia-ui-release/scripts/make-ledger.mjs +0 -179
- package/skills/adia-ui-release/skill.json +0 -75
- /package/skills/{adia-ui-authoring → adia-author}/references/api-contract.md +0 -0
- /package/skills/{adia-ui-release → adia-release}/scripts/assert-monorepo-root.mjs +0 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
# `cut-procedure.md` — the standard lockstep cut
|
|
2
|
+
|
|
3
|
+
> Load for any class-A lockstep cut (cut & ship · author from scratch · deploy
|
|
4
|
+
> handoff). Companions: [`gates-catalog.md`](gates-catalog.md) (gate roster +
|
|
5
|
+
> failure routing), [`changelog-discipline.md`](changelog-discipline.md) (promotion
|
|
6
|
+
> + F-N1 enrichment), [`recovery-paths.md`](recovery-paths.md) (when it goes wrong).
|
|
7
|
+
> The concrete gate names, 9 package paths, and `ui-kit.exe.xyz` deploy are the
|
|
8
|
+
> @adia-ai monorepo's worked example of the portable discipline. `$REPO` = repo root.
|
|
9
|
+
|
|
10
|
+
Two entry variants, converging at Step 5:
|
|
11
|
+
|
|
12
|
+
- **Variant A — deploy handoff:** a peer pre-cut the release commit + CHANGELOG + bump + lockfile. Re-baseline, verify, then resume at Step 6 (tag).
|
|
13
|
+
- **Variant B — author from scratch:** source landed under `## [Unreleased]` with no bump. Do Step 4 (promotion + bump + lockfile), then the full tail.
|
|
14
|
+
|
|
15
|
+
`scripts/release-pack.mjs` (bundled) mechanizes the whole sequence with the three operator checkpoints preserved; the steps below are the manual/diagnostic form.
|
|
16
|
+
|
|
17
|
+
| Step | Action | Mutates? |
|
|
18
|
+
| --- | --- | --- |
|
|
19
|
+
| 1 | Re-baseline (branch check + status + log + fetch) | No |
|
|
20
|
+
| 2 | Classify uncommitted files; stash strays | Stash only |
|
|
21
|
+
| 3 | Pre-flight gates (+ harvest preamble if source content changed) | No |
|
|
22
|
+
| 4 | (Variant B) Promote `[Unreleased]`; bump; lockfile | Yes |
|
|
23
|
+
| 5 | Stage the release allowlist; commit on `release/vX.Y.Z` | Yes |
|
|
24
|
+
| 5.5 | Pre-commit freshness trip-wire | No |
|
|
25
|
+
| 5.7 | Release PR: push branch → CI → merge → re-baseline on `main` | PR + merge |
|
|
26
|
+
| 6 | Tag umbrella + per-package at post-merge HEAD — **checkpoint 1 first** | Yes |
|
|
27
|
+
| 7 | F-N1 release trip-wire; enrich CHANGELOGs on warns | If warns |
|
|
28
|
+
| 8 | Push tags (one per push; `main` already merged) — **checkpoint 2 first** | Push |
|
|
29
|
+
| 9 | Dispatch publish workflows; wait; verify registry — **checkpoint 3 first** | Publish |
|
|
30
|
+
| 10 | GH releases + site deploy | Deploy |
|
|
31
|
+
| 11 | Author release notes (default, not optional) | No |
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## §Step 1 — Re-baseline
|
|
36
|
+
|
|
37
|
+
Context is stale at the start of every turn; run unconditionally:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
git -C "$REPO" branch --show-current # MUST print: main
|
|
41
|
+
git -C "$REPO" status --short
|
|
42
|
+
git -C "$REPO" log --oneline -8
|
|
43
|
+
git -C "$REPO" fetch && git -C "$REPO" log HEAD..origin/main --oneline # must be empty
|
|
44
|
+
git -C "$REPO" tag --list 'vX.Y.Z' '*-vX.Y.Z' # must NOT exist yet
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`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.
|
|
48
|
+
|
|
49
|
+
## §Step 2 — Classify uncommitted files; stash strays
|
|
50
|
+
|
|
51
|
+
Modified/untracked files you didn't author are classification decisions — diff each one. A **stray** = uncommitted + undocumented (no CHANGELOG entry or commit explains it) + behavior-visible + contradicting a release artifact. Stash strays; never revert (revert destroys the work):
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
git -C "$REPO" stash push <file1> <file2> -m "vX.Y.Z-cycle: <reason> — parked"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Keep the stash held through the site deploy (Step 10) — the tarball builds from the **tag** but the site builds from the **working tree**; an uncommitted stray leaks into the deployed site and not the packages, silently. Pop after the cycle; if pop reports "kept the stash", see [`recovery-paths.md`](recovery-paths.md) §Scenario 6. Record any exclusion in the release-commit message (`Excluded — in-flight: <file> (<reason>)`).
|
|
58
|
+
|
|
59
|
+
## §Step 3 — Pre-flight gates
|
|
60
|
+
|
|
61
|
+
### 3.0 Harvest preamble (only when source content changed in the window)
|
|
62
|
+
|
|
63
|
+
If `git diff <prev-tag>..HEAD --name-only` touches component yaml / `.a2ui.json` sources, `*.contents.html`, catalog/site pages with `data-chunk-*` annotations — regenerate downstream artifacts proactively (otherwise the freshness gates force a tag-move recovery later):
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
node scripts/build/components.mjs # catalog + per-component sidecars
|
|
67
|
+
npm run harvest:chunks # chunk corpus from site/apps/playgrounds/catalog
|
|
68
|
+
npm run build:embeddings:chunks # embedding index (needs OPENAI_API_KEY)
|
|
69
|
+
npm run build -w @adia-ai/llm # tsc artifact build:bundle-js resolves
|
|
70
|
+
npm run build:bundles # dist CSS+JS bundles
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**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.
|
|
74
|
+
|
|
75
|
+
### 3.1 The full roster — every gate runs; a subset = pre-flight failure
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
node scripts/build/components.mjs --verify # 1 yaml ↔ sidecar ↔ .d.ts
|
|
79
|
+
npm run verify:traits # 2 trait coverage
|
|
80
|
+
npm run check:lockstep # 3 version coherence
|
|
81
|
+
npm run test:unit # 4 vitest
|
|
82
|
+
npm run typecheck # 5 tsc --noEmit
|
|
83
|
+
npm run check:demo-shells # 6 demo imports cover composes:
|
|
84
|
+
npm run check:lightningcss-build # 7 CSS minifies
|
|
85
|
+
npm run check:css-bundles-fresh # 8 dist CSS matches source
|
|
86
|
+
npm run check:js-bundles-fresh # 9 dist JS matches source
|
|
87
|
+
npm run smoke:engines # 10 gen-UI engines
|
|
88
|
+
npm run smoke:register-engine # 11 register-engine 11/11
|
|
89
|
+
npm run verify:corpus # 12 corpus 0 errors
|
|
90
|
+
npm run check:chunks-fresh # 13 chunk index vs sources
|
|
91
|
+
npm run check:embeddings-fresh # 14 embeddings vs chunk index
|
|
92
|
+
npm run check:links # 15 intra-repo links
|
|
93
|
+
npm run eval:diff -- --engine zettel # 16 eval floors
|
|
94
|
+
npm run dogfood:status # 17 P0/P1 dogfood floor
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Any red → route via [`gates-catalog.md`](gates-catalog.md); fix at the source, re-run the narrowest gate, then re-run the full sequence. The canonical miss: a cut that ran 7 of the gates shipped a stale-embeddings defect that surfaced a day later and cost a tag-move recovery.
|
|
98
|
+
|
|
99
|
+
## §Step 4 — (Variant B) Promote, bump, lockfile
|
|
100
|
+
|
|
101
|
+
**4a. Promote** `## [Unreleased]` → `## [vX.Y.Z] — YYYY-MM-DD` per package (`scripts/promote-unreleased.mjs`); author fresh blocks for changed-but-unlogged packages; stub the pure ride-alongs (`scripts/insert-stub.mjs`). Classification recipe + shapes: [`changelog-discipline.md`](changelog-discipline.md).
|
|
102
|
+
|
|
103
|
+
**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 "${CLAUDE_PLUGIN_ROOT}/skills/adia-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)).
|
|
104
|
+
|
|
105
|
+
**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.
|
|
106
|
+
|
|
107
|
+
**4d.** `npm run check:lockstep` → `OK — all packages at X.Y.Z, all internal ranges at ^X.Y.0`.
|
|
108
|
+
|
|
109
|
+
## §Step 5 — Stage and commit (on a release branch)
|
|
110
|
+
|
|
111
|
+
The release commit lands via PR, never a direct push to `main` (repo
|
|
112
|
+
policy, operator ruling 2026-07-12 — everything ships PR-first). Branch
|
|
113
|
+
FIRST, then stage. Defensively clear the index, then stage by explicit
|
|
114
|
+
allowlist (never `git add -A`; if peers may have pre-staged files,
|
|
115
|
+
`git commit -o <paths>` also bypasses a polluted index):
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
git -C "$REPO" checkout -b "release/vX.Y.Z"
|
|
119
|
+
git -C "$REPO" reset HEAD >/dev/null 2>&1
|
|
120
|
+
git -C "$REPO" add package-lock.json packages/*/package.json packages/*/CHANGELOG.md \
|
|
121
|
+
packages/a2ui/*/package.json packages/a2ui/*/CHANGELOG.md # + in-scope source + Step-3.0 regen outputs
|
|
122
|
+
git -C "$REPO" diff --cached --stat | tail -3 # count must match the allowlist
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Commit shape: `chore(release): vX.Y.Z lockstep — <summary>` with substantive scope per package, ride-along stub list, any `Excluded — in-flight:` lines, and the pasted gate summary.
|
|
126
|
+
|
|
127
|
+
## §Step 5.5 — Pre-commit freshness trip-wire
|
|
128
|
+
|
|
129
|
+
After `git add`, before `git commit`, re-run the three freshness gates against staged state:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
node scripts/build/components.mjs --verify && npm run check:chunks-fresh && npm run check:embeddings-fresh
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
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.
|
|
136
|
+
|
|
137
|
+
## §Step 5.7 — Release PR: push the branch, merge, re-baseline
|
|
138
|
+
|
|
139
|
+
The release commit reaches `main` through the standard PR flow:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
git -C "$REPO" push -u origin "release/vX.Y.Z"
|
|
143
|
+
gh pr create --title "release: vX.Y.Z lockstep" --body "<scope + gate summary>"
|
|
144
|
+
# wait for required checks (fail-soft jobs excluded); then merge per house flow:
|
|
145
|
+
gh pr merge <N> --admin --merge --delete-branch
|
|
146
|
+
git -C "$REPO" checkout main && git -C "$REPO" pull
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Post-merge fixes land as follow-up commits to the SAME release PR (or a
|
|
150
|
+
second PR merged before tagging) — the tag point below is always `main`'s
|
|
151
|
+
post-merge HEAD, so anything merged before tagging ships in the tarball.
|
|
152
|
+
If unrelated PRs merged between yours and the tag step, that is fine: tag
|
|
153
|
+
at HEAD is the invariant, and the window closes at the tag.
|
|
154
|
+
|
|
155
|
+
## §Step 6 — Tag ← operator checkpoint 1 (before tagging)
|
|
156
|
+
|
|
157
|
+
Show the operator the planned tag list + the F-N1 preview; proceed only on their go. 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):
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
node "${CLAUDE_PLUGIN_ROOT}/skills/adia-release/scripts/tag-lockstep.mjs" \
|
|
161
|
+
--version X.Y.Z # umbrella vX.Y.Z + 11 <pkg>-vX.Y.Z (incl. the 2 plugins, 2026-07-15 policy)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## §Step 7 — F-N1 release trip-wire
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
node scripts/release/check-release.mjs --all-pending
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Per-package tags must be `✓ clean`; the umbrella-tag error is expected noise. On warns, run the enrichment pass ([`changelog-discipline.md`](changelog-discipline.md) §F-N1): fix the entry, land it as a follow-up commit through the PR flow (`--amend` is no longer possible — the release commit is already merged), delete + re-create the tags at the new post-merge SHA, re-run.
|
|
171
|
+
|
|
172
|
+
## §Step 8 — Push tags ← operator checkpoint 2 (before pushing tags)
|
|
173
|
+
|
|
174
|
+
`main` is already on the remote (the release PR merged in Step 5.7) —
|
|
175
|
+
only the tags push here. Show the tag list + confirm
|
|
176
|
+
`git rev-list --count origin/main..HEAD` is 0 (a non-zero count means
|
|
177
|
+
local commits bypassed the PR flow — stop and route them through a PR
|
|
178
|
+
first); on go:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
for t in web-components-vX.Y.Z web-modules-vX.Y.Z llm-vX.Y.Z a2ui-runtime-vX.Y.Z \
|
|
182
|
+
a2ui-compose-vX.Y.Z a2ui-corpus-vX.Y.Z a2ui-mcp-vX.Y.Z \
|
|
183
|
+
a2ui-retrieval-vX.Y.Z a2ui-validator-vX.Y.Z \
|
|
184
|
+
adia-ui-factory-vX.Y.Z adia-ui-forge-vX.Y.Z; do
|
|
185
|
+
git -C "$REPO" push origin "$t" # ONE tag per push — batched multi-tag
|
|
186
|
+
done # pushes drop the create event (Scenario 7)
|
|
187
|
+
git -C "$REPO" push origin vX.Y.Z # umbrella last; triggers nothing
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## §Step 9 — Publish ← operator checkpoint 3 (before publishing)
|
|
191
|
+
|
|
192
|
+
For batch pushes, confirm ordering with the operator: **oldest version publishes and settles first** — `npm dist-tag latest` is set by publish order. Then:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
node "${CLAUDE_PLUGIN_ROOT}/skills/adia-release/scripts/dispatch-publish.mjs" \
|
|
196
|
+
--version X.Y.Z --verify-triggered # re-dispatches only missing runs
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Wait for the workflows to settle, then verify against the **registry**, never the workflow's green check:
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
for pkg in web-components web-modules llm a2ui-runtime a2ui-compose a2ui-corpus \
|
|
203
|
+
a2ui-mcp a2ui-retrieval a2ui-validator adia-ui-factory adia-ui-forge; do
|
|
204
|
+
echo -n "$pkg: "; npm view "@adia-ai/$pkg" version
|
|
205
|
+
done
|
|
206
|
+
npm view @adia-ai/web-components dist-tags.latest # must equal X.Y.Z
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Zero workflows fired after a tag push → [`recovery-paths.md`](recovery-paths.md) §Scenario 7.
|
|
210
|
+
|
|
211
|
+
## §Step 10 — GH releases + site deploy
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
for pkg in <the 9>; do
|
|
215
|
+
gh release create "$pkg-vX.Y.Z" --title "@adia-ai/$pkg vX.Y.Z" --notes-file <body>.md
|
|
216
|
+
done
|
|
217
|
+
# Site deploy goes through the pipeline, never a raw rsync (operator go required — deploy is checkpoint-class):
|
|
218
|
+
gh workflow run "Deploy site (ui-kit.exe.xyz)" --repo adiahealth/gen-ui-kit --ref main
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Deploy discipline (the release tenant of the demo-site host; VM/service ops belong to the deploy skill, `adia-deploy`):
|
|
222
|
+
|
|
223
|
+
- `deploy-site.yml` owns build → pre-flight verify → snapshot → rsync → post-deploy verify → auto-rollback; it builds from `main`, so the release commit must already be merged (§Step 5.7 guarantees this). A raw local rsync bypasses every one of those gates.
|
|
224
|
+
- **Verify deployed FILES, never SPA routes.** The docs site returns HTTP 200 + the same ~5 KB shell for *every* path; an unmatched route renders blank with no error. Curl a content file and grep for real bytes:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
curl -s -o /dev/null -w "%{http_code}\n" https://ui-kit.exe.xyz/packages/web-components/styles/host.css # 200
|
|
228
|
+
curl -s https://ui-kit.exe.xyz/<this-cycle's-content-file> | grep -q "<unique string>" && echo OK
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
- 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.
|
|
232
|
+
|
|
233
|
+
Any Step-2 stashes: `git stash pop`; flag conflicts to the operator.
|
|
234
|
+
|
|
235
|
+
## §Step 11 — Author release notes (default)
|
|
236
|
+
|
|
237
|
+
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".
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## §Variant A shortcut
|
|
242
|
+
|
|
243
|
+
Peer pre-cut the release commit: Step 1 (confirm HEAD is the `release(*): vX.Y.Z` commit) → Step 2 → Step 3 → skip 4–5 → resume at Step 6.
|
|
244
|
+
|
|
245
|
+
## §When to abort
|
|
246
|
+
|
|
247
|
+
Stop and surface to the operator when: a gate fails outside the documented recoveries; F-N1 reports >1 warn per package tag or any non-umbrella error; the release-commit candidate fails `check:demo-shells` / `check:lockstep` / `check:embeddings-fresh` (→ [`recovery-paths.md`](recovery-paths.md) §Scenario 4); uncommitted files stay unclassifiable after diffing; or a publish workflow fails E404/E401 (npm-token rotation — operator-owned).
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
# `gates-catalog.md` — pre-flight gate roster + failure → recovery map
|
|
2
|
+
|
|
3
|
+
> Load for a verify-only run or on any gate failure during a cut. Maps every
|
|
4
|
+
> release-flow gate × what it checks × typical failure × recovery. Gates are
|
|
5
|
+
> grouped by **failure category** — how the operator routes when one goes red —
|
|
6
|
+
> not by alphabetical namespace. Cited scripts live in the target monorepo's
|
|
7
|
+
> `package.json` (`check:*` / `verify:*` / `smoke:*` / `test:*`).
|
|
8
|
+
|
|
9
|
+
Row layout per gate: **What** · **Typical failure** · **Recovery**.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## §Category 1 — Release identity (hard-fail any cut)
|
|
14
|
+
|
|
15
|
+
### `npm run check:lockstep`
|
|
16
|
+
|
|
17
|
+
- **What:** all 9 `@adia-ai/*` packages declare the same `version`; internal `@adia-ai/*` dep ranges match policy (`^X.Y.0` during PATCH cycles, bumped at MINOR).
|
|
18
|
+
- **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 → `scripts/bump.mjs` (bundled with this skill); range drift → `npm run check:lockstep:fix` auto-aligns, then re-run.
|
|
20
|
+
- **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
|
+
|
|
22
|
+
### `node scripts/release/check-release.mjs --all-pending` (F-N1, the release trip-wire)
|
|
23
|
+
|
|
24
|
+
- **What:** for every unpushed tag, verifies CHANGELOG coverage of the diff between this tag and the package's previous tag.
|
|
25
|
+
- **Cosmetic failure:** "diff `packages/<pkg>/components/` touched but CHANGELOG `[X.Y.Z]` doesn't mention 'components'" — the entry names the component (`table-ui`) but not the literal path keyword. Regex miss, change IS documented.
|
|
26
|
+
- **Real failure:** a touched directory has NO matching CHANGELOG entry at all — the cycle missed documenting a change.
|
|
27
|
+
- **Recovery:** cosmetic → add the path keyword to a relevant entry (`table.yaml` → `components/table/table.yaml`); real → author the missing entry. Either way: amend the release commit, delete + re-create the tags at the new SHA, re-run. Full discipline: [`changelog-discipline.md`](changelog-discipline.md) §F-N1 enrichment.
|
|
28
|
+
- The umbrella tag's "doesn't match `<pkg>-v<version>`" **error is expected — ignore it**; only per-package warns need action.
|
|
29
|
+
|
|
30
|
+
### `npm run check:changelog-coverage`
|
|
31
|
+
|
|
32
|
+
- **What:** every published package has a `[vX.Y.Z]` CHANGELOG block for the current `package.json` version.
|
|
33
|
+
- **Recovery:** add the block (stub if genuinely no source change — but classify by the diff first, see [`changelog-discipline.md`](changelog-discipline.md) §Detecting source-changing packages).
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## §Category 2 — Generated-file coherence (hard-fail any cut)
|
|
38
|
+
|
|
39
|
+
### `node scripts/build/components.mjs --verify`
|
|
40
|
+
|
|
41
|
+
- **What:** every component yaml has an up-to-date `.a2ui.json` sidecar; `.d.ts` codegen current. (Generated files are also hook-guarded against hand edits.)
|
|
42
|
+
- **Recovery:** `node scripts/build/components.mjs` (no `--verify`) regenerates; stage the sidecars.
|
|
43
|
+
|
|
44
|
+
### `npm run verify:traits`
|
|
45
|
+
|
|
46
|
+
- **What:** `traits/_catalog.json` reflects every `defineTrait()` call; 100% coverage.
|
|
47
|
+
- **Recovery:** `npm run build:traits`; stage.
|
|
48
|
+
|
|
49
|
+
### `npm run verify:a2ui-schema`
|
|
50
|
+
|
|
51
|
+
- **What:** the A2UI JSON Schema is in sync with the `@adia-ai/a2ui-runtime` TS types.
|
|
52
|
+
- **Recovery:** `node scripts/build/a2ui-schema-types.mjs`; stage.
|
|
53
|
+
|
|
54
|
+
### `npm run verify:tsconfig-strictness`
|
|
55
|
+
|
|
56
|
+
- **What:** per-package `tsconfig.json` doesn't silently relax flags set strict in `tsconfig.base.json` (ADR-0029). A relaxation needs a `// TS-MIG-NNN` tracking comment.
|
|
57
|
+
- **Recovery:** remove the override, or add the tracking comment.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## §Category 3 — Component / primitive structural drift
|
|
62
|
+
|
|
63
|
+
### `npm run check:demo-shells`
|
|
64
|
+
|
|
65
|
+
- **What:** every component demo `.html` imports all primitives named in its yaml `composes:` list.
|
|
66
|
+
- **Typical failure:** a yaml gained a `composes:` entry but the demo shell didn't get the matching `<script>` import.
|
|
67
|
+
- **Recovery:** add `<script type="module" src="../<tag>/<tag>.js">` to the demo shell. **Release-blocking: HIGH** — a commit failing this gate ships broken demo pages in its tarball. If the fix already landed later but entangled with `[Unreleased]` work → [`recovery-paths.md`](recovery-paths.md) §Scenario 4.
|
|
68
|
+
|
|
69
|
+
Smaller siblings in this category (same recovery shape — fix the declaration or regenerate the registry):
|
|
70
|
+
|
|
71
|
+
| Gate | What |
|
|
72
|
+
| --- | --- |
|
|
73
|
+
| `check:composes` | every yaml `composes:` entry resolves to a real primitive |
|
|
74
|
+
| `check:dts-sibling-presence` | every component `.js` has a sibling `.d.ts` |
|
|
75
|
+
| `check:registry-catalog-coherence` | runtime registry ↔ A2UI catalog parity (both directions) |
|
|
76
|
+
| `check:required-icons` | every referenced `<icon-ui>` name is registered |
|
|
77
|
+
| `check:standalone-html-phosphor` | standalone demos using Phosphor icons include the loader |
|
|
78
|
+
| `check:substitutable-set-drift` | substitutable-element registry in sync |
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## §Category 4 — CSS spec compatibility
|
|
83
|
+
|
|
84
|
+
### `npm run check:lightningcss-build`
|
|
85
|
+
|
|
86
|
+
- **What:** every CSS file under `packages/web-{components,modules}/` minifies cleanly under LightningCSS + current Vite default targets.
|
|
87
|
+
- **Recovery:** fix the offending CSS. Most common sub-case ↓
|
|
88
|
+
|
|
89
|
+
### `npm run check:scope-bare-descendants`
|
|
90
|
+
|
|
91
|
+
- **What:** no `@scope { > X {} }` bare-combinator descendants (LightningCSS rejects as "Invalid empty selector").
|
|
92
|
+
- **Recovery:** `node scripts/build/codemod-scope-bare-descendants.mjs` rewrites `> X` → `& > X`.
|
|
93
|
+
|
|
94
|
+
Also: `check:no-self-import-css` (no transitively self-importing barrel) · `check:rolldown-glob` (`import.meta.glob` works under Rolldown).
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## §Category 5 — Browser safety / module hygiene
|
|
99
|
+
|
|
100
|
+
### `npm run check:browser-safe`
|
|
101
|
+
|
|
102
|
+
- **What:** no top-level `import 'node:*'` in browser-reachable modules (`packages/a2ui/{compose,retrieval,validator}`, `web-components/`, `web-modules/`, `apps/*/app/*.contents.js`).
|
|
103
|
+
- **Recovery:** dual-mode pattern (`IS_NODE` + dynamic `await import(/* @vite-ignore */ 'node:*')` + `import.meta.glob` browser branch); canonical impl: `packages/a2ui/retrieval/component-catalog.js`.
|
|
104
|
+
|
|
105
|
+
Siblings: `check:absolute-imports` (no leading-`/` imports — rewrite relative) · `check:template-interp` (template `${expr}` contract) · `check:yaml-events` (yaml `events:` match runtime `dispatchEvent` calls) · `check:yaml-impl-coverage` (every yaml prop implemented in the JS class).
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## §Category 6 — Visual / structural integrity
|
|
110
|
+
|
|
111
|
+
| Gate | What |
|
|
112
|
+
| --- | --- |
|
|
113
|
+
| `check:card-structure` / `check:drawer-structure` | card/drawer body wraps in `<section>` (strict variants of the `audit:*` twins) |
|
|
114
|
+
| `check:with-css-pairing` | every shell with paired `.js` + `.css` has a `/with-css` companion + exports-map entry |
|
|
115
|
+
| `verify:no-legacy-shell-shapes` | no legacy `<main>` / `[data-content-*]` shapes under `<admin-shell>` (ADR-0032) |
|
|
116
|
+
| `audit:native-primitive-leak` | native `<button>`/`<input>`/… where a `*-ui` equivalent exists; criticals must be replaced or annotated `data-native-ok="<reason>"` |
|
|
117
|
+
| `audit:shell-composition` | admin-shell compositions missing canonical parts (statusbar, `[data-spacer]`/`[data-actions]`, …); escape hatch `data-shell-opt-out="<reason>"` |
|
|
118
|
+
|
|
119
|
+
The two `audit:*` probes are soft-fail pre-cut (exit-1 only on criticals); findings get folded into release notes if non-zero. Recovery for both is manual — slot/attr semantics need a human eyeball, never auto-fix.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## §Category 7 — Corpus / bundle freshness
|
|
124
|
+
|
|
125
|
+
### `npm run verify:corpus`
|
|
126
|
+
|
|
127
|
+
- **What:** every chunk in `packages/a2ui/corpus/chunks/*.json` is reachable and well-formed.
|
|
128
|
+
- **Recovery:** corpus remediation routes to the A2UI-pipeline skill, not this one.
|
|
129
|
+
|
|
130
|
+
### `npm run check:chunks-fresh`
|
|
131
|
+
|
|
132
|
+
- **What:** `chunks/_index.json` matches on-disk chunks and source fragments.
|
|
133
|
+
- **Recovery:** `npm run harvest:chunks`; stage the corpus outputs.
|
|
134
|
+
|
|
135
|
+
### `npm run check:embeddings-fresh`
|
|
136
|
+
|
|
137
|
+
- **What:** `chunk-embeddings.json` at-or-newer-than `chunks/_index.json`.
|
|
138
|
+
- **Recovery:** `npm run build:embeddings:chunks` (needs `OPENAI_API_KEY`; ~6s). Stage `chunk-embeddings.json` + note the regen in the a2ui-corpus CHANGELOG `[vX.Y.Z]`.
|
|
139
|
+
|
|
140
|
+
### `npm run check:css-bundles-fresh` / `npm run check:js-bundles-fresh`
|
|
141
|
+
|
|
142
|
+
- **What:** the `dist/` CDN bundles (`web-components.min.{css,js}`, `everything.min.js`, per-shell `*.min.js`, `icons-manifest.js`) match source. Stale bundles mean jsdelivr/unpkg serve yesterday's build. **Blocking in CI** (2026-06-08).
|
|
143
|
+
- **Recovery:** `npm run build -w @adia-ai/llm` **FIRST** (its `index.js` is a gitignored tsc artifact `build:bundle-js` resolves — a fresh worktree can't bundle without it), then `npm run build:bundles` (or `build:bundle-css` / `build:bundle-js` individually). Stage both `dist/` trees.
|
|
144
|
+
- **Manual spot-checks** (complement the gate; the v0.6.29–31 cycles shipped a shells-only `everything.min.js` that hard-crashed CDN consumers):
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
grep "import '@adia-ai/web-components'" packages/web-modules/everything.js # must be present
|
|
148
|
+
grep -oE '"[a-z][a-z-]*-ui"' packages/web-modules/dist/everything.min.js | sort -u | wc -l # ≥100
|
|
149
|
+
node -e "const m=require('./packages/web-components/dist/icons-manifest.js'); \
|
|
150
|
+
console.log('regular:', m.default.regular.length, '| cdn:', m.default.cdn)" # non-empty + cdn key
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### `npm run audit:chunk-reconcile`
|
|
154
|
+
|
|
155
|
+
- **What:** duplicate-reconciliation report for the chunk corpus (fingerprint collisions, near-duplicates, structural twins). Advisory, not blocking.
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## §Category 8 — Tests + types + evals
|
|
160
|
+
|
|
161
|
+
### `npm run test:unit`
|
|
162
|
+
|
|
163
|
+
- **What:** the vitest suite (~1000+ tests).
|
|
164
|
+
- **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.
|
|
165
|
+
- **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. **Gate on `npx vitest run --no-file-parallelism`** (sequential is the source of truth); don't treat a one-off parallel flake as a blocker, and don't raise the drain guard.
|
|
166
|
+
|
|
167
|
+
### `npm run eval:diff -- --engine zettel`
|
|
168
|
+
|
|
169
|
+
- **What:** end-to-end gen-UI eval. Floors (preserve-not-regress):
|
|
170
|
+
- **Zettel**: cov ≥ 87%, avg ≥ 85, MRR ≥ 0.94
|
|
171
|
+
- **Free-form**: cov ≥ 90%, avg ≥ 83, F1 ≥ 55
|
|
172
|
+
- **Monolithic**: cov = 100%, avg ≥ 95
|
|
173
|
+
- **Dogfood**: 20/20, avg ≥ 95
|
|
174
|
+
- **Recovery:** retrieval/corpus regression — routes to the A2UI-pipeline skill.
|
|
175
|
+
|
|
176
|
+
Siblings: `typecheck` (`tsc --noEmit`) · `smoke:engines` (gen-UI engines + retrieval probes) · `smoke:register-engine` (11/11) · `test:a2ui` (22/22, +1 skipped OK).
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## §Category 9 — Misc release safety
|
|
181
|
+
|
|
182
|
+
### `npm run dogfood:status`
|
|
183
|
+
|
|
184
|
+
- **What:** aggregator over the component dogfood audits; classifies findings P0–P3 and regenerates the tracker at `qa/findings/dogfood-tracker.md`. Exit-1 when P0+P1 > 0; P2/P3 are advisory.
|
|
185
|
+
- **Pre-cut policy: must pass before tag.** Any P0/P1 means a paid-down bug class was re-introduced; open the tracker, apply the canonical fix template at the cited file:line, re-run. ~5s.
|
|
186
|
+
|
|
187
|
+
### `npm run verify:pack`
|
|
188
|
+
|
|
189
|
+
- **What:** `npm pack --dry-run` succeeds per package — catches malformed `files`/`exports`. Note: the npm `files:` array supports negation (`!components/**/*.html`); verify tarball contents with `--dry-run` after touching it.
|
|
190
|
+
|
|
191
|
+
Siblings: `check:links` (intra-repo markdown links resolve) · `check:cdn-pins` (docs' CDN `@0.X` pins match the current minor — catches a stale `@0.6` after a `0.7` cut) · `verify:contrast` / `verify:palette` (WCAG pairs / OKLCH ramps).
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## §Standard subsets
|
|
196
|
+
|
|
197
|
+
**Minimum 6 (verify-only default)** — fastest set that catches release-blockers:
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
node scripts/build/components.mjs --verify
|
|
201
|
+
npm run check:lockstep
|
|
202
|
+
npm run verify:traits
|
|
203
|
+
npm run test:unit
|
|
204
|
+
npm run typecheck
|
|
205
|
+
npm run check:demo-shells
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Add `verify:corpus` + `check:embeddings-fresh` if chunks were touched; `check:lightningcss-build` if CSS was touched; F-N1 if unpushed release tags exist.
|
|
209
|
+
|
|
210
|
+
**Full pre-cut sweep** — the 17-gate roster in [`cut-procedure.md`](cut-procedure.md) §Step 3. ~90s wall time.
|
|
211
|
+
|
|
212
|
+
**Omnibus** — `npm run check` invokes everything. Heavy; use when re-baselining a stale checkout.
|
|
213
|
+
|
|
214
|
+
**Suffix variants:** most gates have `:strict` (warns fail), `:fix` (auto-apply, e.g. `check:lockstep:fix`), `:json` / `:quiet` (output form) variants.
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## §Gate stewardship
|
|
219
|
+
|
|
220
|
+
- **This catalog must stay in sync with `package.json` `scripts`.** When a cycle meets a release-flow gate not listed here, add its row in the same change.
|
|
221
|
+
- **New CI gates ship advisory first** (`continue-on-error: true`), promoted to blocking after 5+ green runs. Two freshness-gate traps: mtime checks are permanently red on fresh `actions/checkout` (clone-time mtimes — need `fetch-depth: 0` + git-restore-mtime); a dir-watching gate needs its own workflow whose `pull_request: paths:` covers the watched dirs.
|
|
222
|
+
- **New/extended `scripts/release/check-*.mjs` slots run against `main` immediately**; close every finding same-cycle. Before adding a slot, grep the existing ones — the gap is often a regex limit in a current slot, not a missing slot.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# `independent-package-release.md` — class-B cut (independently-versioned package)
|
|
2
|
+
|
|
3
|
+
> Load when releasing a package versioned **independently** of the lockstep set —
|
|
4
|
+
> excluded from the lockstep gate, no umbrella tag, no demo-site deploy.
|
|
5
|
+
> **Class B currently has NO members** (2026-07-15 policy change, operator
|
|
6
|
+
> ruling): the Claude Code plugins under `packages/plugins/*` joined the
|
|
7
|
+
> lockstep after class-B independence let npm drift a full harness-reset
|
|
8
|
+
> behind the repo (npm served forge 0.1.3/factory 0.2.4 pre-reset content
|
|
9
|
+
> while the rewritten estate sat unpublished at a regressed 0.1.0). This
|
|
10
|
+
> procedure is retained for future genuinely-independent packages. The
|
|
11
|
+
> lockstep cut is [`cut-procedure.md`](cut-procedure.md).
|
|
12
|
+
|
|
13
|
+
## §Two release classes in one monorepo
|
|
14
|
+
|
|
15
|
+
| | Class A — lockstep cut | Class B — independent package |
|
|
16
|
+
| --- | --- | --- |
|
|
17
|
+
| Versioning | whole set bumps together | own version line per package |
|
|
18
|
+
| Lockstep gate | enforced (`check:lockstep` 9/9) | **excluded** — the gate skips `packages/plugins/*` by design |
|
|
19
|
+
| Umbrella tag | `vX.Y.Z` + per-package | **none** — per-package tags only (versions differ) |
|
|
20
|
+
| `dist-tag` ordering | cross-package publish order matters | N/A |
|
|
21
|
+
| Demo-site deploy | yes | **none** |
|
|
22
|
+
| Publish trigger | tag-triggered per-package workflow | same mechanism (`.github/workflows/publish-adia-ui-{factory,forge}.yml`) |
|
|
23
|
+
|
|
24
|
+
Class B keeps the operator checkpoints and the verify-against-the-registry discipline; it drops every lockstep-specific invariant.
|
|
25
|
+
|
|
26
|
+
## §New-package onboarding — the three trip-wires a FIRST cut hits
|
|
27
|
+
|
|
28
|
+
Substrate fixes (release scripts / lockfile / CHANGELOG), landed once as a normal PR on `main` *before* tagging:
|
|
29
|
+
|
|
30
|
+
1. **Lockfile.** A new workspace package absent from the lockfile blocks the pre-commit hook and fails the workflow's `npm ci`. Fix: `npm install --package-lock-only && git add package-lock.json`.
|
|
31
|
+
2. **Release-trip-wire package registry.** F-N1 validates each pushed tag against `scripts/release/check-release.mjs`'s hardcoded `PACKAGES` array; an unregistered tag fails the pre-push hook with `unknown package`. Fix: add `{ tagPrefix: '<name>', path: 'packages/plugins/<name>' }`.
|
|
32
|
+
3. **CHANGELOG bracket form.** The trip-wire requires Keep-a-Changelog `## [<version>]` headings; bare `## <version>` fails with "no `## [<version>]` entry".
|
|
33
|
+
|
|
34
|
+
## §Procedure
|
|
35
|
+
|
|
36
|
+
1. **Re-baseline** — `git fetch`; confirm the checkout isn't on a peer's branch.
|
|
37
|
+
2. **Land the package(s) on `main`** via PR; resolve every review thread before an admin-merge (this repo's merge gate).
|
|
38
|
+
3. **Pre-publish gate.** `npm run verify:plugins` (package.json ↔ plugin-manifest versions synced). Plugin-specific structural gates: `npm run audit:plugin-coupling` + `npm run check:factory-bare-repo` (ADR-0040 — the plugin must work in a bare consumer repo, no monorepo coupling). The lockstep gate still passes for the lockstep set. First publish of a name: `npm view @adia-ai/<pkg> version` → `E404` means the name is free.
|
|
39
|
+
4. **Tag at the published commit** — `git tag <pkg>-vX.Y.Z` per package; versions differ; no umbrella. Dry-run the trip-wire over the tags (`node scripts/release/check-release.mjs <tags>`) before pushing. If the shared working tree is on a peer's branch, push tags from a throwaway worktree on `origin/main`.
|
|
40
|
+
5. **Push the tags** → the per-package workflows run `npm ci → verify:plugins → npm publish --access public`.
|
|
41
|
+
6. **Verify against npm, not the workflow:** `npm view @adia-ai/<pkg> version` returns the new independent version for each package. Watch runs (`gh run watch <id> --exit-status`), but the registry is the source of truth.
|
|
42
|
+
7. **Marketplace cut-over** (if a plugin marketplace repo exists): point the manifest's per-plugin `source` at npm (`{ "source": "npm", "package": "@adia-ai/<pkg>" }`), `git rm -r` vendored copies, validate the JSON, commit, push. Consumers then `/plugin marketplace add <org>/<repo>` → `/plugin install <pkg>@<repo>`.
|
|
43
|
+
|
|
44
|
+
## §Verify target
|
|
45
|
+
|
|
46
|
+
The published package(s) on the **npm registry** at their independent versions, plus (if a marketplace exists) its manifest referencing npm. NOT "all 9 + the demo site" — that's class A.
|
|
47
|
+
|
|
48
|
+
## §Gotchas (from the first independent cut, factory v0.2.2 + forge v0.1.2)
|
|
49
|
+
|
|
50
|
+
- Never add the package to the lockstep gate or tag it with the umbrella.
|
|
51
|
+
- Publish-workflow YAMLs are token-bearing — keep `persist-credentials: false` on the checkout step, matching the established workflows' action-pinning.
|
|
52
|
+
- A marketplace repo's org + visibility is an **operator call** — a public `gh repo create` is outward-facing; confirm first, and run a secret-scan of full history before pushing any repo public.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# `migration-guide-authoring.md` — authoring the MIGRATION GUIDE on a breaking cut
|
|
2
|
+
|
|
3
|
+
> Load whenever the cut is **MINOR** (an API-surface break) or on an explicit
|
|
4
|
+
> "author the migration guide" ask. This is the **producer** side of migrations:
|
|
5
|
+
> the release ships the breaking change, so the release authors the guide section
|
|
6
|
+
> consumers follow. The shared producer/consumer format contract is
|
|
7
|
+
> [`../../../references/contracts/migration-guide-format.md`](../../../references/contracts/migration-guide-format.md)
|
|
8
|
+
> — the factory's `adia-migrate` skill consumes exactly that shape.
|
|
9
|
+
>
|
|
10
|
+
> Scope split: **producer (this skill)** authors the guide section + migrates the
|
|
11
|
+
> framework's own in-repo surfaces. **Consumer** (a downstream app sweep) is the
|
|
12
|
+
> factory plugin's `adia-migrate` — decline and redirect. Designing the breaking
|
|
13
|
+
> change itself is a contract decision upstream of both.
|
|
14
|
+
|
|
15
|
+
The guide lives at **`.claude/docs/MIGRATION GUIDE.md`** (the space in the filename is intentional; it's a first-class consumer artifact). One section per breaking release, newest at top; a consumer jumping versions reads the merged span. Every cut — breaking or not — gets a version-scope bullet in the top index (see the format contract).
|
|
16
|
+
|
|
17
|
+
## §When a section is owed
|
|
18
|
+
|
|
19
|
+
Author (or extend) a section when the cut removes or renames a **public API symbol**: a prop/attribute (`variant="danger"` → `color="danger"`), a slot or slot-semantics flip, an event name, a token (`--n-*` → `--a-*`), a tag, a Boolean → enum migration, or a default-value change wide enough that consumers must act. Same line as the PATCH-vs-MINOR rule: cutting MINOR almost certainly owes a section. Additive cuts need none — note "additive; no consumer sweep" in the version-coverage table and move on.
|
|
20
|
+
|
|
21
|
+
## §The authoring workflow
|
|
22
|
+
|
|
23
|
+
**1. Enumerate the breaking surface** from the cut's diff + CHANGELOG `### Removed`/`### Changed` entries. Per item capture: the symbol · before → after · the kind (pure rename / semantic flip / Boolean→enum / removal) · the audit grep · the sweep (or "manual review").
|
|
24
|
+
|
|
25
|
+
**2. Write the section** — one `###` subsection per item:
|
|
26
|
+
|
|
27
|
+
```markdown
|
|
28
|
+
## Migrating to @adia-ai/web-components@X.Y.Z (YYYY-MM-DD)
|
|
29
|
+
|
|
30
|
+
<one-line scope: N breaking items, the headline.>
|
|
31
|
+
|
|
32
|
+
### <item — bold headline> (`old` → `new`)
|
|
33
|
+
|
|
34
|
+
<one sentence: what changed and why.>
|
|
35
|
+
|
|
36
|
+
**Audit:**
|
|
37
|
+
git grep -nE '<pattern that surfaces call sites>'
|
|
38
|
+
|
|
39
|
+
**Sweep:**
|
|
40
|
+
git grep -nlE '<pattern>' | xargs perl -i -pe 's/<old>/<new>/g'
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Shape rules:
|
|
44
|
+
|
|
45
|
+
- **Audit grep first, sweep second** — the consumer always lists call sites before sweeping; author both.
|
|
46
|
+
- **Mechanical vs manual, explicitly labeled.** A pure rename ships a `perl -i -pe`; a semantic flip ships a "manual review — here's why" note (sed can't tell author intent).
|
|
47
|
+
- **One component per sweep regex** — alternation captures (`<(toast|alert)-ui`) don't preserve the matched alternative cleanly.
|
|
48
|
+
- **HTML-attribute regexes only match HTML/JSX** — author a separate JS-side regex when the symbol has a programmatic form (`el.variant = 'danger'`).
|
|
49
|
+
|
|
50
|
+
**3. Migrate the in-repo surfaces FIRST.** Before the cut ships, run the audit + sweep against `apps/`, `playgrounds/`, `catalog/`, `packages/web-components/components/*/*.html` — the release must not ship broken examples of the thing it changed, and dogfooding the recipe here is what proves it works for consumers.
|
|
51
|
+
|
|
52
|
+
**4. Verify.** Run the cut's normal gate roster; the structural/demo gates catch missed in-repo surfaces. Then the **sweep-verification grep** across ALL extensions — the trap is a vocabulary migration that touched markup but not the CSS selectors or JS comments referencing it:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
LEGACY_PATTERNS=( '<old-tag' 'old-attr=' '--old-token' )
|
|
56
|
+
for pat in "${LEGACY_PATTERNS[@]}"; do
|
|
57
|
+
echo "=== $pat ==="
|
|
58
|
+
grep -rln -E "$pat" apps playgrounds catalog \
|
|
59
|
+
--include='*.css' --include='*.html' --include='*.js' --include='*.yaml'
|
|
60
|
+
done # 0 hits = sweep verified clean
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**5. Cross-reference.** The breaking package's CHANGELOG entry names the symbol AND points at the guide section; the release notes carry a `⚠️` heads-up linking it. Anchors are stable — never retitle an existing section (release notes and consumer tooling link them).
|
|
64
|
+
|
|
65
|
+
## §Manual-review classes (never auto-sweep)
|
|
66
|
+
|
|
67
|
+
- **Semantic flips** — a rename that inverts default behavior (`[open]` default-hidden → `[collapsed]` default-visible): the right migration depends on author intent. List occurrences, ask.
|
|
68
|
+
- **Opt-out Booleans defaulting true** — the migration only matters where a consumer explicitly disabled the affordance; sed can't tell.
|
|
69
|
+
- **Ownership moves** — a prop moving from wrapper to slotted child; the target child may not exist yet.
|
|
70
|
+
- **kebab-string property keys** — attribute name unchanged, only the JS programmatic form changed; audit programmatic access only.
|
|
71
|
+
- **Wide namespace renames (50+ symbols)** — tag/token/class rename waves: list by table, require human approval per cluster; blind sweeps hit false positives on shared prefixes.
|
|
72
|
+
|
|
73
|
+
## §The version-coverage table
|
|
74
|
+
|
|
75
|
+
Maintained at the top of the guide; classifies every release so a gap-jumping consumer knows which sections apply: `additive` (bump and go) · `BREAKING (N items)` (has a section) · `structural` (import retargeting) · `rename` (wide namespace rename, manual-review by cluster). Note forward-looking volatile surfaces at the bottom of the guide so the next breaking-release author knows where churn concentrates.
|
|
76
|
+
|
|
77
|
+
## §Anti-patterns
|
|
78
|
+
|
|
79
|
+
Authoring the guide after the cut ships (it's part of the release scope) · a `perl -i -pe` for a semantic flip · merged alternation sweeps · skipping the in-repo sweep · a CHANGELOG bullet with no guide section for a real break (the CHANGELOG says *what*, the guide says *how*) · doing the consumer sweep from here.
|
|
80
|
+
|
|
81
|
+
## §Done when
|
|
82
|
+
|
|
83
|
+
1. Every breaking item in the cut's CHANGELOG has a matching subsection (audit + sweep, or a labeled manual-review note).
|
|
84
|
+
2. In-repo surfaces swept; the sweep-verification grep reports 0 legacy hits.
|
|
85
|
+
3. The cut's structural/demo gates pass.
|
|
86
|
+
4. The release notes carry the `⚠️` heads-up linking the section.
|