Mark, 25 August 2026: "allow shots to be deleted from a session — my testing is generating data!"
A four-shot session on a phone is 44 MB (#98, ses:59e4ec66), essentially all of it clip payload. A day of testing fills a phone, and there is no way to remove anything: nothing in Sources or Packages/Core deletes a Session, a Shot or a clip. The only removeItem calls in the tree are RingBufferRecorder's own fragment eviction.
Why this is not just a delete button
⛔ A bundle is an append-only frame stream. ENC §7 has no delete frame, no rewrite and no random access — 7e says so deliberately: "random access is deliberately not in ppcp/1.0". session_manifest lists every Capture with its digest and byte count, and ENC 7c fixes it before the payload frames. So removing one Shot's bytes from an existing .ppcpbndl means rewriting the file and its manifest, not editing it in place.
⚠ And a Shot is not only its clip. A Shot names its Candidates (8.3a, and 8.3h lets it gain more later), each Candidate names the audio window that explains it (5.12.1a), and every one of those is a Capture with its own payload. "Delete this shot" has to say which of those it means.
⚠ CORE 5.14g/I38 is probably not the obstacle, and it is worth being precise about why. 5.14g forbids a peer evicting a Capture holding payload no receiver has confirmed, and 5.14g1 shuts the door on a retention policy extending the exits — "shot-anchored payload is never sheddable by policy". That is aimed at a device quietly shedding swings under storage pressure, and the remedy it names is refusing to arm. A person deliberately deleting their own recording is a different act from a policy dropping it, and the specification does not appear to speak to it. This wants confirming rather than assuming — if 5.14g does bind, the answer is that deletion is only offered once the payload is confirmed or the Session was never destined for a host, and that changes the feature.
Where it would live
SessionStore (Packages/Core/Sources/CaptureCore/Store/SessionStore.swift) owns the on-disk layout — the .ppcpbndl, clips/ and thumbnails/ — and has no removal API at all.
SessionLibraryScreen is where whole-session deletion belongs; the shot list on the session screen is where per-shot deletion would.
Shot/PpcpShot and PpcpCaptureRecord are what a deletion has to resolve between.
Two things that are probably separable
- Delete a whole Session. Much the simpler half — remove the directory. No rewrite, no manifest question, and it is what "my testing is generating data" most directly asks for. Could ship on its own.
- Delete one Shot from a Session. Needs the manifest and rewrite questions above answered first, and needs a decision on whether the Shot record survives with its Captures announced
absent — which 5.12.1c already contemplates for evicted candidate audio, "never a dangling reference" — or whether the Shot disappears entirely.
⚠ Option 2's absent-with-a-reason shape looks right and would keep the bundle honest about what was there, but that is a design call, not a foregone conclusion.
Exit criterion
⛔ A golfer can remove a session, and a shot within one, from the device; the bundle that remains reads back through libppcp's own reader with a manifest that matches what is actually in it; and the space is genuinely reclaimed.
A four-shot session on a phone is 44 MB (#98,
ses:59e4ec66), essentially all of it clip payload. A day of testing fills a phone, and there is no way to remove anything: nothing inSourcesorPackages/Coredeletes a Session, a Shot or a clip. The onlyremoveItemcalls in the tree areRingBufferRecorder's own fragment eviction.Why this is not just a delete button
⛔ A bundle is an append-only frame stream.
ENC§7 has no delete frame, no rewrite and no random access — 7e says so deliberately: "random access is deliberately not inppcp/1.0".session_manifestlists every Capture with its digest and byte count, andENC7c fixes it before the payload frames. So removing one Shot's bytes from an existing.ppcpbndlmeans rewriting the file and its manifest, not editing it in place.⚠ And a Shot is not only its clip. A Shot names its Candidates (8.3a, and 8.3h lets it gain more later), each Candidate names the audio window that explains it (5.12.1a), and every one of those is a Capture with its own payload. "Delete this shot" has to say which of those it means.
⚠
CORE5.14g/I38 is probably not the obstacle, and it is worth being precise about why. 5.14g forbids a peer evicting a Capture holding payload no receiver has confirmed, and 5.14g1 shuts the door on a retention policy extending the exits — "shot-anchored payload is never sheddable by policy". That is aimed at a device quietly shedding swings under storage pressure, and the remedy it names is refusing to arm. A person deliberately deleting their own recording is a different act from a policy dropping it, and the specification does not appear to speak to it. This wants confirming rather than assuming — if 5.14g does bind, the answer is that deletion is only offered once the payload isconfirmedor the Session was never destined for a host, and that changes the feature.Where it would live
SessionStore(Packages/Core/Sources/CaptureCore/Store/SessionStore.swift) owns the on-disk layout — the.ppcpbndl,clips/andthumbnails/— and has no removal API at all.SessionLibraryScreenis where whole-session deletion belongs; the shot list on the session screen is where per-shot deletion would.Shot/PpcpShotandPpcpCaptureRecordare what a deletion has to resolve between.Two things that are probably separable
absent— which 5.12.1c already contemplates for evicted candidate audio, "never a dangling reference" — or whether the Shot disappears entirely.⚠ Option 2's
absent-with-a-reason shape looks right and would keep the bundle honest about what was there, but that is a design call, not a foregone conclusion.Exit criterion
⛔ A golfer can remove a session, and a shot within one, from the device; the bundle that remains reads back through
libppcp's own reader with a manifest that matches what is actually in it; and the space is genuinely reclaimed.