From 3be412b743a78b11c8b944fa7024b2f37ed0a679 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 30 Jul 2026 06:29:04 +0000 Subject: [PATCH 1/2] docs(agents): list which spec artifact each CI gate guards, and how to regenerate it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `packages/spec` has eight checked-in generated artifacts, each with its own gate, split across two CI jobs that run their gates sequentially — so the first stale artifact masks every one behind it and you get one red build per artifact. AGENTS.md documented the auto-gen boundary but never mapped a change to the generator it invalidates, so the mapping had to be rediscovered from red CI. #4040 paid that twice, neither time a logic error: a `.describe()` string landed in `content/docs/references/` (`check:docs`), and one new export landed in `api-surface.json` (`check:api-surface`) — the second only visible after the first was fixed. Adds a change → gate → regenerate table, plus a loop that runs all eight so the tooling reports which artifact is stale instead of CI doing it one per push. Also records that `check:liveness` / `check:empty-state` / `check:skill-examples` / `check:react-conformance` have no generator — a failure there is a real finding, not an artifact to regenerate. Includes a caveat found while verifying this: `check:api-surface` reads the built `dist/*.d.ts`, so a stale `dist` reports exports as REMOVED when nothing was removed — the snapshot is just newer than the build. It reported two phantom breaking removals (`canonicalAstOperator`, `FieldErrorCode`) on an untouched tree until `pnpm build` was run, which is exactly the shape of a bug someone would otherwise file against `main`. Every command in the new section was run as written, from a clean checkout of the merged main: all eight gates PASS. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01QoA8AV99Ss1RRkLLAYmDzq --- AGENTS.md | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 5cd449e439..56d0a184d3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -195,6 +195,49 @@ Root also exports: `defineStack`, `composeStacks`, `defineView`, `defineApp`, `d | `content/docs/getting-started/` | hand-written | ✅ | | `content/docs/protocol/` | hand-written | ✅ | +### Touched `packages/spec`? Regenerate its artifacts BEFORE pushing + +`packages/spec` has **eight** checked-in generated artifacts, each with its own CI gate. +They live in two different jobs (`TypeScript Type Check` in `lint.yml`, `Check Generated +Artifacts` in `ci.yml`), and each job runs its gates **sequentially** — so the first +stale artifact masks every one behind it, and you get one red build per artifact instead +of one for all of them. Match the change to the gate and regenerate up front: + +| You changed | Gate that fails | Regenerate with `pnpm --filter @objectstack/spec …` | +|:---|:---|:---| +| A `.describe()` / TSDoc on any schema | `check:docs` | `gen:schema && gen:docs` | +| A public export (added / removed / renamed) | `check:api-surface` | `gen:api-surface` | +| An authorable key on a metadata schema | `check:authorable-surface` | `gen:schema` | +| An ADR-0087 conversion / migration registry | `check:spec-changes`, `check:upgrade-guide` | `gen:spec-changes`, `gen:upgrade-guide` | +| A `SKILL.md` (frontmatter or body) | `check:skill-docs`, `check:skill-refs` | `gen:skill-docs`, `gen:skill-refs` | +| The react-blocks contract | `check:react-blocks` | `gen:react-blocks` | + +A `.describe()` string counts — it is not "just a comment", it lands in +`content/docs/references/`. Adding one export counts — it lands in `api-surface.json`. +Both were learned the hard way in #4040: two separate red builds, neither a logic error. + +Cheapest way to be sure, since a gate is just its generator in `--check` mode — run the +whole set and let it tell you which artifact is stale: + +```bash +cd packages/spec +pnpm build # REQUIRED first — see the dist caveat below +for c in check:docs check:api-surface check:authorable-surface check:spec-changes \ + check:upgrade-guide check:skill-refs check:skill-docs check:react-blocks; do + printf '%-28s ' "$c"; pnpm -s $c >/dev/null 2>&1 && echo PASS || echo FAIL +done +``` + +⚠️ **`check:api-surface` reads the built `dist/*.d.ts`, not `src/`.** A stale `dist` +makes it report exports as **removed** — "N breaking (removed/narrowed)" — when nothing +was removed at all: the snapshot is simply newer than your build. Rebuild before you +believe it, and before you file a bug about `main` being red. (Two phantom "breaking +removals" this way while writing this section.) + +`check:liveness`, `check:empty-state`, `check:skill-examples` and +`check:react-conformance` are pure checks with no generator — a failure there is a real +finding to fix, not an artifact to regenerate. + --- ## Context Routing — apply the right role per path From ef19a09afb610ea933f98568e7828ecb65e2b44d Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 30 Jul 2026 06:30:58 +0000 Subject: [PATCH 2/2] =?UTF-8?q?chore:=20add=20an=20empty=20changeset=20?= =?UTF-8?q?=E2=80=94=20this=20PR=20releases=20nothing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `Check Changeset` requires every PR to add a `.changeset/*.md` (diffed against the PR base, so the directory's existing entries can't mask a missing one). An empty-frontmatter changeset is the sanctioned "releases nothing" declaration, on par with the `skip-changeset` label, and there is ample precedent for docs-only changes (`adr-0104-design-doc-only.md` and others). Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01QoA8AV99Ss1RRkLLAYmDzq --- .changeset/agents-spec-generated-artifacts-map.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .changeset/agents-spec-generated-artifacts-map.md diff --git a/.changeset/agents-spec-generated-artifacts-map.md b/.changeset/agents-spec-generated-artifacts-map.md new file mode 100644 index 0000000000..7efef54016 --- /dev/null +++ b/.changeset/agents-spec-generated-artifacts-map.md @@ -0,0 +1,13 @@ +--- +--- + +Docs only — no package changes, nothing to release. + +AGENTS.md now maps each `packages/spec` change to the generated artifact it +invalidates and the CI gate that catches it. The eight gates live in two jobs that +run them sequentially, so the first stale artifact masks the rest — #4040 got one +red build per artifact (a `.describe()` string via `check:docs`, then five new +exports via `check:api-surface`) with no logic error involved either time. + +Also records the `check:api-surface` trap: it reads the built `dist/*.d.ts`, so a +stale `dist` reports exports as REMOVED when nothing was removed.