- GET /system/health splits processes into current instances (hosts with
a beat in the last 10 min, newest per host+kind, not stopped) and
retiredProcesses[]; 45s stale and level only consider current ones
- heartbeat writer marks stopped_at on graceful exit (migration 0043),
upsert clears it; pure api role now stops its writer on SIGTERM
- scheduled job system.heartbeat_cleanup (maintain, 1h) deletes rows
without a beat for 24h and samples older than 7 days
- status page: per-role alarms ("io worker 45 秒没有心跳"), collapsible
retired instances; glossary/runbook updated
- bump all members to 0.2.2, CHANGELOG [0.2.2]
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- /files/move|copy go through planImport's new `transfer` variant (keep names, directory
expanded to per-file plan) → organization_record + verifyAndImport/executeRecord: per-file
ledger resumable, fsproxy, cross-volume directory move = per-file copy→verify→delete then
remove empty source dirs; shared plan store + plan_stale; asset_location follows per file,
path_binding revised when a whole directory moved (finalizeTransfer); request waits up to
FILES_TRANSFER_WAIT_SEC, else executed.pending
- /files/organize per-item overrides take effect: season/episodes (domain planOrganize
overrides), contentUnitId coverage, targetDir (no binding), operation, slotId (satisfied
after verify); warnings only for inapplicable overrides
- delete/trash/restore write organization_record (action trash|delete|restore, file-level
results; migration 0026)
- GET /files/download (admin session, nfo/subtitle/image, size cap, streamed, audited)
- GET /files/records?ids|planIds for the organize page
- fs race errors map to 503/404/403/400 instead of 500
- runbook updated
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- subscription: status pending (TMDB not ready: searchable/evaluable, not completable),
last_searched_at / next_search_at
- content_unit (season): episode_total ledger with source / lock / timestamp
- acquisition_plan: unit_keys (Slot × unit reservation) and file_selection; drop the
one-in-flight-per-slot unique index (checked under slot row lock per unit instead)
- new tables slot_deferral, slot_unit (per-unit quality ledger), subscription_history
- contracts: SubscriptionParams, SubscriptionHistory, SlotDeferral, SlotUnit, SubscriptionProgress,
EpisodeTotalSet, CandidateEvaluation pri/trace/unitKeys and decision deferred;
endpoints subscriptions.search/progress/setEpisodeTotal and subscription-history
- mapping: evaluation messages via describeViolation, pri/trace passthrough
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- POST /organization-records: sourcePaths must resolve (realpath) under a
registered library_root or downloader path-mapping host path; `..` and
symlink escapes rejected (400), dryRun included. Move requires an admin
session, or an API key with an automation_grant covering the entity or a
matching one-time approval (consumed on use), else 403. Manual Move from a
managed download_task with unsatisfied H&R returns 409 and opens a
decision; never silently downgraded to Copy.
- Series slot completion: total episode count is unknown while units are
provisional, so the slot is not satisfied and the subscription keeps
tracking; coverage is registered per actual file (creating provisional
episode units), and already_in_library files count as verified presence.
- POST /engine/runs/{id}/retry (admin): re-enqueue by original task name and
raw input with idempotency key retry:<id>:<n>, audited; retry button on
the run detail page.
- E7 regular series e2e, E8 AT24 tag removal / task disappearance e2e.
- All workspace members and root set to version 0.1.0; CHANGELOG.md.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
New @umt/mapping (depends on domain + contracts only): download status + pause reason,
evidence level / media kind, identity resolution status, slot status / spec columns /
evaluation, ParsedRelease <-> source_release.parsed, SiteRelease <-> source_release,
PathBinding, OrganizePlan -> organization_record / file results / organize.plan output.
Tables are Record<union, ...> so adding a value on either side fails typecheck or tests.
Co-Authored-By: Claude Opus 5.5 <[email protected]>