flower
/
All briefs
idea draft note vodmanager
epic · VOD Manager — post-review roadmap (ambassador launch...

Generated clips are NOT the user's archive — separate free/ephemeral model (reframes clip quota)

Dispatch

canonical · plan

Spec

markdown

hand-off · dispatch

Dispatch

Auto-dispatch

when it reaches planned

Design-loop

design pass before build

Direct dispatch — no refine required. The packet tells the agent to ask questions only if the request is blocked by ambiguity.

kind

No dispatch requests yet — dispatch above to generate a copy-paste packet.

provenance · append-only

Trace

live
or paste a screenshot uploading…
  1. refinement 8h ago

    DONE (commit b7b91a0, held main) — independently re-verified (full suite 1977 pass / 1 skip, Pint clean). generated_clips table + GeneratedClip model + stream_highlights.generated_clip_id (legacy generated_clip_vod_id kept, unused). HighlightClipCutter reworked off the quota path entirely (dropped QuotaService/FreeTierLimits from the constructor; no VodArchivedEvent) → writes to the app-owned free bucket (StorageProfile::freeTier()), quota-exempt by construction, expires_at = now+7d, deterministic updateOrCreate on stream_highlight_id (reuse/replace on retry) + stale-object cleanup on kind change, graceful skip when free storage absent. Kept all generation guards. GeneratedClipController download/watch (ownership-scoped, presigned S3 redirect) + auth-gated routes. keepClip action (status=kept, clears expiry) via a shared Livewire concern. Highlight-card + replay UI: Available shows Watch/Download + "expires in N days" + Keep; Kept shows a badge, no expiry. vodmanager:purge-expired-generated-clips scheduled daily (deletes expired+available, never kept; nulls the highlight FK so it's re-clippable). Reviewed by hand: a clip can never evict a user's real VOD (quota-exempt), serving is ownership-scoped (403 foreign / 404 purged / login-redirect guest), and generated clips are invisible to the free-tier VOD count/purge accounting (separate table). REMAINING (the deferred "next conversation", NOT built): keep/publish SEMANTICS (Keep only clears the expiry today); social/vertical (9:16 + captions) export; whether kept clips ever move to the user's storage (and then count); per-account cap on concurrent ephemeral clips; retention_days tuning. PREREQ (confirmed): app-owned free bucket (FREE_STORAGE_*) is required to generate clips — same bucket as the free tier; tracked on deploy-readiness #146.

    agent · claude-code
  2. refinement 9h ago

    GREENLIT — implementation in progress (background agent). Confirmed shape: separate generated_clips table on app-owned free storage, quota-exempt, expires_at default 7 days (env VODMANAGER_GENERATED_CLIP_RETENTION_DAYS), auto-purge unless kept, "Keep" = clears expiry (publish/social/move-to-user-storage stay deferred). Includes reworking HighlightClipCutter off the quota path (keeps the single-pull/disk-preflight/clamp/min-size/is_clipable/idempotency guards), a serving route (presigned, ownership-scoped), highlight-card/replay UI (expiry countdown + Keep + download), and a daily purge command. PREREQUISITE SURFACED: because generated clips now live on the app-owned FREE bucket, that bucket (the same StorageProfile::freeTier() / FREE_STORAGE_* config that was previously an ambassador-only pre-deploy item) becomes a prerequisite for generated clips too — so clip prod-testing needs the free bucket configured. Generation degrades gracefully (skip + clear message) when it's absent, so nothing breaks, but no clips get produced without it. Ties back to deploy-readiness #146.

    agent · claude-code
  3. parent set 10h ago

    Grouped under epic #272.

    agent · claude-code
  4. note added 10h ago

    OPERATOR DIRECTION: the clips WE generate (auto-clip / highlight output) must NOT count against the user's account storage quota the way Twitch-derived VODs/clips do. They're product output, not the user's preservation archive. Store them as a COMPLETELY SEPARATE model/record, on FREE (app-owned) storage, ephemeral — auto-purge after N days UNLESS the user saves/publishes/keeps. (What keep/publish ultimately means — free-forever vs. move-to-user-storage-and-then-count vs. social export — is an explicit FOLLOW-UP conversation, not designed here.) THIS REFRAMES THE JUST-SHIPPED P0-2 (commit 7894c23). As shipped, HighlightClipCutter::reserveForClip routes a generated clip through the user's free-tier count eviction + QuotaService::tryToFit against their TwitchAccountStorage — so a generated clip (a) counts against the user's quota and (b) can EVICT their oldest real archived VODs to make room — and it lands in the user's own bucket (storage_profile_id = source's). That's the wrong model. The rest of the clip hardening (single-pull, disk preflight, idempotency, bound clamping, is_clipable, fan-out cap) is about GENERATING clips correctly and is unaffected — only the storage/quota model changes. NB: the eviction only triggers when the account is already at byte quota, so short-term testing on not-near-quota accounts is safe; fix before real at-quota users. PROPOSED MODEL (design; confirm before build): - New concept "generated clip" — a separate table/model (e.g. generated_clips), NOT a vods row (also resolves the review's type=highlight conflation of native-Twitch highlights vs our auto-clips). Fields ~ stream_highlight_id, owner twitch_account_id, source_vod_id, storage_path (app-owned free bucket), file_size_bytes, duration_seconds, kind (heuristic/refined), title/headline, status (available/kept/published/purged), expires_at, kept_at/published_at, timestamps. - Storage: app-owned free bucket (like the free-tier/ambassador storage) so it never touches the user's quota or storage. Quota-exempt by construction. - Lifecycle: created with expires_at = now + config('generated_clips.retention_days', e.g. 7). Daily command purges expired + status=available (not kept/published). "Keep"/"Publish" clears expiry / transitions status — semantics = the FOLLOW-UP conversation. - Playback/download/share: reuse the replay + download machinery pointed at the new model (some adaptation), or a lightweight clip-serving path. - Migration: decide whether to migrate existing type=highlight generated clips out of vods, or cut over new-only. CHANGE to the shipped code when built: drop reserveForClip's user-quota reservation for generated clips; store to app-owned free storage; write the generated_clips row instead of (or alongside) a vods row. The protected_vod_ids param added to tryToFit/evictIfAtCap becomes unused by clips (harmless — leave for other callers or remove). OPEN QUESTIONS (the "another conversation"): retention_days default; what keep/publish do; whether kept clips ever move to the user's storage (and then count); social/vertical export ties in here (deferred clip idea); per-account cap on concurrent ephemeral clips. Relates to clip track #151. Near-term: consider a small interim so generated clips can't evict a user's real VOD before any prod clip testing.

    agent · claude-code
  5. participant joined 10h ago
    system · claude-code

epic · dependencies

Relationships

depends on

No dependencies — dispatchable once planned.

agents · waves

Participants

  • claude-code participant · active

trace · graph

Links

No links yet — they accrue as agents work the brief.

scope

Projects

  • vodmanager · primary

dogfood · read-only

Agent’s-eye view

The literal recall_brief payload an agent gets — same service path as the MCP tool.