Progress is kept in memory while a show runs and written once, as a
complete report, when the operator finishes the run. The stored history
therefore never contains a partial run.
- Nothing writes on the cue path. triggerReportEntry only updates memory,
so the sidecar is untouched between the first event and finish.
- Removes the write coalescing added for the previous model: with a
single write per run there is nothing to debounce, so the timer, the
dirty flag, the flush export and the shutdown hook all go, and app.ts
returns to its previous state.
- ShowRun.endedAt is no longer nullable. A stored run is finished by
definition, so recovery of runs left open by a crash is gone along with
the concept, and the run list drops its ongoing state.
- Adds GET /report/runs/open for the editor indicator. /runs now means
finished reports only, which is also the contract Cloud sees.
- A run whose rundown was deleted before it finished now reports the
events that actually ran as its planned count, rather than zero.
Known gap: RestorePoint carries playback state only, so a crash mid show
loses the in progress report. The stored history is unaffected.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019nr3FbLbM8gB8Jm771YgTV
Review of the run history feature turned up four defects, all in the
code that feature introduced.
- Runs were dated with a time of day rather than a wall clock instant.
`clock` and `rundown.actualStart` are millis since midnight, so every
run in the history list rendered as 1 January 1970, and getLatestRun
ordered runs incorrectly across days: a run at 09:00 today sorted below
one at 20:00 last week, so the "last run" chip and /runs/latest could
return an older run. Runs now take `_startEpoch`, the instant the show
began, and the type documents the invariant.
- A stop arriving with no run open is ignored. Loading a project stops
playback and reinitialises reporting in the same tick, and the trailing
stop was attributing the previous project's event to the new one.
- Run summaries counted planned events from the loaded rundown rather
than the rundown the run belongs to, so switching rundowns mid-run gave
the summary a denominator from a different rundown. A run whose rundown
has since been deleted now keeps its last known count instead of
dropping to zero.
- Recovery of runs left open by a crash only closed the first one. Any
others stayed dangling forever: permanently shown as ongoing and never
eligible as the latest run.
Also replaces the raw ISO default run label with a readable local date
and time, and adds a batching upsertRuns to the store so recovery writes
the sidecar once rather than racing one write per run.
Each fix has a regression test, verified to fail without the change.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019nr3FbLbM8gB8Jm771YgTV
Turns the reporter from a live-only, single-run curiosity into a
persistent, per-project, per-rundown history of runs.
- Extend OntimeEventReport with a schedule snapshot (scheduledStart,
scheduledDuration) taken when an event starts, plus playCount. Reports
are now a record that survives later rundown edits, rather than a live
join against the current rundown.
- Add a run lifecycle: a run opens on the first event start and closes on
a full stop, archiving the previous run to history so the next start
begins fresh.
- Persist runs to a per-project sidecar file (services/report-service),
patterned on the existing restore-service, so a crash or restart no
longer loses the whole show's record. Runs are scoped by rundownId for
multi-rundown projects, cascade-deleted with their rundown or project,
renamed alongside a project rename, and deliberately not copied when a
project is duplicated.
- Extract the over/under/on-time variance and run summary maths shared by
the rundown chip, the report settings panel, and the server into
ontime-utils (getEventVariance, getRunSummary, countPlannedEvents).
- Extend the report API with run history endpoints (list, get, latest,
rename, delete) while keeping GET /report's existing shape so Companion
and HTTP automations are unaffected.
- Replace the settings report table with a run browser: a list of runs
with a rundown filter, inline rename, delete, and a detail view with
per-run summary stats and CSV export.
- Add a third, muted state to the rundown event chip: an event with
nothing in the current run yet previews how it went last time.
Fixes a real bug found while testing the new store: emptyStore() was a
shared object, so its runs array leaked mutations across project loads.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019nr3FbLbM8gB8Jm771YgTV
* fix: issue where a count-to-end would lead to incorrect expected times
* fix: include add time in overtime when countToEnd
* fix: ui and server use same calculation for expected end
Surface {{groupNow.*}} template variables (title, note, colour, times,
custom fields) in the automation template autocomplete so events inside a
group can reference their group. The runtime store already carries
groupNow, so substitution and filters worked already; this makes it
discoverable.
Extend the message-secondary action with an optional text field so an
automation can set the secondary message content, not just its source.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LZYPZVdZLWowU7DyzGkWyy
TypeScript 7 ships as a native Go binary and drastically trims the
package's public JS API surface (no more `main`, and `exports['.']`
now only resolves to lib/version.cjs) since the programmatic compiler
API isn't stable again until 7.1. This broke apps/resolver's tsdown
build, which used rolldown-plugin-dts' tsc-program mode (import ts
from 'typescript'; ts.createProgram(...)) for declaration generation.
Fix by switching that build to isolatedDeclarations, which lets
rolldown-plugin-dts generate .d.ts via its oxc-based path instead of
the TS compiler API entirely. That surfaced two isolatedDeclarations
violations in ontime-types (array/Object.keys initializers lacking
explicit annotations), fixed with explicit `string[]` types matching
their existing inferred type. Also bumped tsdown to pick up its latest
rolldown-plugin-dts, and disabled allowJs in tsconfig.dts.json since
it's incompatible with isolatedDeclarations.
Full workspace typecheck, lint, build, and test suite (1186 tests)
pass under TypeScript 7.0.2.
* refactor: allow secondary rundowns
* ui: move dropdown
* feat: follow loaded
* ui: background edit warning
ui: fix disable radio button
* feat(ui): add loaded sufix in the rundown list
* feat(ui): add direct link to background edit from rundown manager
* fix: better fallback
* fix: default to is isCurrentRundown for nav bar colour
* chore: rename navigate to cuesheet
---------
Co-authored-by: alex-arc <ac@omnivox.dk>
* feat: update auto cue numbering
* feat: renumber from ui
* refactor: patchEntries is not used
* chore: format
* fix: correct cue at top of group
* fix: handle precision
* refactor dialog
* bump limit for performance time test
* extract type
* add class name to lable
* fix rebase
* refator: extract renumering logic
* chore: comments for getIntegerAndFraction function
* chore: add the for renumber mutation
* fix: fraction match precision
* refactor: small cleanup
* refactor: use more narrow validator
---------
Co-authored-by: alex-Arc <omnivox@LAPTOP-RC5SNBVV.localdomain>
* fix: prevent add filter from submitting form
* refactor: event clarifies whether automations exist but are disabled
* refactor: improve readability of automation form
* refactor: add affordance for field warnings
* refactor: improve visibility of automation off state
* refactor: apply warning styles to other feature toggles
* Adding playback actions to automations (#2024)
* adding intial automation actions
* cleaning up
* fixing formatting
* ran oxfmt
* switching action names to playback- to match the dropdown strings
* fixing flicker that was caused by scroll arrows gettting unmounted
---------
Co-authored-by: Cameron Slipp <cdslipp@gmail.com>
* chore: migrate eslint to oxlint
* chore: migrate prettier to oxfmt
* chore: migrate typescript
* chore: toThrow should have a expected value
* chore: cast test value as Day
* chore: small title fix
* chore: mocks should be hoisted
* chore: incorrect async useage
* chore: test should be inside description
* chore: test sohuld include an expeced
* chore: oxfmt
---------
Co-authored-by: alex-Arc <omnivox@LAPTOP-RC5SNBVV.localdomain>
* feat: get server port from app satate or env
optional startup port from env will always override
function for parsing port from env
populate default port in app state
add test for migration
* bump version
* feat: main src in backstage view
* feat: main src in timeline view
* feat: main src in countdown view
* feat: main src in studio view
* feat: hide past events in countdown view
* notes can not be set as main src
* feat: show group title as secondary src
* chore: spelling
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
---------
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>