Skip to content

fix(cli): fail loudly on render job path collisions (#65)#68

Merged
jbrecht merged 2 commits into
mainfrom
fix-65-jobs-collision-guard
Jun 16, 2026
Merged

fix(cli): fail loudly on render job path collisions (#65)#68
jbrecht merged 2 commits into
mainfrom
fix-65-jobs-collision-guard

Conversation

@jbrecht

@jbrecht jbrecht commented Jun 16, 2026

Copy link
Copy Markdown
Owner

Closes #65. Defense-in-depth before cutting 0.13.0.

Correction from code review

The collision #65 describes cannot occur through the CLI today: validateTutorial enforces SLUG_RE (no dots in ids) and discoverTutorials rejects duplicate ids, so a tutorial named setup.es is rejected at discovery long before buildRenderJobs. The real protection is the slug rule.

So this PR is not a live corruption fix — it's a backstop plus a test that pins the actual protection.

What

  • buildRenderJobs throws a clear error if two jobs would resolve to the same work dir / output (jobPathKey mirrors the real .forge/<id><suffix> + <id><suffix>.mp4 derivation). A backstop for a future relaxed slug rule or a caller that skips validation — where the collision would be simultaneous corruption under --render-concurrency, not a benign overwrite.
  • The real first line of defense, now tested: a spec test asserting a dotted id (setup.es) is rejected by validateTutorial/SLUG_RE.
  • Guard comment + CHANGELOG reframed to say the slug rule prevents this; the guard is insurance.

Tests

spec.test.ts: dotted-id rejection (the production protection). render.test.ts: the backstop throws on validation-bypassing literals; legitimate combos don't. core 183 + cli 10 pass.

🤖 Generated with Claude Code

jbrecht and others added 2 commits June 15, 2026 22:37
buildRenderJobs now throws a clear error when two jobs resolve to the
same work dir / output — i.e. a tutorial id that coincides with another
tutorial's id+language suffix (e.g. `setup.es` source vs `setup` in es).
Pre-existing edge (a benign sequential overwrite before); the new
--render-concurrency makes it simultaneous corruption, so detect and
reject it up front rather than ship a latent corruption path with the
concurrency feature. Tests cover the collision + the legitimate case.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Code review on PR #68: the cross-tutorial id+suffix collision can't occur
through the CLI — validateTutorial's SLUG_RE forbids dots in ids and
discoverTutorials rejects duplicate ids, so the real protection is the
slug rule, not this guard.

- Reframe the guard's comment + CHANGELOG: it's defense-in-depth (guards
  a future relaxed slug rule / a caller that skips validation), not a
  live corruption fix.
- Add a spec test pinning that a dotted id (`setup.es`) is rejected at
  validation — the actual first line of defense for #65.
- Note in the guard's own test that its literals deliberately bypass
  validation to exercise the backstop directly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jbrecht jbrecht merged commit 339bf4d into main Jun 16, 2026
1 check passed
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.

workDir/output collision when a tutorial id equals another id + lang suffix

1 participant