ursa.recovery¶
Recovery utilities — migration-grade code, not on the production read path.
This sub-package houses derivation helpers used by the one-off rebuild /
maintenance scripts under scripts/ and any future recovery tooling that
needs to compute catalog field values from raw R2 segment bytes rather than
catalog rows.
Production reads should not import from this module; the contract is
“best-effort derivation,” not “correct on every input.” Error handling
differs per submodule: :mod:ursa.recovery.timing parsers catch
exceptions internally (collected in ModalitySignals.errors), while
- mod:
ursa.recovery.first_epochprobes let read/parse failures raise — callers must catch them per row.
Package Contents¶
Classes¶
End-time candidates per signal source for one recording. |
Functions¶
Probe every modality worker under |
API¶
- class ursa.recovery.ModalitySignals[source]¶
End-time candidates per signal source for one recording.
Populated by :func:
derive_recording_end_time. Use- Meth:
max_endto collapse the modality candidates into a singleended_atvalue;Noneindicates no signal source produced a parseable result (the row is indeterminate).
- eeg: datetime.datetime | None¶
None
- camera: datetime.datetime | None¶
None
- mic: datetime.datetime | None¶
None
- screen: datetime.datetime | None¶
None
- samsungwatch: datetime.datetime | None¶
None
- environment: datetime.datetime | None¶
None
- worker_report: datetime.datetime | None¶
None
- errors: list[str]¶
‘field(…)’
- max_end() datetime.datetime | None[source]¶
Best
ended_atestimate, orNoneif no signal produced a candidate (the row is indeterminate).Prefers the latest data-stream end (
eeg/camera/mic/screen/samsungwatch/environment), each read from actual recorded sample timestamps.worker_report(stopped_at_utc) is wall-clock at worker process teardown, not the last sample — workers routinely linger hours (even into the next day) past the last data, so including it in the max inflated durations (e.g. a 5h session reported as 30h, or short single-modality sessions reported as a uniform ~8h once the recorder’s idle timeout fires). It is therefore used only as a fallback when no data-stream signal exists — i.e. for worker types that still lack a sample-timestamp probe (notes / pupillabs / keyboard / mouse / location / battery).
- ursa.recovery.derive_recording_end_time(store: ursa.store.ObjectStore, rec_id: str) ursa.recovery.timing.ModalitySignals[source]¶
Probe every modality worker under
recordings/<rec_id>/and return per-modality end-time candidates.- Func:
ModalitySignals.max_endcollapses them into a singleended_atvalue. A single broken segment file degrades only its own worker — the error is recorded inModalitySignals.errorsand the walk continues. Callers should logerrorsregardless of themax_end()outcome so future parser regressions don’t hide behind a successful sibling modality.