Skip to content

fix(cli): read BOM-prefixed JSON files for timeline plans, grades and motion specs - #6845

Merged
miguel-heygen merged 5 commits into
mainfrom
fix/json-file-bom
Oct 30, 2026
Merged

miguel-heygen merged 5 commits into
mainfrom
fix/json-file-bom

Conversation

@miguel-heygen

@miguel-heygen miguel-heygen commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

fails without the fix: reads an edit plan saved with a UTF-8 BOM in packages/cli/src/timeline/a2Commands.ids.test.ts (also the grades, motion spec, reads a --batch file saved with a UTF-8 BOM, reads a policy saved with a UTF-8 BOM and detects a JSON transcript saved with a UTF-8 BOM tests)

What

hyperframes timeline apply <plan> --plan refused a UTF-8 file with a BOM as "edit plan is not valid JSON", because it read the file as plain text and JSON.parse rejects the leading BOM. Windows editors and PowerShell write that BOM. jsonFlag.ts already decodes a BOM and UTF-16 for the JSON flags, so it now also exports the file and stdin readers, and the other places that read a user-supplied JSON file use them: the timeline apply plan and the timeline undo receipt file, the grade-compare grades file, the motion spec, the render --batch rows file (now through this one reader instead of the copy #6605 added), the lambda policy file and JSON transcripts (detectFormat, normalize). lambda render-batch and cloudrun JSONL batches already survive a BOM (trim() drops it), so they are left alone. Files the CLI writes itself (caches, state) are untouched.

What I measured

  • Five new tests (plan, grades, motion spec, policy, transcript), each red with the old read in its source file, green with the change; the batch case is covered by the test fix(cli): batch renders accept PowerShell JSON files #6605 added. 161/161 in the seven test files. oxfmt --check and oxlint clean.

What I did NOT execute

  • A real timeline apply run on a Windows-written file; the test writes the BOM bytes itself.
  • Hooks skipped on commit (no node_modules in the worktree); the checks above ran on a Linux box.

Size

Lone fix nothing can carry: one shared reader and six call sites with a test each (batch already tested); it is a lone fix nothing can carry into another PR.

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES · 1 blocker · 0 important · 0 nits · head fd836211

  • blocker: render --batch rows.json still reads its file raw, at packages/cli/src/commands/batchRender.ts:244 (options.readFile ?? ((path) => readFileSync(path, "utf8"))), so a BOM-saved batch file still fails. I ran parseBatchRows on a \uFEFF[{"title":"a"}] file read the same way, and it throws Invalid JSON in --batch: … Unexpected token '\uFEFF'. The PR body says "the other places that read a user-supplied JSON file use them", and this is one of those places. The fix is options.readFile ?? readJsonFileText plus a BOM row test next to the other three.
Scope

Read all 8 files. Grepped packages/cli/src for JSON.parse(readFileSync and readFileSync(…, "utf8"). The rest read files the CLI writes itself (caches, state, manifests) or HTML. Ran jsonFlag, motionSpec and batchRender tests locally: 40/40 pass. grade-compare and a2Commands need workspace builds that I didn't do. The fails without the fix: line is present.

@github-actions

github-actions Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 271 (base branch 271), smooth 112 of those

The gate passes.
Smoothness is reported in the artifact, not gated. A case fails only if it fails 2 of 3 runs.

Quarantined, measured but not gated (0)

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: APPROVE — 1 resolved, 0 open, 0 new · fd83621 → 61fd537. --batch now uses readJsonFileText; its BOM test and the policy test fail against main. CI green on this head.

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES — 0 open, 1 new · 61fd537 → a6aeb6d

  • blocker: CI › Fallow audit is red on this head in both runs. The one finding this PR introduces is fallow/unused-export on decodeJsonText (packages/cli/src/utils/jsonFlag.ts:11): batchRender.ts was its only importer, and the rebase moved it to readJsonFileText. Dropping the export (function decodeJsonText(bytes: Buffer): string {) clears the gate. Running npx [email protected] audit --base origin/main locally then gives ✓ No issues in 13 changed files; the other 8 findings are inherited and don't gate.

The rebased code is the same as the head I approved, apart from the batch reader.

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: APPROVE: 1 resolved, 0 open, 0 new · a6aeb6d → 0904ea6. Fallow is green, and I confirmed it locally. The stale exitBatchRenderInputError suppression is safe to drop; render/execute.ts:90 calls that export. CI is green on this head.

@miguel-heygen
miguel-heygen added this pull request to the merge queue Oct 30, 2026
Merged via the queue into main with commit 16e2e4c Oct 30, 2026
83 checks passed
@miguel-heygen
miguel-heygen deleted the fix/json-file-bom branch October 30, 2026 19:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant