Skip to content

Commit 58902b2

Browse files
Merge pull request #60 from gridaco/chore/consolidation-scoreboard-v0
feat(consolidation): add sealed scoreboard v0
2 parents cdba65c + c4a001d commit 58902b2

51 files changed

Lines changed: 4173 additions & 95 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/consolidation-gates.yml

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,69 @@ jobs:
305305
if: steps.gate.outcome == 'failure'
306306
run: exit 1
307307

308+
scoreboard_shape:
309+
name: scoreboard v0 shape
310+
needs: scope
311+
if: needs.scope.outputs.engine == 'true'
312+
runs-on: ubuntu-24.04
313+
timeout-minutes: 30
314+
env:
315+
FORCE_SKIA_BINARIES_DOWNLOAD: "1"
316+
steps:
317+
- name: Checkout head revision
318+
uses: actions/checkout@v4
319+
with:
320+
ref: ${{ needs.scope.outputs.head }}
321+
322+
- name: Free up disk space
323+
run: |
324+
sudo rm -rf /usr/share/dotnet
325+
sudo rm -rf /usr/local/lib/android
326+
sudo rm -rf /opt/ghc
327+
sudo rm -rf /opt/hostedtoolcache/CodeQL
328+
sudo docker image prune --all --force
329+
330+
- name: Install system dependencies
331+
run: |
332+
sudo apt-get update
333+
sudo apt-get install -y \
334+
libexpat1-dev \
335+
libfontconfig1-dev \
336+
libfreetype6-dev \
337+
libgl1-mesa-dev \
338+
libgles2-mesa-dev \
339+
libwayland-dev \
340+
libx11-dev \
341+
libx11-xcb-dev \
342+
libxcb-render0-dev \
343+
libxcb-shape0-dev \
344+
libxcb-xfixes0-dev \
345+
libxcursor-dev \
346+
libxi-dev \
347+
libxinerama-dev \
348+
libxrandr-dev \
349+
libxxf86vm-dev \
350+
mesa-common-dev
351+
352+
- name: Setup Rust toolchain
353+
uses: dtolnay/rust-toolchain@stable
354+
with:
355+
toolchain: 1.92.0
356+
357+
- name: Cache cargo build outputs
358+
uses: Swatinem/rust-cache@v2
359+
with:
360+
shared-key: consolidation-scoreboard-v0
361+
cache-all-crates: true
362+
cache-workspace-crates: true
363+
cache-on-failure: true
364+
365+
- name: Run scoreboard synthetic tests
366+
run: cargo test --locked -p grida_dev scoreboard
367+
368+
- name: Validate the scoreboard corpus and renderer preflight
369+
run: cargo run --locked --profile test -p grida_dev -- scoreboard check
370+
308371
armed:
309372
name: armed
310373
needs:
@@ -313,6 +376,7 @@ jobs:
313376
- seam_architecture
314377
- legacy_pixel_sweep
315378
- n0_gate
379+
- scoreboard_shape
316380
if: always()
317381
runs-on: ubuntu-24.04
318382
steps:
@@ -323,14 +387,16 @@ jobs:
323387
SEAM_RESULT: ${{ needs.seam_architecture.result }}
324388
PIXEL_RESULT: ${{ needs.legacy_pixel_sweep.result }}
325389
N0_RESULT: ${{ needs.n0_gate.result }}
390+
SCOREBOARD_RESULT: ${{ needs.scoreboard_shape.result }}
326391
run: |
327392
if [[ "$LOCK_RESULT" != success ]]; then
328393
exit 1
329394
fi
330395
if [[ "$ENGINE_SCOPE" == true ]] && \
331396
[[ "$SEAM_RESULT" != success || \
332397
"$PIXEL_RESULT" != success || \
333-
"$N0_RESULT" != success ]]; then
398+
"$N0_RESULT" != success || \
399+
"$SCOREBOARD_RESULT" != success ]]; then
334400
exit 1
335401
fi
336402
echo "All applicable consolidation gates passed."

Cargo.lock

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/grida_dev/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ grida = { path = "../grida", features = [
1313
"native-clock-tick",
1414
"native-gl-context",
1515
] }
16+
n0 = { path = "../n0" }
1617
fonts = { path = "../fonts", features = ["webfonts"] }
1718
math2 = { path = "../math2" }
1819
anyhow = "1.0"
@@ -37,6 +38,9 @@ skia-safe = { version = "0.93.1", features = [
3738
] }
3839
serde_json = "1.0"
3940
serde = { version = "1.0", features = ["derive"] }
41+
sha2 = "0.10"
42+
quick-xml = "0.37"
43+
tempfile = "3"
4044
image = { version = "0.25", default-features = false, features = [
4145
"png",
4246
"jpeg",

crates/grida_dev/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ cargo run -p grida_dev -- https://example.com/scene.grida
2626
Supported formats: `.grida`, `.grida1` (JSON), `.svg`, `.png`, `.jpg`, `.jpeg`, `.webp`.
2727
Multi-scene files support **PageUp/PageDown** pagination. Drop new files at any time to replace the scene.
2828

29+
### Consolidation scoreboard
30+
31+
The `scoreboard` subcommand validates and, once owner-authorized, measures the
32+
legacy engine and the chassis against a declared oracle. Its corpus, sealed
33+
pre-ratification posture, report contract, and bless flow are documented in
34+
[`SCOREBOARD.md`](./SCOREBOARD.md).
35+
2936
### Headless GPU Benchmark
3037

3138
The `bench` subcommand runs a headless GPU benchmark (no window) and prints per-frame timing stats. Use it to measure rendering performance reliably.

crates/grida_dev/SCOREBOARD.md

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# Consolidation scoreboard
2+
3+
`grida_dev scoreboard` is the consolidation program's comparison instrument.
4+
It measures the legacy engine and the chassis against the same declared oracle
5+
and against each other. The legacy engine is context, never the oracle.
6+
7+
The instrument is present but scoring is not yet authorized. Registry decision
8+
FLIP remains open in
9+
[gridaco/nothing#49](https://github.com/gridaco/nothing/issues/49), and the
10+
[decision proposal](../../docs/wg/consolidation/flip-rule.md) is explicitly
11+
unratified. Until the owner records GO and that proposal carries a ratification
12+
record, `scoreboard run` refuses before corpus validation or either renderer is
13+
called. The committed Chromium images are oracle inputs, not scores.
14+
15+
## Corpus contract
16+
17+
Scoreboard v0 uses the closed
18+
[`svg-rect-path-v0` corpus](../../fixtures/scoreboard/svg-rect-path-v0/corpus.json).
19+
Its manifest fixes the ordered denominator, source digests, 128×128 viewport,
20+
oracle paths, and an explicit excluded-family patrol ledger. Each included row
21+
sends the identical checked-in SVG bytes to the legacy SVG entry point, the
22+
chassis's bounded authored-Base entry point, and Chromium. No model bridge or
23+
oracle-only source rewrite is permitted.
24+
25+
The corpus is intentionally limited to the direct static rectangle/path
26+
intersection already accepted by both engine entry points. Unsupported source
27+
families remain visible in the exclusion ledger. `scoreboard check` requires
28+
both entry points to accept every row in this fixed v0 corpus. During an
29+
authorized report run, the same preflight is retained as per-engine evidence:
30+
an entry-point rejection becomes `UNSUPPORTED` without calling that renderer,
31+
while a failure after an accepted preflight remains an error. A later admitted
32+
row therefore stays in the denominator with an explicit disposition rather
33+
than being silently removed or classified by matching diagnostic text.
34+
35+
## Commands
36+
37+
Run commands from the repository root.
38+
39+
```sh
40+
# Validate the closed corpus, source/oracle hashes, bake provenance, and both
41+
# parser entry points. This performs no rasterization or image comparison.
42+
cargo run -p grida_dev -- scoreboard check
43+
44+
# Deliberately sealed until FLIP is ratified on gridaco/nothing#49.
45+
cargo run -p grida_dev -- scoreboard run
46+
47+
# Derive a fresh review candidate from an authorized, complete report.
48+
# This never overwrites the committed baseline.
49+
cargo run -p grida_dev -- scoreboard bless
50+
```
51+
52+
The shared path options are `--corpus`, `--report`, and `--baseline` where
53+
applicable. `bless` also accepts `--candidate`. Defaults are:
54+
55+
| Artifact | Default |
56+
| ------------------ | ------------------------------------------------------- |
57+
| Corpus | `fixtures/scoreboard/svg-rect-path-v0/corpus.json` |
58+
| Report | `target/scoreboard/report-v0.json` |
59+
| Baseline | `fixtures/scoreboard/svg-rect-path-v0/baseline-v0.json` |
60+
| Baseline candidate | `target/scoreboard/baseline-v0.candidate.json` |
61+
| Hard run budget | 120 seconds |
62+
63+
The baseline is intentionally absent before the first authorized score. The
64+
ratified active configuration must declare that absence explicitly; after the
65+
first baseline lands, it pins the required baseline digest. A missing or
66+
mistyped path therefore cannot silently disable regression checks. The
67+
120-second budget is part of the proposed rule identity and has no command-line
68+
override. The timer starts before corpus, oracle, parser, renderer, comparator,
69+
and prior-baseline validation. Those stages run behind a terminal-command
70+
watchdog that returns at the deadline even if an in-process stage is blocked.
71+
The worker has no report path; only a complete in-budget result returns to the
72+
caller that may publish the create-new report.
73+
74+
## Chromium bake
75+
76+
The checked-in Chromium PNGs are produced by
77+
[`scoreboard_bake_chromium.ts`](./scripts/scoreboard_bake_chromium.ts). The
78+
script verifies each source digest, transports that exact hashed buffer to a
79+
JavaScript-disabled, network-disabled browser context without DOM mutation,
80+
style injection, or animation control, captures it twice, and requires
81+
byte-identical PNG output. Repository inputs and output parents must contain no
82+
symlink components. It records the Chromium version, corpus digest,
83+
script digest, capture policy, and per-row oracle digests in
84+
[`oracle-bake.json`](../../fixtures/scoreboard/svg-rect-path-v0/oracle-bake.json).
85+
86+
The bake command is create-new-only. Its default outputs must not already
87+
exist; a re-bake never replaces the committed oracle in place. Prepare a fresh
88+
corpus candidate that preserves the ordered row/source identities but declares
89+
fresh repository-relative `oracle_bake` and per-row `oracle` paths, then pass
90+
all three matching paths:
91+
92+
```sh
93+
pnpm --filter @grida/reftest exec tsx \
94+
../../crates/grida_dev/scripts/scoreboard_bake_chromium.ts \
95+
--corpus target/scoreboard/oracle-candidate/corpus.json \
96+
--out target/scoreboard/oracle-candidate/chromium \
97+
--bake-manifest target/scoreboard/oracle-candidate/oracle-bake.json
98+
```
99+
100+
## Report and baseline laws
101+
102+
An authorized report records exact corpus, oracle-bake, scoring-method, rule,
103+
and run identities. Every included row has one tagged cell for each engine and
104+
all three comparisons: legacy-vs-oracle, chassis-vs-oracle, and
105+
legacy-vs-chassis. Comparison cells carry integer differing/scoring-pixel
106+
counts or a reasoned unavailable state. Coverage obeys
107+
`included = scored + unsupported + error` for each engine.
108+
109+
The baseline is a deterministic projection of a valid report. It excludes
110+
host, timestamp, output paths, prior-baseline pointer, and other run-local
111+
data. Baseline candidates are direct create-new files under
112+
`target/scoreboard/`; symlinked directory components are refused, and a
113+
candidate cannot be written directly to the committed baseline path. Blessing
114+
fails closed
115+
for an unratified rule, identity mismatch, incomplete coverage, missing
116+
comparison triple, invalid provenance, or an over-budget run. A scored row
117+
becoming unsupported/error, or an engine-to-oracle differing-pixel count
118+
increasing, is a regression; aggregates cannot hide it.
119+
120+
The threshold and eligibility laws belong to the owner-gated WG decision, not
121+
to the report or bless command. See the consolidation
122+
[method](../../docs/wg/consolidation/method.md) for the full gate lifecycle.
123+
124+
## CI posture
125+
126+
The consolidation workflow runs the synthetic scoreboard contract tests and
127+
`scoreboard check` when engine scope changes. It does not invoke
128+
`scoreboard run` while FLIP is unratified. Once the owner records GO, enabling
129+
the real run and committing the first baseline are a separate consolidation
130+
step with their own gate evidence.

0 commit comments

Comments
 (0)