Skip to content

Shooting Schedule & Day Out of Days#2

Open
newjordan wants to merge 3 commits into
wassermanproductions:masterfrom
newjordan:feat/shooting-schedule-dood
Open

Shooting Schedule & Day Out of Days#2
newjordan wants to merge 3 commits into
wassermanproductions:masterfrom
newjordan:feat/shooting-schedule-dood

Conversation

@newjordan

Copy link
Copy Markdown

Shooting Schedule & Day Out of Days

ScriptBreak's arc is breakdown → schedule → shoot, and the app already points at scheduling — the shot-list CSV is sold as "for StripBoard, or your 1st AD," the scene CSV as "the skeleton of a schedule" — but it stops at the breakdown and never delivers the schedule itself. This PR adds that missing step: a suggested shooting schedule (draft stripboard) and the standard cast Day Out of Days, the paperwork a 1st AD / line producer needs to take a breakdown to set.

It stays true to every project constraint: additive JS in the single src/index.htmlno build step, no dependencies, no network — and it's mirrored read-only in the MCP server so agents get it too.

What's in it

Desktop app (src/index.html) — a new Export → "Shooting Schedule & Day Out of Days" card with a pages/day control and four outputs:

  • Shooting Schedule (print/PDF + CSV): scenes grouped into synthetic shoot days by master location → lighting regime (DAY / dusk-dawn "MAGIC" / NIGHT) → INT vs EXT → scene number, then split under a page budget (default 5 pg/day, ±1 page tolerance; one location per day). Print view shows day headers, scene lists, cast IDs, and a shoot-day / pages / locations summary.
  • Day Out of Days (print/PDF + CSV): the cast × shoot-day grid with standard status codes SW / W / WF / SWF / H and per-cast Work / Hold / Total(span) counts, plus a code legend and cast key.
  • Both CSVs are added to the "Everything" zip, and there's a new Help entry.

MCP server (mcp/scriptbreak-mcp.mjs) — two new read-only tools, get_schedule and get_day_out_of_days, accepting pagesPerDay + the existing scope selectors and returning structured JSON plus a byte-identical csv and a caveat field. (9 → 11 tools.)

Honest by design

Cast presence in ScriptBreak comes from dialogue cues only, so a performer on set with no line in a scene isn't in sc.characters. A DOOD is entirely a cast-presence document, so this would under-report who's needed. Rather than hide that, every output — the print views, the zip README, the export-card copy, and the MCP caveat field — says so plainly: this is a draft starting point for your 1st AD, not a locked schedule; cast presence is dialogue-inferred, page counts may be estimated, and it doesn't model cast/location availability, company moves, or turnaround. Conventions follow standard AD practice (Movie-Magic-style grouping; standard DOOD SWF codes; all in-span non-work days shown as paid Hold, the conservative default).

Verification

  • The scheduling/DOOD helpers are duplicated verbatim between the app and the MCP; rendering both for the same project and diffing shows the schedule CSV is byte-identical. The DOOD algorithm was hand-checked against a multi-location day+night fixture (holds land where a performer's scenes straddle non-work days).
  • All executable <script> blocks in index.html pass node --check; the MCP passes node --check and a full stdio round-trip (11 tools; both new tools exercised).
  • Audited. An adversarial pass (independent review + edge-case tests) found no blockers and no high-severity issues; the DOOD status codes, Work/Hold/Total math, day-grouping hard rules, HTML escaping, and empty/malformed-input handling were all independently confirmed correct. A follow-up commit in this PR hardens the CSV exports — a spreadsheet formula-injection guard (=/+/-/@) and a leading "DRAFT — verify with your 1st AD" note row so the caveat travels with a detached file — and tightens the MCP's parity wording.

The two small unrelated bug fixes I found while building this are split into a separate PR so this one is purely the new feature; the two are independent and merge cleanly in any order.


🤖 Generated with Claude Code

https://claude.ai/code/session_01A2NtcuBy6SQmKaBQtgvkog

newjordan and others added 3 commits July 20, 2026 12:51
ScriptBreak's arc is breakdown → schedule → shoot, and the app already points
at scheduling (the shot-list CSV is "for StripBoard, or your 1st AD"; the scene
CSV is "the skeleton of a schedule") but never delivered it. This adds the
missing step, as an additive export in the single index.html — no build step,
no dependencies, no network.

- Suggested stripboard: scenes grouped into synthetic shoot days by master
  location -> lighting regime (DAY / dusk-dawn "MAGIC" / NIGHT) -> INT vs EXT
  -> scene number, then split under a page budget (default 5 pg/day, +/-1 pg
  tolerance; one location per day). Print/PDF view + CSV.
- Day Out of Days: the standard cast x shoot-day grid with SW / W / WF / SWF /
  H status codes and per-cast Work / Hold / Total(span) counts. Print/PDF + CSV.
- New "Shooting Schedule & Day Out of Days" card in Export (with a pages/day
  control), both CSVs added to the "Everything" zip bundle, and a Help entry.

Honest by design: cast presence is inferred from dialogue cues only, so
silent/background cast are not detected and the DOOD under-reports who is
needed; page counts may be estimated; and it does not model cast/location
availability, company moves, or turnaround. Every output carries a prominent
"draft — verify with your 1st AD" caveat. Conventions follow standard AD
practice (Movie Magic-style grouping; standard DOOD SWF codes).

Reuses exportScenes()/scopeLabel() (honors the scope bar), the openBreakdown-
Sheets() print pattern, csvCell()/download(), and makeZip(). The scheduling
helpers are duplicated verbatim in the MCP server (next commit) to preserve
app<->MCP output parity.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A2NtcuBy6SQmKaBQtgvkog
…f_days

Add two read-only tools to the headless MCP server so agents (Claude Code,
Codex, Hermes, …) get the same shooting schedule and Day Out of Days as the
desktop app:

- get_schedule — the suggested stripboard: ordered shoot days with location,
  I/E, day/night, scene numbers, page eighths, and cast IDs, plus a byte-
  identical `csv`.
- get_day_out_of_days — the cast DOOD grid (SW/W/WF/SWF/H codes, Work/Hold/
  Total counts) with a `legend`, plus a byte-identical `csv`.

Both accept `pagesPerDay` and the existing scope selectors, and return a
`caveat` field spelling out that cast presence is dialogue-inferred (so the
DOOD under-reports) and the schedule is a draft. The scheduling helpers are
copied verbatim from index.html; rendering both sides for the same project and
diffing confirms the schedule CSV is byte-identical between app and MCP.

Docs: bump the tool count to eleven and document the two tools + caveat in the
root README and mcp/README.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A2NtcuBy6SQmKaBQtgvkog
Follow-ups from an adversarial audit of the schedule/DOOD feature:

- CSV formula injection: csvCell now prefixes any cell beginning with = + - @
  (or tab/CR) with an apostrophe, so a location or character name like
  =HYPERLINK(...) / =1+1 / @sum(...) can't execute when the CSV is opened in
  Excel/Sheets/LibreOffice. Applied identically in the app and the MCP (which
  also makes the two csvCell copies textually identical), and it protects the
  pre-existing shotlist/scenes CSVs too.
- DOOD/schedule CSVs now carry a leading "DRAFT — …verify with your 1st AD"
  note row, so the caveat travels with the file once it's detached from the
  app (the payroll-relevant surface). Identical in app and MCP → CSV stays
  byte-for-byte across both.
- MCP get_schedule / get_day_out_of_days coerce pagesPerDay with Number() and
  fall back to 5 for non-positive/NaN input (a string previously made the day
  budget NaN and silently disabled day-splitting).
- Docs: scope the MCP "byte-for-byte" claim to all/scene/page scopes and state
  plainly that scope:"filter" reproduces the structured toggles only (not the
  app's live free-text search box) and that the generation-date header line is
  locale/day-dependent — the previous "any filter, byte-for-byte" was an
  overclaim.

Verified: app and MCP schedule/DOOD CSVs remain byte-identical (incl. the note
row and escaped injection payloads); pagesPerDay:"abc" -> 5; all app <script>
blocks and the MCP pass node --check; 11 tools intact.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A2NtcuBy6SQmKaBQtgvkog
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