Skip to content

id: media.* — typed media artifacts by default, one bounded raw stream for realtime (#2027) #2342

Open

Description

@dezren39

Follow-up from the capability taxonomy v0 investigation (#2027, record: doc/2026-10-29T14-05-00Z_investigation_capability_taxonomy/, PR #2337).

Goal

media.* with typed artifacts as the default and exactly one raw channel: media.image/media.audio/media.video returning artifact references, and media.stream for realtime only.

Scope

  • Artifact reference {artifact_id, mime, bytes, sha256, width/height or duration_ms, created_at}; read back by id, bounded, deduplicable, replayable from the journal.
  • Decision needed (taxonomy §9.3): artifact storage beside records — artifacts want dedupe and GC, records.read has neither. Propose the shape in the issue before implementing.
  • media.stream: subscription of frames each ≤ MAX_EVENT_BYTES, explicit end, backpressure signal; never the permanent record — it ends in an artifact or is discarded.
  • Refusals: unknown_cap+device_lacks_affordance (no storage/hardware), outside_ceiling (slow link), bad_args+oversize, cap_denied+consent_required for capture.

Acceptance

  • Typed artifact produced and read back by id with digest verified; oversize refused.
  • A stream test asserting the 64 KiB frame ceiling and clean termination into an artifact.
  • Media surface renders artifact refs only — bytes never travel in a surface.

Out of scope

Transcoding, thumbnails, CDN delivery, inline playback.

Acceptance criteria

  • The artifact-storage decision (taxonomy §9.3 — beside records, which has neither dedupe nor GC) is proposed on this issue before implementation
  • A typed artifact (media.image/audio/video) is produced and read back by id ({artifact_id, mime, bytes, sha256, dimensions/duration, created_at}) with digest verified; oversize refused (bad_args + oversize)
  • A stream test asserts the MAX_EVENT_BYTES (64 KiB) frame ceiling, backpressure/end signalling, and clean termination into an artifact (or discard) — the stream is never the permanent record
  • The Media surface renders artifact refs only; bytes never travel in a surface; capture refusals use the documented vocabulary (unknown_cap/device_lacks_affordance, outside_ceiling, cap_denied/consent_required)

Activity

  1. added
    kind/featureNew feature or capability request
    app/idPackage/app: id (pkgs/ or apps/ in this repo)
    on Oct 29, 2026
  2. developing-today commented on Oct 29, 2026

    @developing-today
    Contributor
  3. added
    priority/normalOrdinary priority (the default)
    effort/lLarge: multi-day or open-ended; expect staged check-ins
    meta/enrichedIntake review done: acceptance criteria, links, and normalized labels added
    on Oct 29, 2026
  4. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    Intake review

    Related: parent investigation #2027 (record: PR #2337); siblings #2338-#2345 are the other taxonomy follow-ups

    Notes: Filed 2026-10-29T14:04Z from #2027. Still live: no open or merged PR implements it. #2344 (speech.capture) reuses this issue's stream ceiling and consent rules.

    Risks: Building storage before the §9.3 decision lands risks a second media store to migrate; the decision is an explicit acceptance gate here.

    Suggested approach: Post the storage-shape proposal on the issue first; implement artifacts, then the single raw stream.

    🤖 Agent note · filed

    • Agent: fleet monitor (repo-fleet-monitor)
    • Session / ID: repo-fleet-monitor run 2026-10-29T14:30Z (09:30 CDT)
    • Found via: monitor reconciliation
    • Task: Duty 2 intake enrichment — acceptance criteria appended (original body preserved verbatim above it), labels normalized, meta/enriched applied. Still-live check this pass: no merged PR or fix commit explicitly resolving this issue was found; where a queue triage task owns verification, it is named in the notes.
    • Expectation: see the effort label; done = the appended acceptance criteria are met.
    • Links: this issue
  5. added
    queue/queuedHas a queued task in the Supabase agent queue
    source/creatorFiled by the new-issue-creator job
    task/triageQueue packet kind: verify, reproduce, and route this item
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    on Nov 3, 2026
  6. 23 remaining items

  7. added
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    status/parkedDeliberately paused with a recorded resume condition
    and removed
    queue/claimedQueue worker lifecycle state
    on Nov 3, 2026
  8. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · parked

  9. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · parked

  10. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · parked

    • Agent: queue worker (repo-worker-code), lane code-d
    • Session / ID: task 8776
    • State: Parked 3600s on the §9.3 decision gate. Fresh check 2026-11-03T23:33:20Z: no comments on issue id: media.* — typed media artifacts by default, one bounded raw stream for realtime (#2027) #2342 since 2026-11-03T22:33Z — proposal comment 6614191454 still awaits Drew's answers/amendments to its 4 open questions (sha256 vs BLAKE3 in the ref, MAX_MEDIA_BYTES value, GC grace period, journal vs artifact-chain placement). Implementation starts only after that decision is accepted on the issue.
  11. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    state: parked
    task 8776 (small_fix, lane code-l, direct) parked 3600s on the §9.3 decision gate. Fresh check 2026-11-04T00:46Z: proposal comment 6614191454 still awaits Drew answering/amending its 4 open questions (sha256 vs BLAKE3 in the ref, MAX_MEDIA_BYTES value, GC grace period, journal vs artifact-chain placement); no comments on #2342 since 2026-11-03T23:33Z and no acceptance recorded. Per the packet's ordering rule, implementation does not start before acceptance. Resume: when the decision is accepted on this issue.

  12. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · escalated

    • Agent: queue worker (repo-worker-code), lane code-p
    • Session / ID: task 8776
    • Found via: queue claim
    • Task: Reviewed the §9.3 decision gate first-hand (proposal comment 6614191454, re-read in full this shift; fresh check: no answer from Drew since it was posted, and none since lane code-l's 2026-11-04T00:46Z check either). Escalating to user/escalated: the four questions are framed to Drew in the proposal itself, and each is a policy/interop call, not an implementation detail a worker should settle by default.
    • Expectation: Drew answers or amends any of the four questions on this issue; the task then unblocks and implementation of media.* proceeds under the accepted answers.

    My read, to make the decision cheap (recommendations, not decisions)

    1. Digest (sha256 vs BLAKE3): the proposal's BLAKE3-only ref is internally consistent (the blob store is BLAKE3-native; DocumentRef::verify_content is the working precedent). The only reason to also store sha256 is external interop outside the world protocol — if no external consumer is planned, BLAKE3-only is the simpler correct call.
    2. MAX_MEDIA_BYTES 256 MiB: reasonable as a hard constant beside MAX_EVENT_BYTES; making it server-configurable below the constant is nearly free (devices already advertise lower ceilings via outside_ceiling), so "constant + configurable-down" loses nothing.
    3. GC grace: 30 days fixed vs keep-until-store-pressure — this one is a data-retention values call (sovereign replicas, accidental-removal recovery). The 30-day grace is the safer default for a first version; pressure-only eviction can surprise-delete the only copy a peer would have re-fetched from.
    4. Journal placement: media.put in the world event journal follows the documents.rs precedent and is what makes the shared blob_gate reference index coherent; the artifact.rs chain would duplicate that machinery. Lowest-risk option is the proposal's.

    Blocking task 8776 as escalated-to-user with this note attached; issue #2342 label moves user/review → user/escalated.

  13. added
    user/escalatedQueue or user escalation state
    queue/blockedQueue or user escalation state
    status/blockedQueue or user escalation state
    and removed
    status/parkedDeliberately paused with a recorded resume condition
    user/reviewNeeds a user-look: Muse reviews first and handles what it can
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Nov 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

app/idPackage/app: id (pkgs/ or apps/ in this repo)effort/lLarge: multi-day or open-ended; expect staged check-inskind/featureNew feature or capability requestmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedpriority/normalOrdinary priority (the default)queue/blockedQueue or user escalation statesource/creatorFiled by the new-issue-creator jobstatus/blockedQueue or user escalation statetask/triageQueue packet kind: verify, reproduce, and route this itemuser/escalatedQueue or user escalation statework/assignedQueue worker lifecycle state

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions