# Independent technical critic: wordmark outline finish

Review date: September 13, 2026. Scope: the sealed source-only kit, mapped core/SVG inputs, existing preparations and replays, and the documented commands. This is not a source-aesthetic review.

## Biggest reproducible gap

**P2 — An explicitly requested research check can disappear behind a successful exit.**

In `verify.py:143`, empty file bytes become `None`. In `verify.py:145`, the parsed value is tested for truthiness instead of checking whether `--critic` was supplied. Consequently, a zero-byte file, `{}`, and `[]` all bypass the requested input validation and source comparison. The same truthiness condition controls the expected measurement count at `verify.py:233`.

I ran the real documented verifier against the existing, nonempty two-identity build with each of those three invalid inputs. All three exited **0**, wrote `verification.json`, reported `mechanical-measurements-complete; fidelity-not-approved`, and produced only the 604 ordinary measurement rows. Both identities' `sourceComparison` and `upstreamComparison` remained `{"status":"not-run"}`. The zero-byte case produced a byte-identical verification report to the run with no research arguments at all.

This is an exit-status/request-handling defect, **not fabricated source measurements**: the nested report does say `not-run`. Nevertheless, a caller asking for the sealed-input check can receive success without that check occurring. `README.md:104` says `--critic` adds the source comparison and that omission of the arguments yields `not-run`. An explicitly supplied invalid file must fail, not behave like an omitted option.

**Countercheck:** a nonempty partial object containing only `reviewState: "ready-for-fresh-separate-review"` exited 1 with `KeyError: 'movies'`, before creating the requested proof directory. The guard exists, but falsey inputs never reach it. Running without either research argument exited 0 with both research comparisons explicitly `not-run`; that omission behavior is not a defect.

**Fix direction:** distinguish option absence from invalid file contents. When `--critic` is present, require nonempty bytes and a valid object with the required movie records before doing measurements or creating a completed report. Derive required comparison counts from requested options after validation, not from payload truthiness. Add CLI regression cases for empty bytes, `{}`, `[]`, and incomplete objects.

Status: **reproduced by one reviewer**. Two isolated refutation agents were unavailable; this does not satisfy that independent review gate and is not labeled “Confirmed.” No other source critics or findings were consulted.

### Minimal reproducer

Use the pinned environment described below. `$KIT` is the read-only code/document root; `$WORK` is the existing read-only artifact worker. `$CASE_OUT` must be a new directory inside the authorized review output. `$INVALID` is a tiny file in that output. These aliases replace private paths; literal arguments and output are retained in the private receipts.

```bash
printf '{}\n' > "$INVALID"
"$PYTHON_WITH_PILLOW" -B "$KIT/verify.py" \
  --work "$WORK" --code "$KIT" --out "$CASE_OUT" \
  --browser "$WORDMARK_BROWSER" --encoder-lock "$SHARED_ENCODER_LOCK" \
  --critic "$INVALID"
```

Actual: exit 0, completed ordinary proof, requested source comparison not run. Expected: nonzero exit and no completed proof. Repeat with `printf '[]\n'` or `: > "$INVALID"`, using a different new output directory for each run. No source movie is needed to reproduce the bypass.

| Input to `--critic` | Bytes | Exit | Requested source check |
| --- | ---: | ---: | --- |
| Argument omitted | — | 0 | Not run; permitted and uncredited |
| `{}` plus newline | 3 | 0 | Not run; defect |
| `[]` plus newline | 3 | 0 | Not run; defect |
| Empty file | 0 | 0 | Not run; defect |
| Object with `reviewState` only | 51 | 1 | Rejected; no completed proof |

## Executed scope

### Pinned prerequisites and schema

- The commands used Node **v24.13.1**, as required by the supplied core pins, not the shell's default v22.22.0.
- The direct full Chrome ELF was **Google Chrome for Testing 152.0.7977.42**. `run.mjs --action check` verified its bytes/version, the core files, the font, and installed package versions. That command does not launch a page or execute the font-fit gate.
- Packages checked: Remotion CLI/renderer/bundler/runtime **4.0.520**; React and React DOM **19.2.8**; React types **19.2.18**; React DOM types **19.2.7**; TypeScript **5.9.3**. Python was **3.14.7**, Pillow **12.3.0**.
- `WORDMARK_SHARED_NODE_MODULES` pointed to the supplied existing dependencies. The supplied Chrome runtime libraries and authorized `TMPDIR` were used. No dependency installation, copy, symlink, or browser download was performed.
- FFmpeg decoding used the supplied shared lock. A review-only `ffprobe` launcher used that same lock. Three initial verifier attempts stopped because that launcher initially named a nonexistent executable; those attempts receive no verification credit. The corrected launcher used the installed executable, and the affected commands were rerun.
- The recipe and SVG inventory use schema version **1**. The design input is the plain `WordmarkDesign` object in `CONTROLS.md:10`, not an object with an added `schemaVersion` field. Required: `family` in `compass`/`beacon`, and `word` matching `^O[a-z]{5}$`. Optional aspect/aperture bounds are `[0.94,1.06]` and `[0.90,1.08]`; paper is white; ink is opaque RGB with every channel at most 64.
- The additional live font-width requirement is Geist, weight 650, 170 px, 10 px letter spacing, complete word width at most **760.5 px**. The edited props' browser font-fit status remains **not-run**; structural validation is not credited as browser validation.

### Commands and actual outputs

All command arguments, return codes, and sanitized output excerpts are enumerated in `verdict.json`. Paths are aliases for the supplied read-only roots and the authorized writable review output.

| Check | Result and boundary |
| --- | --- |
| `node run.mjs --action check` with actual project, pins and browser | Exit 0; exact environment/core checks, not a browser render |
| `node run.mjs --action check-prepared` with existing SVG and prepared directories | Exit 0; 2 identities, 226 prepared states |
| `node --experimental-strip-types design.mjs` for both designs below | Both exit 0; complete `{recipe,content}` props; recipe unchanged |
| Same design command with eight invalid/partial designs | All exit 1; no props files produced |
| `run.mjs --action prepare` with empty and 113-record SVG indexes | Both exit 1 before creating output; no plate generation |
| `run.mjs --action check-prepared` with a full manifest but no PNGs | Exit 1; missing inventory rejected |
| `node --experimental-strip-types --test` with an attempted name filter | 34 tests executed, 34 passed; see the write-scope exception below |
| `test_verify.py` with four explicitly named read-only cases | 4 tests executed, 4 passed; its temporary-directory case was not run |
| `verify.py` without research arguments | Exit 0; 604 actual ordinary comparison rows; all research uncredited |
| `verify.py --critic` with the three falsey inputs | Each exit 0; the defect above |
| `verify.py --critic` with the truthy partial object | Exit 1 before output creation |

The independent table/asset audit checked all **226** Resolve clip rows, **302** native parameter rows, **302** clock rows, and **226** existing SVG states against the selected core. Each V1 clip list spans frames `[0,151)` without gaps: states 0–111 have one frame each and state 112 has 39. Text deletion counts, sampled transforms, pose slots, and five-surface painter order matched the supplied data. This is a data/command check, not execution of the Resolve instructions.

Both existing MP4s were probed and decoded by the documented verifier: 1920×1080, 151 frames, constant 60/1 cadence, zero audio streams. The 39-frame raw tail was identical within each identity. All **604** newly measured ordinary rows exactly matched the corresponding frozen ordinary rows. SVG preparation matched raw Remotion RGB exactly on **32/151** frames per identity, not all frames. Maximum RGB MAE was 0.11082947530864197 for the original and 0.11619164737654321 for the adaptation. These are implementation measurements, not moving-quality acceptance criteria.

### Two distinct edit fixtures

```json
{"family":"compass","word":"Oceans","lobeAspect":1.02,"apertureScale":0.98,"ink":"#102030"}
{"family":"beacon","word":"Otters","lobeAspect":0.94,"apertureScale":1.08,"ink":"#404040"}
```

Both produced 368 content keys, including 365 pose slots. Copy and ink matched the requests, and all 365 serialized pose slots differed from the corresponding frozen fixture. This count is a serialized-data observation, not a count of visually distinct surfaces; an empty beacon surface is not credited as visible geometry. Both complete recipe objects remained unchanged. Output SHA-256 identities are in `hashes.json`. Temporary props were hashed, parsed, and then removed; no edited-content deliverable is included.

The rejected designs were: missing word, missing family, empty object, array, null, null aspect, unsupported extra schema field, and invalid word syntax. New edited footage, new edited SVG inventories, and new plate preparations were not produced. The documented handoff into an existing Remotion application was not rendered or mounted here.

## Frozen provenance

The ZIP was streamed with `zipfile`; it was not extracted. **276** payload members matched their mapped read-only paths byte-for-byte: root kit files from the code/document root, and `build/` plus `svg/` from the artifact worker. The remaining member, generated `PACKAGE_CONTENTS.json`, independently matched all 276 payload byte counts and SHA-256 values. There were no duplicate members. Its absence as a root file on disk is not a defect.

| Asset | Identity |
| --- | --- |
| Source-only ZIP | 9,179,529 bytes; 277 members |
| ZIP SHA-256 | `e32fcefac92531b3b8eceb290883ecba56f54b2087f40bb32d7e3781eaf80bb0` |
| Original MP4 SHA-256 | `d3af7398007407149fe9e25d47b41306089498105958ca40910cfc845abfa5b0` |
| Adaptation MP4 SHA-256 | `62e44d4e381e9b1f3f793806288163a1dda45ff0994ad3c4ed23889421826e41` |

All 30 listed root `SHA256SUMS` entries matched. Before/after inventories checked **855 supplied files** across the two input roots, including byte hashes, sizes, modification times and modes. No supplied file changed. Separate critic/finding files were not interpreted; opaque hashing for the integrity inventory is not review evidence from those files.

The exact global storage guard passed before bulk work and again before sealing, with the requested 31,457,280-byte allowance and no trailing punctuation argument. A failing global guard would stop writes; the review-worker ceiling is not a substitute. No symlinks were used, including in negative fixtures. `verdict.json` records the final guard observation.

## Limitations and scope exception

- **Write-scope exception:** the attempted Node name filter did not exclude two tests. They created and removed temporary directories in the input worker. This violated the requested write boundary, although no existing sealed file was modified and all 855 files remained unchanged. The full 34-test result must not be described as a strictly read-only execution. The remaining explicit negative fixtures and command outputs were confined to the designated review worker.
- No valid `--stage` or valid source-research `--critic` run was performed. No research comparison is credited, including in the defective successful runs. Official source provenance was not independently re-researched.
- No native Resolve launch/import/export, moving-quality assessment, source-fidelity judgment, new render, dependency installation, deployment, or source edit was performed. External Resolve manuals and installed Resolve behavior were not verified.
- Live edited-copy font loading/width, React mounting, and edited output appearance were not tested. The guide requires those checks later; this report does not waive them.
- Independent refutation agents were unavailable. The report names an executed failure path and its local counterchecks, not an independent multi-reviewer certification.

Recommendation: fix the requested-check bypass before relying on the verifier as fail-closed. No production or native-tool clearance is given.
