Add JABS Hub-backed projects client integration plan - #418
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new design/implementation plan document describing how jabs-behavior-classifier will integrate JABS Hub-backed projects as an offline-capable caching client (media + pose + annotations + metadata synced from Hub; derived artifacts remain local).
Changes:
- Introduces a comprehensive client-side architecture + phased delivery plan (auth, Hub client, cache/media resolver, annotation store + sync engine).
- Defines client/Hubs contract expectations (API surfaces, manifests, optimistic concurrency, conflict UX, optional
numFrameshandling). - Records client-relevant decisions, risks/mitigations, and test strategy for the planned work.
Suppressed comments (1)
docs/development/plans/jabs-hub-backed-projects-plan.md:746
- In Appendix A.3, the
video_manager.pyline reference forget_videosappears to be off by one (def get_videosis currently at line 154). Updating this keeps the reference consistent with the earlier section.
- Settings/manifest: `settings_manager.py`; video enumeration `video_manager.py:153`.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| order: local cache → Hub feature cache → compute (optionally upload). Does not change the MVP | ||
| "recompute locally" default. | ||
| - **Project sharing + role-based permissions** — membership beyond the owner (D19), then a role model | ||
| (viewer / labeler / owner, potentially per-video or per-behavior) that the client honors via a |
There was a problem hiding this comment.
This is currently named VIEWER / EDITOR / ADMIN in the propsed JABS-hub ADR.
| D19 projects are **personal (owner-only)** in the first cut, so the MVP membership set is normally | ||
| one user — but the check is a membership check from day one, so sharing is an added row, not a | ||
| redesign. | ||
| - **Membership gates projects, not the video library.** A library video exists before and |
There was a problem hiding this comment.
As currently written, ADR-0014 Decision 6 makes library access the union of video visibility and membership in any containing study or project. So project membership now does grant library access to that project's videos.
| redesign. | ||
| - **Membership gates projects, not the video library.** A library video exists before and | ||
| independently of any project (ADR-0012), so project membership is not a well-defined question for | ||
| library media: **ADR-0014 Decision 3 makes the library readable *and writable* by any authenticated |
There was a problem hiding this comment.
Reads still effectively open under the LAB default and creating a video is unaffected, but writes to an existing video now need owner or study/project membership.
| - **Group-scoped library visibility — out of scope for the MVP, but a known future requirement, not a | ||
| hypothetical.** Library videos will eventually need to be readable only to specified groups | ||
| (collaborator data, embargoed studies), so the lab-wide catalogue above is a starting posture rather | ||
| than the end state. Enforcement is Hub-side (ADR-0014 Decision 3 today, its OQ2 for the ACL model); |
There was a problem hiding this comment.
The ACL model now has a concrete shape (visibility, owner_subject).
| only to specified groups — see §2.5. Client-side work when it lands: honor a visibility field on the | ||
| library listing and the project manifest, present "no longer accessible" states for cached media | ||
| whose access was withdrawn, and keep every library browse path behind a filtered query rather than a | ||
| full scan. Sequenced after Hub decides where group membership lives (ADR-0014 OQ1/OQ2), which is the |
There was a problem hiding this comment.
OQ2 is now OQ3 and OQ1 is resolved.
|
|
||
| - **Library + media:** `GET /videos` (list/search), `POST /videos` + `.../video-upload-url` / | ||
| `.../pose-upload-url` / `.../upload-complete` (upload), `GET /videos/{id}/video-url` / | ||
| `.../pose-url` (signed download). Media is content-addressed; **exact pose bytes preserved**. |
There was a problem hiding this comment.
This is true only for the upload path.
A pipeline's output prefix is write-once and keyed by run_id on purpose (ADR-0010 DAG-8), so a re-run never overwrites a prior result.
| `jabs/hub-conflicts/<video>-<version>-<timestamp>.json` in the cache, so a discarded edit is | ||
| always recoverable from disk (and re-importable via `VideoLabels.load`). | ||
| - **Notify, don't interrupt.** Resolution surfaces as a non-modal status-bar / sync-indicator | ||
| message — "Labels for `<video>` were also changed by `<user>`; your version was kept, theirs saved |
There was a problem hiding this comment.
A Hub change since this was written adds a second reason for 409.
If someone unlinks and relinks a video in the web UI the old association's annotations are dropped and a new, empty one replaces it (spec 0006 §7.3). A client holding queued offline edits for that video then pushes against an association that has no annotations. It follows the new association because sync state is keyed by video name and resolved to a projectVideoId from the manifest.
Hub used to accept that push silently as version 1. It now returns 409.
The client already writes the rejected edit to hub-conflicts/ and reports it without interrupting the user, so the handling itself needs no change. Only the message needs a second case.
Perhaps:
"Labels for
<video>no longer exist on Hub (the video was re-linked); your version was saved to …"
Adds the client-side design/plan for JABS Hub-backed projects: the desktop GUI
(
jabs-behavior-classifier) becomes a caching client for cloud projects, with video, pose,annotations, and project metadata stored in JABS Hub and cached locally for frame-accurate labeling,
feature extraction, training, and offline work.
Design doc only — no code, no dependency changes. The document is
docs/development/plans/jabs-hub-backed-projects-plan.md.Companion Hub work
docs/specs/0006-jabs-project-backend-design.mdinTheJacksonLaboratory/jabs-hub(merged, #59)Proposed, under review.The REST API (spec §7), the data model (spec §5), and the annotation-document schema (Appendix A.1)
are the shared contract between the two repos.
Two sections track decisions that are not yet ratified, so expect them to move:
numFramesfollows ADR-0012 Decision 3What reviewers are asked to decide
Eleven decisions are already Confirmed. These seven are Recommended (pending confirm) — this
is the actual ask:
VideoLabels.mergereserved for a later 3-way merge(identity, behavior)is post-MVP (shared; Hub owns storage)project.jsonsplits into shared (synced to Hub) vs local/GUI keyspackages/jabs-hub-client(importjabs.hub), depending onjabs-coreonlyjabs-cli)jabs/hub-conflicts/Where to look
§8 (Decisions) is the fast path — it is the whole design in one table. Beyond that:
network or auth, lazy-imported Hub client, local workflows untouched. The section most likely to
matter if you do not use Hub.
video_path,save_annotations,ProjectPaths), withfile:linereferencesChanged since the 2026-07-30 approval
+165 / −26. @keithshep's approval predates all of it, so a re-review is warranted. Addressed from
that review:
lines had only one space), and a
;inside a sequence-diagram message split the statementAlso added since: the library's lab-wide read/write posture plus group-scoped visibility recorded as
a known future requirement (§2.5, §10), and
numFramesmarked optional in the §5 contract with aprobe-on-first-open fallback (§4.6).