For Agents
Living index of themes for this project. Each H2 is a topic; bullets are wikilinks to related notes. Updated by
obsidian-documenterwhen documenting work. Read byhistorianat bootstrap. Topics kept alphabetical.The project is now called Aposemati — the folder name
phone-camera-clonepredates the rename. Start at aposemati.
Architecture
- aposemati — current architecture: four QUIC channels (preview/control/stills/video), “never stream the thing you are keeping”, “framing is metadata, never pixels”, three modules, 8 phases.
- ⭐ aposemati-phase2-live-preview — ⚠️ the shipped preview architecture is not the specified one:
NWConnectionGroup/NWMultiplexGroupdid not work, so preview is a thirdNWConnectionto a secondNWListeneron its own port — better isolation than the spec describes, but the durable spec still records the plan. Also: both connections share one serialDispatchQueue, worth ~40% of measured interference. - ⭐ aposemati-phase0-phase1-build — the architecture as actually built and running: two QUIC connections (not one — shared congestion controller), 16-byte UUID prefix on asset frames replacing positional pairing, 16 MiB decode-side frame cap.
- diy-continuity-camera-clone-research — ⚠️ superseded Wi-Fi Aware pipeline (AVFoundation → VideoToolbox → Wi-Fi Aware data path → decode → virtual cam / record). Kept as a record.
Build & Tooling
- ⭐ aposemati-build-install-run — 🔴
swift build/swift testcannot seeApps/at all — neither app target is inPackage.swift, and the Mac app was silently broken for five commits. Bothxcodebuildgate commands (CODE_SIGNING_ALLOWED=NO, ~90 s) are in the note. - ⭐ aposemati-build-install-run — the commands that actually work, and the two naming traps: the iOS product is
Aposemati.app, notAposematiCamera.app, andxcodebuild -destination id=is not thedevicectlidentifier (same phone, two UUIDs). Also: a denied Local Network permission does not error — the browser parks forever. - aposemati-apple-signing-gotchas — WWDR G3 intermediate, Xcode-first device registration, security-scoped bookmarks.
Build Status
- ⭐ aposemati-phase2-live-preview — 🟢 PHASE 2 COMPLETE at
c29f84d, 2026-08-25: 33 commits, 418 tests, both apps building, live preview over QUIC datagrams working end to end on loopback. ⏸️ Verdict deliberately blank pending hardware — the two deciding readings need two devices. Ranked hardware checklist inside; item 1 is re-verifying Phase 1’s 48 MP + ZSL stills with the video output attached. - ⭐ aposemati-whole-branch-review — ✅ the last engineering step is DONE: the final whole-branch review ran on 2026-08-19 and no finding blocks the branch. The remaining work is applying its ranked fixes (arm D,
AuditGapTests.swift, the C2 hybrid) and the hardware run. - ⭐ aposemati-loopback-blind-spot — 🐛 the permanently frozen viewfinder is fixed, 2026-08-26:
NetworkPreviewChannelhad no teardown path at all on the sending end. Two changes — a[weak self]stateUpdateHandlerin the shared class (which fixes both ends) and the retry loop the Mac already had. Verified by hand-run mutation; still open: whetherawdl0delivers.failedat all, and the missing-shutter defect. - aposemati-crop-and-framing — 🟡 Phase 6 first half shipped 2026-08-26 at
4c0d828, 546 tests: lens picker, framing control, countdown, one normalized crop region driving both preview and still. Two defects found by hardware in ten minutes — one now closed, one still open. - ⭐ aposemati-phase0-phase1-build — 🟢 working software, final state 2026-08-19: 48.8 MP iPhone → Mac over
awdl0 — direct. 68 commits, 219 tests, zero warnings, clean tree, branchphase0-phase1-link-and-shutterunmerged and unpushed, both apps installed on hardware. Review loop closed; the one remaining step is the final whole-branch review over all 68 commits + 27 deferred minors.
Code Review & Audit
- ⭐ aposemati-whole-branch-review — the final whole-branch review, 2026-08-19: six reviewers, isolated clones, all 68 commits at once, verify-by-execution. No finding blocks the branch. POSIX 57 root-caused; the 250 ms listener margin; C1/C2 mutually exclusive; test suite ~70% real (119 mutations, 35 survived); 29 deferred minors triaged with seven struck as disproved by measurement; four documentation-drift items. Nothing applied yet.
- aposemati-build-process-lessons — the review method: mutation testing’s two opposite failure modes, instrument-vs-instrument checking, per-agent clones, a per-task review’s structural blindness.
- ⭐ aposemati-build-process-lessons — ⭐ Phase 2’s additions: five measurements that answered a different question than the one asked; two tasks each correct in scope, jointly leaving a hole neither owned; a test double that collapses two roles hides defects that survive full review with mutation evidence;
Apps/is outside the SPM package and was silently broken for five commits; and bounding a review explicitly beats an open one. - aposemati-phase2-live-preview — 23 rulings and ~15 deferred minors in one phase, one whole-phase review plus a fix wave, with the parked residuals listed rather than quietly closed.
- ⭐ aposemati-loopback-blind-spot — ⚠️ the limit of review itself: 546 tests, eight task reviews and a whole-branch review all missed a defect a plugged-in phone found in ten minutes, because the harness cannot produce the failure the field produces. The mutation was run by hand rather than trusted from a report — precedent: commit
371b32a, a fix later disproved because its test passed identically with and without the change.
Competitive Intelligence
- camo-studio-teardown — Camo Studio 2.8.2 at binary level: pricing, free-tier limits, the exclusion matrix, missing NDI/curves/encoder control, Snap Camera Kit AR dependency,
AiBackgroundStyles.json. - aposemati-apple-api-measurements — Continuity Camera’s real ceiling (1920x1440, 8-bit), Photo Booth’s non-destructive effect model, OBS/Camo signing posture.
Distribution & Signing
- aposemati-build-install-run — signing summary plus the install-side identifier trap.
- aposemati-apple-signing-gotchas — WWDR G3 intermediate missing →
find-identityreports 0 valid identities andcodesignfailserrSecInternalComponent; Xcode device registration before-allowProvisioningUpdates; security-scoped bookmarks in the sandbox; XcodeGen with an uncommitted.xcodeproj. - aposemati-apple-api-measurements — Developer ID + notarization, not Mac App Store; OBS (
2MMRE5MTB8) and Camo (Q248YREB53) both unsandboxed with no MAS receipt; Camo’stemporary-exception.sbplforusbmuxd; system extensions must be notarized to load.
Homelab Integration
- aposemati — ❌ closed:
telep-mainframe’s AX210 has no antenna on its u.FL connector, so it cannot be a wireless peer at all. - diy-continuity-camera-clone-research — original (now void) plan to record into telep-mainframe via go2rtc/Frigate.
Image Processing & Encoding
- aposemati-apple-api-measurements — device capability matrix: 48 MP starts at the iPhone 14 Pro; 12/13/14 non-Pro and all iPads are 12 MP; 24 MP only via deferred delivery (opted out). Nothing hardcodes a resolution.
- aposemati-apple-api-measurements — VideoToolbox low-latency latencies (H.264 4K30 140.1 → 16.4 ms),
kVTCompressionPreset_VideoConferencing, AV1 encode does not exist, Core Image colour chain at 0.506 ms/1080p,CIPersonSegmentationaccurate fixed at ~30 ms. - ⭐ aposemati-crop-and-framing —
AVCaptureSession’s.photopreset silently selected a 17 fps video format and nobody had noticed; a format offering 4032×3024 video at 30 fps and 8064×6048 stills sat unused indevice.formatsthe whole time. Now 30–31 fps on hardware. Found by printing the format table, not by reasoning — two mechanisms were confidently argued first and both were wrong. Also: at zoom 1 the phone’s bytes go to disk untouched (~0 ms, gain map intact); only a zoomed still is re-encoded (~300 ms). - ⭐ aposemati-phase2-live-preview — the JPEG-per-frame viewfinder and the H.264 gate: a 12-rung ladder (3 scales × 4 qualities, long edge 1920), reactive admission, and the measured baseline H.264 must beat — 482,530 B / 408 fragments / 117.4 Mbps against ~33,300 B / ~29 fragments / ~8.1 Mbps. H.264 buys bandwidth and loss tolerance by spending latency (23.2 ms encode vs JPEG’s 2.8–7.6). Periodic intra-refresh goes live the moment H.264 lands, and the measured
psets its interval.
Process & Method
- ⭐ aposemati-loopback-blind-spot — ⭐ loopback cannot reproduce “a send that succeeds into nothing”, and that is why a 546-test suite was silent about a real defect. Over
awdl0a datagram send into a dead peer succeeds; on loopback it fails withPOSIXErrorCode 57, so the harness takes the error path the field never takes and a test written for the defect passes against unmodified code. Only the quiet form (peer leaves, nothing being sent) is reproducible; the live-sender form is not reproducible at all. Rule: ask which error the real medium declines to produce before trusting a harness about a failure mode. - ⭐ aposemati-build-process-lessons — ⭐ mutation testing has two opposite failure modes and neither was guarded in any of 14 task reviews: false SURVIVED (mutant reverted by another agent’s directory-wide
git checkout, or never compiled in — SwiftPM’s same-second mtime race reuses the previous binary) and false CAUGHT (21% of pristine runs fail under load). Guard with a canary test that passes only if the mutant is live plus source/binary hashing; give each concurrent agent its owngit clone --local. - ⭐ aposemati-build-process-lessons — ⭐ “verify by execution” is necessary but NOT sufficient — check the instrument against an independent one. Both wrong claims in the whole-branch review were measurement artifacts (attackers’ memory counted as the victim’s; a harness reusing one
Databuffer that copy-on-write shared across all frames — andData(count:)is equally invalid, untouched zero pages are never resident). Caught by another reviewer’s number disagreeing, never by re-reading code. - ⭐ aposemati-build-process-lessons — ⭐ trace a symptom to its single throw site and measure there (two fix rounds were spent on a bug a review reported as fixed: once from a confident report that contradicted its own error table, once from a mutation-harness false negative) and treat a confident report as a claim to verify; a per-task review structurally cannot see across tasks; verify by execution, not by reading; passing tests are never evidence; mutation testing required wherever a fix claims to close a hole; a test named for a failure often does not catch it; commit-as-you-go (one agent lost a whole fix round to a machine sleep, another lost nothing).
Project Decisions
- aposemati-pairing-security-model — in-memory per-launch TLS identity, never persisted, never in the keychain (accepted cost: re-pair on every relaunch); commit-reveal SAS over a typed code; the pairing model moved twice, both times because measurement contradicted the plan.
- aposemati — name (aposematism, a pun on Camo), open source + free, Apple-only, “serious personal tool”, v1 = 48MP stills + on-device recording, virtual camera deferred to phase 7, off-router transport as the defining constraint.
Research & Planning
- aposemati — phase plan; Phase 0 transport spike is existential because no throughput figure exists anywhere.
- ⭐ aposemati-phase2-live-preview — the open decision: JPEG-per-frame or H.264. Four passing rows and four failing rows, the exact two-device protocol that fills them, and a deliberately blank verdict. Row 4 (bitrate against measured throughput) is the one most likely to fail and the one not in the spec.
- aposemati-transport-findings — the research that killed the previous plan; SDK-header-level verification method.
- diy-continuity-camera-clone-research — ⚠️ superseded original brief; transport-first framing still valid.
Security
- ⭐ aposemati-pairing-security-model — ✅ the “cheating initiator dictates the six digits” exploit is REFUTED (the commit-reveal binds; the grind was offline computation never pushed through the shipped responder) — but
pairingCommitmentBrokenhas zero test coverage, deleting the verification guard SURVIVES mutation, and the existing MITM test exercises nonce mixing, not the commitment. Online regrinding rated Low (~297/s, no rate limit, but the code cannot be steered). - ⭐ aposemati-pairing-security-model — ✅ the pre-confirmation memory hole is CLOSED (
aef872b): the transport reads nothing until the app asks for frames — 34.7 MB peak against four flooding strangers vs 486 MB reverted; and the refusal-recovery endless loop is closed (e1cd333). Plus the 0.77 s machine-in-the-middle that defeated plain SAS comparison, and the commit-reveal nonce exchange that fixes it; 252 MB buffered by an unconfirmed peer; the refusal blacklist’s per-process-lifetime scope; UI as part of the security boundary. - ⭐ aposemati-peer-restart-inference-boundary — ⭐ peer data must never move the watermark backwards. Seven rebuilds of one restart detector; four inference mechanisms each satisfied their requirement and each was exploitable, because an honest restart and a spoofed one are indistinguishable at admission. The fifth answer was to delete the mechanism and let the session layer call
reset(). One hard residual (cyclic restart inside the reordering tolerance) documented with the reason the obvious silence-keyed fix must not be used. - swift-character-isnumber-digit-trap — non-ASCII digits passing validation in three places, one of them the pairing code.
- aposemati-network-framework-gotchas — QUIC has no TLS-PSK;
.readyon a listener proves nothing about the security config. - ⚠️ aposemati-peer-restart-inference-boundary — the silence rule’s real scope, and a miscitation that was widening it (2026-08-26): it binds the receiver-side reassembler stall watchdog only and says nothing about connection state.
HANDOVER.mdcites “spec §4.3” three times; that section does not exist, the rule is at2026-08-18-aposemati-design.md:502. A rule that travels by citation drifts in scope — here it was being used to argue against astateUpdateHandler, which is a local transport fact, not silence.
Superseded & Corrections
- diy-continuity-camera-clone-research — ⚠️ SUPERSEDED 2026-08-18. Wi-Fi Aware “winning path” invalidated; AWDL-was-replaced claim corrected inline.
- aposemati-transport-findings — the correcting note.
- aposemati-network-framework-gotchas — ⚠️ corrections to the transport research:
NWBrowser.Result.interfacesis the only public AWDL source; never filter by interface type; QUIC has no TLS-PSK; Multipeer is deprecated as of the 27.0 SDK, not 26.x. - aposemati-apple-api-measurements — ⚠️ the “48 MP everywhere” assumption corrected to a per-device capability matrix.
- aposemati — ⚠️ four channels on two connections, not one; phases renumbered (preview moved from Phase 1 to Phase 2).
- ⚠️ aposemati-crop-and-framing — “framing is metadata, never pixels” was REVERSED 2026-08-26: the crop ships destructive and the uncropped 48 MP original is never written to disk. Chosen deliberately and reaffirmed when the contradiction with this vault was found. Cost: a 2× crop takes 48.8 → 12.2 MP with no original to return to.
- ⚠️ aposemati-peer-restart-inference-boundary —
HANDOVER.md’s “spec §4.3” does not exist (cited three times); the silence rule is at2026-08-18-aposemati-design.md:502and is narrower than the citation implied. - ⚠️ aposemati-crop-and-framing — the freeze’s “leading hypothesis, untested” is now confirmed, fixed, and narrower than stated — aposemati-loopback-blind-spot.
- ⚠️ aposemati-phase2-live-preview — corrected again: preview is a third connection on its own listener and port, not datagrams on Connection A;
.backgroundis set nowhere; the “~155 fragments” figure carried forward from Task 6 is 240 (and the other case is 408); the burstiness rule was backwards; and the loss denominator was inflatingpby 2.03×.
Swift & Concurrency Traps
- ⭐ swift-uncancellable-continuation-trap — a bare
withCheckedContinuationinside awithTaskGroupcannot be cancelled; the QUIC idle timer had been accidentally rescuing the deadlock until a keepalive removed it. Appeared three times; fix iswithTaskCancellationHandler. - ⭐ swift-character-isnumber-digit-trap —
Character.isNumber/CharacterSet.alphanumericsaccept Arabic-Indic, Devanagari and fullwidth digits. Also the unpinned-DateFormatter-locale neighbour.
Transport
- ⭐ aposemati-phase0-field-measurements — the numbers: 339 Mbps beside the router, 156 Mbps where Camo drops, both
awdl0 — direct, rtt 37 ms unchanged, 0.011% retransmission. Range costs bandwidth, not latency. - ⭐ aposemati-network-framework-gotchas — how to obtain and pin an AWDL interface at all, plus the QUIC/keepalive/datagram traps.
- ⭐ aposemati-network-framework-gotchas — 📡 QUIC datagrams ARE reachable from Swift: read
usableDatagramFrameSizeoff the datagram flow (the parent connection returns 0); an oversize datagram is accepted with NO error and silently dropped; the two ends disagree (9156 vs 9164) so clamp on the local read; DATAGRAM frames are not flow-controlled. ❌NWConnectionGroup+NWMultiplexGroupdid not work —POSIXErrorCode 50on every extracted connection, group.readywith its path down; and bothnewConnectionGroupHandlerandnewConnectionHandleron one listener failsPOSIXErrorCode 22. - ⭐ aposemati-phase2-live-preview — the loss table and the bandwidth ceiling: a lost fragment costs exactly one frame (measured on two real QUIC ends at 1200 B); 10% of frames go at p=0.026–0.044%; preview at 117.4 Mbps is 75% of the 156.3 Mbps measured at the Camo-drop spot, against a derived 50% bar. Phase 0’s 0.011% retransmission is a different quantity and cannot be substituted for
p. - ⭐ aposemati-network-framework-gotchas — ✅ POSIX 57 SOLVED: a QUIC listener hands you two
NWConnections per peer (streamIdentifier1 = the one it was handed, 0 = the peer’s real stream) and cancelling either resets the whole connection. Tolerance is a hard cliff at ~250 ms, not a probability. Fix is a reference lifetime (park by 4-tuple, release on the peer’s stream, reap from your own timeouts) — 1800 pairings, zero failures; the naivereturn nilis worse than the bug. - aposemati-phase0-phase1-build — the readiness bound is 30 s (was 10, measured still failing at 10.65 s over a radio). The POSIX 57 that was long unexplained is now root-caused — see above.
- aposemati-whole-branch-review — C1/C2: the late-reader guarantee holds only to 256 KB (a 4 MB photo vanishes silently while
carriedTraffic()reports it acknowledged), andLoopbackTransportaccumulates 320.8 MB for 320 MB offered with no back-pressure — but has zero non-test uses. - aposemati-transport-findings — ⭐ the verdict: Wi-Fi Aware is
@available(macOS, unavailable)(five independent proofs); AWDL is alive (awdl0UP,llw011.5 GB in); no public AWDL API; Multipeer Connectivity not deprecated;NWParameters.includePeerToPeeris the primary candidate; iPhone 16/17 non-Pro are USB 2 only; Wi-Fi Aware hardware/entitlement/Info.plist details kept for a future iPhone↔iPad path. - ⭐ aposemati-network-framework-gotchas — 💀 a QUIC datagram send into a DEAD peer SUCCEEDS over
awdl0and FAILS on loopback (POSIXErrorCode 57). Never make send failure your peer-death detector — install a[weak self]stateUpdateHandleron everyNWConnectionand nil it insideshutDown()before thecancel()that re-enters it. Loopback propagates a peer’scancel()in ~76 ms; over the radio theCONNECTION_CLOSEmay be lost and the survivor falls back to the 30 s idle timeout — unmeasured, and hardware checklist item 8. - ⭐ aposemati-loopback-blind-spot — the defect that fact caused: a permanently frozen viewfinder with both ends believing they were healthy, and a Mac log looping cleanly every 32 seconds forever.
- aposemati — four-channel QUIC design over whichever transport survives Phase 0.
- camo-studio-teardown — Camo’s own transport prefs (“Bonjour connections”, “Peer-to-peer”, “Malheur connections”, “Send video packets twice”).
- diy-continuity-camera-clone-research — ⚠️ superseded options table (USB, AWDL, Wi-Fi Aware, hotspot).
Virtual Camera
- aposemati-apple-api-measurements — CMIO extension gotchas: XPC does not work (
CMIOExtensionMachServiceNameis “a red herring”,NSCocoaErrorDomain Code=4099); use a sink stream viaCMIOStreamCopyBufferQueue+CMSimpleQueueEnqueue; DAL disabled in Sonoma 14.1; container must live in/Applications; entitlement list. - camo-studio-teardown — Camo ships
com.reincubate.macos.cam.avextension+ a CoreAudio virtual driver + a LaunchAgent. - aposemati — deferred to phase 7.
- diy-continuity-camera-clone-research — original cross-platform sink survey (CMIO / Media Foundation / v4l2loopback); Windows and Linux are now out of scope.