Skip to content

Commit 7d70565

Browse files
authored
Merge pull request #67 from ChanMeng666/docs/testing-reference-sync
docs: add testing-system reference; sync all agent-facing docs to the shipped gates
2 parents 1252767 + 3d81b00 commit 7d70565

7 files changed

Lines changed: 503 additions & 68 deletions

File tree

.claude/commands/release-check.md

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,26 @@ you observed. Do NOT push anything — this command only verifies.
6262
a hard CI gate (`.github/workflows/ci.yml`) and it is separate from `npm run check`, which
6363
does **not** run it. It is the gate that catches a `src/manifest.ts` edit whose
6464
`docs/cli-reference.md` was never regenerated — the single most common way a release goes red.
65+
- `npm run typecheck:all` — the four workspaces typecheck too (CI's `builds` job).
6566
- `npm run docs:build` — the docs site still builds (the core suite does not compile it).
67+
- **Confirm the PR gates for the release commit are green on GitHub**
68+
`gh run list --branch main --limit 5` / `gh run view <id>`. `ci.yml` alone has five gating
69+
jobs and `codeql.yml` a sixth; a green local `npm run check` is a subset of them, not a
70+
substitute. What each job catches: `docs/testing.md` §1.
71+
72+
7. **The two artifacts that used to need a by-hand probe are now GATED — confirm the gate, don't
73+
redo the recipe.** Both live in CI's `builds` job; run them locally if it has not run yet:
74+
75+
```bash
76+
npm run build && npm run mcp:build:only
77+
node packages/mcp/scripts/check-dist-resources.mjs # every baked MCP resource == its repo source
78+
npm run vscode:build:only && npx vitest run editors/vscode # incl. the __CORE_VERSION__ bundle stamp
79+
npx vitest run packages/mcp/test/lockstep.test.ts # both server.json versions, mcpName, dep range
80+
```
81+
82+
A red `check-dist-resources` means rebuild (and `npm run gen:all` first if the repo artifact is
83+
itself stale). A red dep-range assertion is **expected on every core release** and is the
84+
intended prompt to bump the shim — see item 2.
6685

6786
## Reminders (do not act on these here — they are context for the push)
6887

@@ -74,41 +93,37 @@ you observed. Do NOT push anything — this command only verifies.
7493
management is human-with-interactive-2FA only.
7594
- **The VS Code extension bundles the core at build time.** A language-surface change (new
7695
token/keyword, grammar change, new quick-fix) means a Marketplace republish of
77-
`ChanMeng.archlang` — see `CONTRIBUTING.md#releasing`. Verify the `.vsix` by searching the built
78-
`editors/vscode/dist/server.js` for a new keyword/code, not by reading the version string.
79-
**Verify it by COUNT, with Node — a bare "no match" is not evidence.** Read the bundle and count
80-
occurrences of each new symbol, so a present symbol shows a number and an absent one shows `0`:
81-
82-
```bash
83-
node -e "const s=require('fs').readFileSync('editors/vscode/dist/server.js','utf8'); \
84-
for (const k of ['E_LEVEL_MIX','escalator']) console.log(k, s.split(k).length - 1)"
85-
```
86-
87-
This is immune to two ways a grep-style check lies about a build artifact: the bundle's line
88-
shape (esbuild's wrapping is not guaranteed, and a line-oriented matcher on a one-line bundle can
89-
read as a false negative), and regex metacharacters in the pattern — several of this language's
90-
surface strings contain `|`, `"`, or `-` (`dir up|down`, `"stair"`, `--level`), which a PowerShell
91-
`Select-String` will interpret as a regex unless you pass `-SimpleMatch`. A `0` count for a symbol
92-
the new core defines is the real failure signal; anything else means the rebundle took.
93-
*(2026-07-26, v1.21.0: `server.js` was 24,595 lines / 3,983 max line and `Select-String` did work —
94-
but the count is what proved it, and it costs nothing to be shape-independent.)*
96+
`ChanMeng.archlang` — see `CONTRIBUTING.md#releasing`. **"Did the rebundle take?" is now a test,
97+
not a by-hand probe:** esbuild stamps the resolved core version into `dist/server.js` as
98+
`__CORE_VERSION__` and `editors/vscode/test/stdio.test.ts` asserts it equals that version, over a
99+
real LSP round-trip against the built bundle. Confirm the gate — `npm run vscode:build:only &&
100+
npx vitest run editors/vscode` (CI's `builds` job runs exactly this) — rather than counting
101+
symbols in the artifact. The old count-with-Node recipe was replaced because a version stamp
102+
cannot be stale-but-plausible the way a hand-picked symbol list can: it fails for *every* core
103+
change, not only the ones somebody remembered to grep for.
104+
- Still true, and why the test spawns the bundle rather than reading it: never judge a build
105+
artifact with a line-oriented or regex matcher. esbuild's wrapping is not guaranteed, and
106+
several of this language's surface strings contain `|`, `"` or `-`, which PowerShell's
107+
`Select-String` treats as a regex unless you pass `-SimpleMatch`.
95108
- **The shim's handshake drift is FIXED** (0.2.3, 2026-07-26): `packages/mcp/src/server.ts` derives
96109
its `McpServer` version from `package.json` via `readShimVersion()`, mirroring the core's
97110
`readVersion()` in `src/cli/io.ts`, and a test pins the two together. Don't "fix" it again — and
98111
don't reintroduce a literal.
99112
- **Ask what the shim SHIPS, not just what its diff says.** Its `archlang://spec` / `context` /
100113
`grammar` resources are copied into the tarball at **pack time**
101114
(`packages/mcp/scripts/copy-resources.mjs`), so they freeze at the last publish while the `^1.x`
102-
dep range resolves to a current core. Nothing catches that: `check:drift` compares the *repo-root*
103-
artifacts, and `git diff <lasttag>..main -- packages/mcp` is empty. Published 0.2.2 handed hosts a
104-
**v1.19 GBNF grammar that could not decode** `arc`/`polygon`/`zone`/`level` at all. On any release
105-
that changed the language surface, unpack the published shim and **count** symbols:
106-
107-
```bash
108-
npm pack @chanmeng666/archlang-mcp@<published> && tar -xzf chanmeng666-archlang-mcp-*.tgz
109-
node -e "const s=require('fs').readFileSync('package/dist/archlang.gbnf','utf8'); \
110-
for (const k of ['arc','circle','polygon','zone','level','paper']) console.log(k, s.split(k).length-1)"
111-
```
112-
113-
A `0` for a keyword the current core defines means the shim is lying to hosts, and **only a version
114-
bump ships the fix** — that is a legitimate reason to spend one even when the diff is empty.
115+
dep range resolves to a current core. `check:drift` does not see it (it compares the *repo-root*
116+
artifacts) and `git diff <lasttag>..main -- packages/mcp` is empty. Published 0.2.2 handed hosts a
117+
**v1.19 GBNF grammar that could not decode** `arc`/`polygon`/`zone`/`level` at all.
118+
119+
**Two gates now cover this class, and item 7 above is how you confirm them** — the by-hand
120+
`npm pack` + symbol-count probe is retired:
121+
`packages/mcp/scripts/check-dist-resources.mjs` byte-compares every baked resource against its
122+
repo source (CI's `builds` job), and the dep-range assertion in
123+
`packages/mcp/test/lockstep.test.ts` is a **string** equality against `^` + the root version, so a
124+
core release reddens the shim on purpose until it is consciously re-pinned and rebuilt. Do not
125+
relax that to a semver-satisfies check to green a release.
126+
127+
What the gates cannot do is publish for you: **only a version bump ships the refreshed
128+
resources** — that is a legitimate reason to spend one even when the diff is empty — and the bump
129+
must land in BOTH `packages/mcp/package.json` and BOTH of `server.json`'s version fields.

.claude/commands/verify-loop.md

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,34 @@ scripts and report a pass/fail table.
2525
- If you touched the CLI, expect `docs/cli-reference.md` to move — it is generated from
2626
`src/manifest.ts`. **Read that diff**; it is the one artifact a CLI change always rewrites.
2727

28-
3. **If tests fail, fix the root cause.** Do not paper over a red suite.
29-
- Never run `vitest -u` or `UPDATE_GOLDENS=1 vitest run test/visual.test.ts` without first
30-
reviewing the diff and being able to justify **every changed byte**. `compile()` output is
31-
byte-for-byte stable and snapshot/golden-tested; an unexplained golden change is a real
32-
regression, not a snapshot to bless.
28+
3. **`npm run typecheck:all`** — REQUIRED whenever the change touched anything outside `src/` +
29+
`test/`; skippable (and worth skipping, it is slow) when it did not. Step 1's `typecheck` only
30+
covers `src`; this adds the root dev config (`test`, `eval`, `dataset`, `scripts`, `bench`) plus
31+
the playground, docs-site (vue-tsc), MCP shim and VS Code extension. CI runs it in the `builds`
32+
job.
33+
- A `TS2345 … | undefined` on a workspace file that `tsc -p <workspace>` calls clean means a
34+
ROOT test imported that module into the strict root program. Fix it in the shared module —
35+
never by relaxing the root option (AGENTS.md → Gotchas; `docs/testing.md` §4).
36+
37+
4. **Conditional gates — run the ones the diff earns:**
38+
- touched `docs/*.md` or `docs-site/`**`npm run docs:build`** (the core suite never compiles
39+
the site).
40+
- touched `playground/` ⇒ `npm run build && npm run playground:build:only && npm run
41+
e2e:playground`.
42+
- touched `docs-site/``npm run build && npm run docs:build:only && npm run e2e:docs`.
43+
- touched `packages/mcp``npm run mcp:build && node packages/mcp/scripts/check-dist-resources.mjs`.
44+
- touched `editors/vscode``npm run vscode:build:only && npx vitest run editors/vscode`
45+
(the stdio + bundle-freshness tests SKIP without a built bundle).
46+
47+
5. **If tests fail, fix the root cause.** Do not paper over a red suite.
48+
- Never run `vitest -u`, `UPDATE_GOLDENS=1 vitest run test/visual.test.ts` or
49+
`ASCII_UPDATE=1 vitest run test/ascii.test.ts` without first reviewing the diff and being able
50+
to justify **every changed byte**. `compile()` output is byte-for-byte stable and
51+
snapshot/golden-tested; an unexplained golden change is a real regression, not a snapshot to
52+
bless.
53+
- For any other red guard — a lockstep pin, a docs tripwire, an MCP gate — look up its row in
54+
**`docs/testing.md` §2** before touching it: each says whether the answer is *fix the source*,
55+
*regenerate*, or *consciously update the pin*.
3356

3457
## Report
3558

@@ -50,5 +73,10 @@ Finish with a pass/fail table:
5073
| drift: schemas/plan.schema.json | pass/fail |
5174
| drift: schemas/intent.schema.json | pass/fail |
5275

53-
Note: `docs:build` is a separate gate — the core suite does NOT compile the docs site, so a
54-
`docs/*.md` edit still needs `npm run docs:build` to catch a broken site build.
76+
Add a row for each conditional gate you ran (`typecheck:all`, `docs:build`, `e2e:playground`,
77+
`e2e:docs`, MCP dist resources, vscode bundle tests) and mark the ones the diff did not earn as
78+
`n/a — <reason>`. Never report a gate you skipped as `pass`.
79+
80+
Note: `npm run check` covers neither `check:drift` nor `typecheck:all` nor `docs:build` — the core
81+
suite does not compile the docs site or any workspace. Full map of what each gate catches, and the
82+
red-run response for every guard: `docs/testing.md`.

0 commit comments

Comments
 (0)