Skip to content

Commit f2179fe

Browse files
committed
Add CI to auto-refresh the README highlighter bench
New workflow .github/workflows/readme-bench.yml regenerates the head-to-head block in README.md and commits it back to master whenever the grammar, bench, scope-roles, or issue-cases change (or on manual dispatch). - Deterministic: grades the adversarial bug-ledger (all in-repo) against a PINNED official grammar fetched from a vscode tag, so the block is byte-reproducible in CI. The parser-conformance corpus (a heavy, version-sensitive TS clone) is left out of the auto-block and kept as a hand-written balance note beside it. - No loop: the bot's README-only commit isn't in the trigger paths, and the commit carries [skip ci] as a backstop, so it can't re-trigger the workflow. - bench: --write-readme now respects --corpus; bench:readme is adversarial-only. The committed block was regenerated from the pinned grammar (vscode 1.96.0 — identical numbers to a local VS Code), so the first CI run is a no-op.
1 parent 3256136 commit f2179fe

4 files changed

Lines changed: 78 additions & 3 deletions

File tree

.github/workflows/readme-bench.yml

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: README bench
2+
3+
# Auto-refreshes the highlighter head-to-head block in README.md (between the
4+
# <!-- bench:start --> / <!-- bench:end --> markers) and commits it back to master.
5+
#
6+
# Determinism: the block is the ADVERSARIAL corpus only (the documented-bug ledger
7+
# in test/issue-cases.ts, all in-repo) graded against a PINNED official grammar
8+
# fetched below — so the same inputs always yield the same block. The
9+
# parser-conformance corpus (a heavy, version-sensitive TypeScript clone) is left
10+
# out on purpose; that axis lives in a hand-written note next to the block.
11+
#
12+
# No infinite loop: the bot commit touches only README.md, which is NOT in the
13+
# paths filter below, so it cannot re-trigger this workflow ([skip ci] is a backstop).
14+
15+
on:
16+
push:
17+
branches: [master]
18+
paths:
19+
- 'examples/typescript.tmLanguage.json'
20+
- 'test/highlight-bench.ts'
21+
- 'test/scope-roles.ts'
22+
- 'test/issue-cases.ts'
23+
- '.github/workflows/readme-bench.yml'
24+
workflow_dispatch:
25+
26+
permissions:
27+
contents: write
28+
29+
concurrency:
30+
group: readme-bench-${{ github.ref }}
31+
cancel-in-progress: true
32+
33+
env:
34+
# Pinned VS Code tag whose bundled TypeScript grammar is the "official" baseline.
35+
# Bump this deliberately to re-baseline against a newer official grammar.
36+
OFFICIAL_TM_TAG: '1.96.0'
37+
38+
jobs:
39+
update-readme:
40+
runs-on: ubuntu-latest
41+
steps:
42+
- uses: actions/checkout@v4
43+
44+
# Node 24+ runs the .ts sources directly (native type stripping) — no build, no tsx.
45+
- uses: actions/setup-node@v4
46+
with:
47+
node-version: 24
48+
49+
- run: npm ci
50+
51+
- name: Fetch pinned official TypeScript grammar
52+
run: |
53+
curl -fsSL \
54+
"https://raw.githubusercontent.com/microsoft/vscode/${OFFICIAL_TM_TAG}/extensions/typescript-basics/syntaxes/TypeScript.tmLanguage.json" \
55+
-o "${RUNNER_TEMP}/official-ts.tmLanguage.json"
56+
57+
- name: Regenerate the README bench block
58+
env:
59+
MONOGRAM_OFFICIAL_TM: ${{ runner.temp }}/official-ts.tmLanguage.json
60+
run: npm run bench:readme
61+
62+
- name: Commit the refreshed block (if it changed)
63+
run: |
64+
if git diff --quiet -- README.md; then
65+
echo "README bench block already current — nothing to commit."
66+
exit 0
67+
fi
68+
git config user.name "github-actions[bot]"
69+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
70+
git add README.md
71+
git commit -m "chore: refresh README highlighter bench results [skip ci]"
72+
git push

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,14 @@ Independently-verified **Monogram fixes** — official structurally wrong, Monog
7878
| corpus | Official | Monogram |
7979
|---|---|---|
8080
| documented bug ledger (534 tokens) | 83.5% | 94.2% |
81-
| TS parser conformance (15856 tokens) | 99.0% | 96.3% |
81+
82+
<sub>Parser-conformance row omitted — run with the TS corpus cloned to `/tmp/ts-repo` to include it.</sub>
8283

8384
<sub>Regenerate: `node test/highlight-bench.ts --write-readme`. Neutral oracle + frozen scope→role table: [`test/scope-roles.ts`](test/scope-roles.ts).</sub>
8485
<!-- bench:end -->
8586

87+
> **The other side of the ledger (honesty check).** On the *broad* TS parser-conformance corpus — not just the documented bugs — raw token-role accuracy flips: the official grammar's decade of hardening leads (~99% vs ~96%). Monogram's gap there is specific backlog (Unicode identifiers, qualified type names), **not** the ambiguity class above. Clone the TS corpus to `/tmp/ts-repo` and run `node test/highlight-bench.ts` to see both corpora.
88+
8689
## What you get
8790

8891
From one grammar definition (a small TypeScript combinator API), three outputs are **fully functional**:

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"test": "node test/sanity-check.ts",
88
"conformance": "node test/run-conformance.ts",
99
"bench": "node test/highlight-bench.ts",
10-
"bench:readme": "node test/highlight-bench.ts --write-readme"
10+
"bench:readme": "node test/highlight-bench.ts --corpus adversarial --write-readme"
1111
},
1212
"devDependencies": {
1313
"@types/node": "^25.9.1",

test/highlight-bench.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,7 @@ async function allTs(dir: string): Promise<string[]> {
647647

648648
// ── run selected corpora ──────────────────────────────────────────────────────
649649
const WRITE_README = argv.includes('--write-readme');
650-
const WHICH = WRITE_README ? 'both' : (getFlag('--corpus') ?? 'both');
650+
const WHICH = getFlag('--corpus') ?? 'both'; // --write-readme respects --corpus (CI uses adversarial = deterministic, no TS clone)
651651

652652
let parserSummary: BenchSummary | null = null;
653653
let advSummary: BenchSummary | null = null;

0 commit comments

Comments
 (0)