All notable changes to this project are documented in this file. Format loosely based on Keep a Changelog.
This project is currently in the reverse-engineering phase — there is no
working app yet, so entries so far are documentation, tooling, and process
rather than app releases. See TODO.md for current status and PROJECT.md
for the "definition of done" that will mark v1.
- Core documentation and guardrails (
AGENTS.md,PROJECT_RULES.md,PROJECT.md,ARCHITECTURE.md,PROTOCOL.md,README.md). - Fedora 44 workstation setup (
WORKSTATION_PREPARATIONS.md): Claude Code, Antigravity, Java 21, Kotlin/SDKMAN, Wireshark, Android SDK/adb, JADX, apktool. - Bluetooth HCI snoop capture procedure (
CAPTURE_BLUETOOTH_HCI_SNOOP.md). - Test plan mapping user/app/hardware actions to expected Bluetooth traffic,
validated against official screenshots/support docs
(
TESTPLAN_BLUETOOTH_HCI_SNOOP.md). - Reference screenshots for the official app and web companion app.
SECURITY.md,CONTRIBUTING.md,DESKRESEARCH_FINDINGS.md.
- Defined a narrow, bounded BLE-scanning exception for the Fast Pair Battery
Notification (filtered/foreground-triggered/time-boxed) to resolve a
conflict with the absolute no-scanning rule —
DECISIONS.mdADR-006. - Removed
TODO.md's duplicated, checkbox-synced open-questions list in favor of single-source pointers toPROTOCOL.md§6 andARCHITECTURE.md§15. - Tied the
FrameEncoder/FrameDecoderimplementation gate to a requiredDECISIONS.mdADR, not just 🟢 FACT confidence alone (ARCHITECTURE.md§2.1, later superseded by the per-DLCICodecRouterdesign). - Added an ADR-numbering rule (sequential, never reused) to prevent stale hardcoded ADR references elsewhere.
CAPTURE_BLUETOOTH_HCI_SNOOP.md: clarified Group A (lightweight forget-and-re-pair) vs. Group P #16 (destructive factory reset) are distinct; added the missing §9 Capture Index; made a full reboot the default recovery step (§2) with Bluetooth toggle as a faster fallback; branched frame-analysis instructions by type (RFCOMM vs. BLE advertisement) instead of applying one hypothesis to all captured frames; madebtsnooz.pythe primary log-extraction method; corrected several unsubstantiated claims (empty-capture cause, "non-rootable" phrasing, a community-forum report presented as confirmed); rewrote the encryption FAQ entry to distinguish HCI-boundary visibility from genuine link-layer encryption; clarified "one action per window" means one user-triggered event, not one frame; marked the post-action wait as a heuristic, not a guarantee; added observation-start/-end boundary logging for passive windows; replaced a binary traffic-observed/not check with a proper 3-way outcome taxonomy for Loud Noise Protection/Adaptive Audio.- Fixed a self-contradictory "Android 14+ (API 34)" phrasing in
ARCHITECTURE.md/README.md— separated the decided compile/target SDK from the still-open minimum supported API. - Fixed
TODO.mdundercounting Gradle modules as four instead of five (missing:app); same gap fixed inDECISIONS.mdADR-001. - Added Group Z (pipeline validation) and a cross-command framing check after
Group K to
CAPTURE_BLUETOOTH_HCI_SNOOP.md; reorderedTODO.mdPhase 1 to match. Declined to hardcodeCAP-NNNnumbers intoTODO.md— IDs are assigned in the Capture Index as work happens. - Fixed stale filename references (
PROTOCOL-NOTES.md,TESTPLAN_EN.md) found during a cross-file consistency pass. fix:renumbered three second-attempt capture sessions that had been reusing their first attempt'sCAP-NNNID with only their folder's date/time suffix distinguishing them — a violation ofDECISIONS.mdADR-007's "never reused" ID-format rule, and the direct cause of the 2026-08-18 Group T session (CAP-005) never getting a row of its own inCAPTURE_BLUETOOTH_HCI_SNOOP.md's Capture Index. ReusedCAP-005(2026-08-18, Group T) →CAP-015; reusedCAP-007(2026-08-18, Group U) →CAP-016; reusedCAP-010(2026-08-16 18:30, Group W) →CAP-017. The original, first-attempt sessions (CAP-0052026-08-15,CAP-00709:14-10 2026-08-16,CAP-01011:42 2026-08-16) keep their original IDs unchanged. Renamed the affected folders/files (git mv, preserving history) and updated every current-state cross-reference acrossPROTOCOL.md,CAPTURE_BLUETOOTH_HCI_SNOOP.md,TESTPLAN_BLUETOOTH_HCI_SNOOP.md, andDESKRESEARCH_FINDINGS.mdto the new IDs; earlier entries in this changelog that mention the old IDs are left as-is (historical record).ci:bumpedactions/checkout@v4→@v5andactions/setup-python@v5→@v6across the three docs-site workflows (.github/workflows/lint-docs.yml,.github/workflows/update-docs-sidebar.yml,.github/workflows/update-sitemap.yml) to clear GitHub's Node 20 deprecation warning — both actions now declareusing: node24natively instead of being force-run on it.
-
Identified the official Fast Pair "Battery Notification" and "Message Stream: Device Information" extensions as likely covering battery reporting, reducing what needs reverse engineering from scratch.
-
Corrected an earlier fixed-interval battery-polling assumption — Fast Pair battery updates are event-driven (connect or on change), not polled.
-
Restructured
CAPTURE_BLUETOOTH_HCI_SNOOP.md/TESTPLAN_BLUETOOTH_HCI_SNOOP.mdto remove their overlap:CAPTURE's Groups became capture scenarios,TESTPLANbecame a stable Test-ID catalog (70 IDs) with a thin evidence pointer intoPROTOCOL.md, closing the chain Test-ID → Group →CAP-NNN→ frame → finding. Recorded asDECISIONS.mdADR-007. Surfaced two catalog gaps (INEAR-004,GATT-001) not yet covered by a capture scenario at the time. -
Ran several information-preservation and consistency audits across
AGENTS.md/ARCHITECTURE.md/PROTOCOL.md/CAPTURE/TESTPLANagainst earlier drafts; found and restored a handful of genuine content losses (a droppedTESTPLANrow note, a narrowed cross-reference, and a fully dropped battery mechanism —ACTION_BATTERY_LEVEL_CHANGED, restored asPROTOCOL.md§4.3 Option 0) and fixed several orphaned Test-ID/formatting/traceability gaps. Flagged (not created) a then-missingEXPERIMENTS.mdthat seven files referenced — later resolved by retiring the concept entirely (see 2026-08-15 entries below). -
Fixed a real
btsnooz.pybug inCAPTURE_BLUETOOTH_HCI_SNOOP.md§3, found viaCAP-001(Group Z): the bugreport's internal.txtkeeps Android's own generated name regardless of the name passed toadb bugreport. -
Formalized Group R (forced GATT re-discovery, bond removal via system settings not the app's own "Forget") and Group S (GMS disabled / no Pixel Buds app,
GFPS-001) as documented capture scenarios, each written up from an actual capture rather than designed speculatively. -
2026-08-12 deskresearch pass, resolving two long-standing open questions without a new capture: ANC mode set/get/notify → 🟢 FACT (Google's official Hearable Controls extension, Message Group
0x08, matchesCAP-001byte-for-byte with a 4/4 content+timing correlation); and DLCI 0x02's framing → 🟢 FACT (Pigweedpw_hdlc, CRC-32 matchingpw_checksumexactly, 640/640 sub-frames across three captures, matchingpbpctrl's documented Maestro transport).PROTOCOL.md§2.3 restructured from a binary framing question into a three-channel table as a result.libmaestro's own command content stayed unresolved, deliberately not force-closed with an unreviewed ADR. -
2026-08-14–15: 8-lens project review, executed in four phases (each committed and confirmed separately) —
- Phase 1: renamed the project (trademark), replaced the "clean-room"
claim with "independent implementation" (reaffirmed AGPL-3.0 unaffected,
DECISIONS.mdADR-002), and reworkedARCHITECTURE.mdaround the 3-DLCI reality (CodecRouter,UnidentifiedFrame, State Reconciliation, Startup Handshake/Safe Mode, wakelock budget). - Phase 2: retired
PROTOCOL_NOTES.mdandEXPERIMENTS.mdas intermediate buffers (agents workCAP-NNN-FINDINGS.md→PROTOCOL.mddirectly); addedDESKRESEARCH_FINDINGS.md; added AI-guardrail rules (no unilateral FACT/ADR promotion, hex-dump determinism, the hex & script rule); addedSECURITY.md/CONTRIBUTING.md. - Phase 3: demoted an over-generalized CTKD finding back to HYPOTHESIS;
fixed a GMS-vs-app-uninstall confound in the
CAP-004GMS-dependency conclusion; added an AES-128 open question for DLCI 0x02; split the battery mechanism docs (Fast Pair event-driven vs. HFP periodic ~6–7s, fixing a staleAT+IPHONEACCEV/AT+XAPLreference along the way); addedDECISIONS.mdADR-008 (Fast Pair Account Linking/Ownership Transfer/Non-Owner Service out of scope); corrected Group R's GATT-cache claim in favor of Group W; distinguished the UI-baseline vs. still-open wire-baseline firmware version. - Phase 4: added
DECISIONS.mdADR-009 (ANC channel confirmed, butFrameEncoderblocked pendingCAP-006— 2 ofCAP-001's 6 ANC taps produced no command frame); added a hardware-bricking disclaimer (README.md) and Disaster Recovery procedure (WORKSTATION_PREPARATIONS.md); added a hardcoded-wire-string exception rule (PROJECT_RULES.md); reprioritizedTODO.mdaroundCAP-005(Group T, EQ)/CAP-006(ANC)/CAP-010(Group W) as top priority over edge-case protocol research; trimmed this changelog's own verbosity.
- Phase 1: renamed the project (trademark), replaced the "clean-room"
claim with "independent implementation" (reaffirmed AGPL-3.0 unaffected,
-
2026-08-20: comprehensive documentation audit and remediation, an 8-phase review (inventory, structural/cross-reference integrity, traceability, FACT/HYPOTHESIS/ASSUMPTION labeling, rule compliance, raw wire-data re-verification, editorial review, gap analysis) covering every core doc, the full Capture Index, and all
CAP-NNN-FINDINGS.md/CAP-NNN-EVENT-NOTES.mdfiles. Headline: zero 🔴 Critical findings — independenttsharkre-derivation of every checkable Phase-5 claim (connection lifecycles, ANC frame counts, EQ quintets, GATT discovery counts, the DLCI-0x02 CRC-32 pipeline) matched the documentation exactly, with no factual discrepancy found. Findings resolved, in order of impact:- Status-taxonomy unification: 🔴 OPEN QUESTION formally added as a
fourth confidence tier in
PROJECT_RULES.md§1 rule 1 andPROTOCOL.md§0 (alsoREVERSE_ENGINEERING.md/DESKRESEARCH_FINDINGS.md's legends) — reconciling the written rule with practice already unanimous across everyCAP-NNN-FINDINGS.mdfile and 16 uses inPROTOCOL.md's own body.PROJECT_RULES.mdrule 4's stale "🟡 Secondary" citation fixed to match. PROJECT_RULES.mdrule 9a: added a grandfather clause (findings dated before the rule's own 2026-08-15 introduction aren't retroactively required to be cleaned up) and a worked before/after example. Fixed the two residual post-rule violations found (CAP-004-FINDINGS.md§10,CAP-005-FINDINGS.md§1) by rewriting them in place.- Test-ID
PAIR-002corrected toPAIR-001onCAP-002/CAP-003/CAP-004(no factory reset was performed in any of the three;PAIR-002is reserved for that perTESTPLAN_BLUETOOTH_HCI_SNOOP.md's own definition). ARCHITECTURE.md's title (predated the project rename) and its §5 DLCI 0x02 description (predated the 2026-08-17 address-instability finding) both brought current;PROTOCOL.md§1's transport-overview table and §8's changelog table (missing several 2026-08-18 entries) likewise updated.- Filename/timestamp corrections: a doubled-prefix typo in a
CAP-001example command; two imprecise timestamps inDESKRESEARCH_FINDINGS.md;CAP-005-recoding.mp4renamed toCAP-005-recording.mp4(git mv, preserving history). - Added a
.gitignore(none existed, despitePROJECT_RULES.mdrule 19 referencing one). - New tooling:
id_registry.csv(machine-readableCAP-NNN/ADR-NNN/ Test-ID registry) andscripts/lint_docs.py(dead-filename, unregistered-ID, and stale-project-name checks) — running the lint script against the as-audited repo immediately surfaced four Test-IDs already in live use with no catalog row (OBS-003,APP-001,APP-002,GFPS-002), now added toTESTPLAN_BLUETOOTH_HCI_SNOOP.md(plus a newAPPID prefix). - Two Phase-7 gap-analysis items closed:
CAP-002's DLCI 0x03/0x05 traffic checked and confirmed to belong to an unrelated device sharing the same long, non-restarted log buffer (not the Buds — same class of artifact asCAP-004's incidental Fitbit traffic), not a real DLCI-coverage gap;CAP-006's DLCI 0x0c traffic noted as in-scope-elsewhere, out-of-scope for that ANC-focused session. - Added
TESTPLAN_BLUETOOTH_HCI_SNOOP.md§9 open item andCAPTURE_BLUETOOTH_HCI_SNOOP.mdGroup Y (GATT-002) for isolating whether theCAP-016-discovered0x0044BLE notification burst is triggered by BLE connection alone — a second-review suggestion adopted after independent verification confirmed the reviewer's own re-derivation.
- Status-taxonomy unification: 🔴 OPEN QUESTION formally added as a
fourth confidence tier in
-
2026-08-21: 8 new captures analyzed (
CAP-011,CAP-019–CAP-025, Groups Q/C/F/G/H/I/J/K), closing out most of the app's remaining main-run-through command coverage. Headline finding: a general-purpose DLCI 0x02 settings-write envelope (field5{field4{...}}) identified and confirmed across 9+ distinct settings — Conversation Detection, Multipoint (CAP-019), Touch controls, Head gestures (CAP-020), per-earbud press-and-hold + ANC-mode rotation (CAP-021), Mono audio, Volume EQ, Volume balance (CAP-022), In-ear detection, and both Case-sound settings (CAP-024) — each now has its ownPROTOCOL.md§4.5 subsection (§4.5.1–§4.5.8) in place of the previous bare unmapped-feature bullet list.PROTOCOL.md§4.4 (Find My Buds) confirmed for Left/Right (CAP-025, video-correlated, proposed for 🟢 FACT pending maintainer sign-off), with a notable new finding that Case/"both simultaneously" route through a separate, likely GMS/account-mediated Find Hub mechanism rather than the local Ring command — flagged as a possible Zero-GMS hard limit.CAP-023resolvedPROTOCOL.md§0.1's long-open wire-baseline-vs-UI-baseline firmware-version question (on-screenrelease_5.203matches the already-documented DLCI 0x08 string, same session) and found the firmware-check UI is cached, not live-queried (clean negative finding).CAP-011's passive-BLE-scan attempt for the Battery Notification advertisement was inconclusive — a procedure deviation (active connection present throughout) and a structural non-match against the documented byte layout, recorded honestly rather than force-fit; a clean repeat is still needed. Two gaps explicitly flagged rather than silently left blank:CAP-023never visited the "About" (serial numbers/connection status) screen (FW-003/FW-004), andHOLD-005's 16-frame ANC-rotation-checklist burst can't be split between Left's and Right's lists from wire content alone. ~10 new open questions added toPROTOCOL.md§6. -
2026-08-22/23: external audit and maintainer-directed remediation. A full-repository audit (all governance/protocol docs, all 19 real captures, external spec validation) produced a report (
AUDIT_REPORT_2026-08-22.md, a working artifact — not committed alongside this batch, its findings are captured here and in the specific entries below it made). Independent re-derivation of three wire-level claims (DLCI 0x02 CRC-32,CAP-006's ANC frame count, aCAP-015EQ quintet) against raw captures found no discrepancies; external verification of 13 technical claims against the Bluetooth Core Spec, Google's Fast Pair spec, Pigweed source, and Android/AOSP docs confirmed 11 outright, clarified one (BluetoothDevice.ACTION_BATTERY_LEVEL_CHANGEDis@SystemApi-gated, though the literal broadcast string remains usable by third-party apps), and found one genuine error:PROTOCOL.md§2.1/§4.4's cited "spec worked ACK example" for the Ring/Find My Buds command did not match Google's actual specification — corrected via dated notes (neither observedCAP-025ACK variant actually matches the real spec example either; §6's open item on the extra byte was reopened against the corrected 4-byte tail). Maintainer reviewed the report and directed all recommendations be carried out:TESTPLAN_BLUETOOTH_HCI_SNOOP.md: 9 stale EQ-row Evidence columns (EQP-003–EQP-007,EQS-001/002/003/005) updated to point atPROTOCOL.md§4.2, which had confirmed them sinceCAP-015(2026-08-18) without the catalog being updated to match; EQ band/preset naming reconciled against the actual on-screen labels (screenshot-verified: "Upper treble" not "High treble", "Default" not "Standard", "Light bass" for Bass Reduction).DECISIONS.mdADR-010 added (PROJECT_RULES.mdrule 19 does not apply to the maintainer's owncaptures/data — a real conflict withCONTRIBUTING.md's existing, already-practiced policy that had never been formally recorded as the ADRPROJECT_RULES.mditself requires for a knowing deviation); rule 19's text cross-linked to it and its stale.gitignorereference corrected.PROTOCOL.md§4.3 Option C annotated to explain why DLCI 0x08 and DLCI 0x09 are both legitimately called "channel 4" (one RFCOMM multiplexer session, disambiguated by direction bit — confirmed viatshark, not a numbering error); Option D gained the Battery Level characteristic UUID (0x2A19) alongside the already-documented service UUID (0x180F); §6 gained a refined, still-HYPOTHESIS-level characterization ofCAP-021's unexplained DLCI 0x0a burst (timing/direction/entropy profile suggesting a segmented bulk-data transfer).TODO.md's stale "not yet reviewed" checklist item closed (the work it was waiting on completed 2026-08-20, but the checkbox was never updated).REVERSE_ENGINEERING.md's APK keyword list gained HID-related classes, matching the project's already-live HID hypothesis;README.mdandCAPTURE_BLUETOOTH_HCI_SNOOP.mdgained minor completeness/staleness fixes (non-standard per-capture artifacts, the full Group A–Z range).PROJECT_RULES.mdrule 4a clarified: aPROTOCOL.mdrestatement pointing at an already-compliantCAP-NNN-FINDINGS.mdsatisfies the hex-and-script rule without duplicating the hex inline.- Tooling:
scripts/lint_docs.pygained a check for Markdown image-syntax references (it previously only checked backtick-quoted filenames, missing how theSCREENSHOTS_*.mdfiles referenceimages/), and.github/workflows/lint-docs.ymladded so it actually runs in CI.
-
2026-08-23: maintainer sign-off session — three pending FACT promotions reviewed and approved, each recorded with its own
DECISIONS.mdADR perAGENTS.md§6:- Find My Buds Left/Right (
PROTOCOL.md§4.4) → 🟢 FACT (ADR-011). Case/"both simultaneously" remains a separate, unresolved (likely Find-Hub-mediated) mechanism, not covered by this promotion. - Wire-baseline firmware version
"release_5.203"(PROTOCOL.md§0.1,CAP-023) → 🟢 FACT (ADR-012)."Revision 6"'s meaning stays open, unaffected. - DLCI 0x02's general-purpose settings-write envelope shape (
PROTOCOL.md§4.5's shared preamble) → 🟢 FACT (ADR-013) — narrowly scoped to the outerfield5{field4{...}}}wrapper only. The maintainer explicitly declined to blanket-promote the 9+ individual field mappings at the same time; each stays its own, separately-labeled 🟡 HYPOTHESIS, graded by actual evidence strength per setting (§4.5.1–§4.5.8 unchanged).
- Find My Buds Left/Right (
-
2026-08-23:
CAP-011re-analyzed after the maintainer spotted a 1% battery drop for both earbuds in the session recording. A frame-by-frame video re-derivation corrected the timestamp from an initial "~09:45:47" estimate (actually just the screen's first-opened values) to the actual change at 09:52:25.8. Wire analysis around that moment found a DLCI 0x08 private-envelope message (Group 0x0e Code 0x01) whose first two entries track the on-screen Left/Right percentages across all 4 occurrences in the log (including a further decline, 88%→87%→86%, in two off-camera recurrences), cross-confirmed by a second message (Group 0x04 Code 0x03). Cross-checked same day againstCAP-001/CAP-002(both 2026-08-09) and found a clean 3-for-3 match — the message's 3rd entry is Case, not just Left/Right — upgrading this from a single-session to a 3-session, 12-day-spanning finding (CAP-011's own Case entry reads stale in that one session, flagged as its own anomaly, not treated as contradicting the mapping). Refines an already-known-but-undecoded message shape first seen inCAP-002-FINDINGS.md§2a (2026-08-12), not a newly-discovered packet type. Reviewed and approved by the maintainer the same day — promoted to 🟢 FACT (DECISIONS.mdADR-014) for the index→Left/Right/Case mapping specifically;CAP-011's stale Case reading, theflagfield's meaning, and the burst's trigger stay open, unaffected by the promotion. -
2026-08-30: Phase 2 (APK reverse engineering) groundwork — governance, storage, and procedure. The maintainer explicitly requested AI assistance with the mechanical parts of APK decompiling and proto-schema extraction;
DECISIONS.mdADR-017 (superseding ADR-003, sign-off obtained on the exact wording before it was added) records the new boundary: an AI session may search, list candidates, runpbtk, and explain already-surfaced code or native.sodisassembly output — the maintainer explicitly placed native.sodisassembly assistance in scope too — but never decides relevance or promotes aREVERSE_ENGINEERING.mdfinding;AGENTS.md§6/§15's FACT/ADR sign-off requirement is unchanged. Also added:WORKSTATION_PREPARATIONS.md's pbtk section, corrected against pbtk's own README rather than assumed (it has two extractors — Java/DEX and native-binary-with-reflection-metadata — so native.soextraction isn't ruled out the way this project first assumed, only unconfirmed againstlibmaestro/libgfpsspecifically); a versioned APK storage layout (reverse-engineering/apk/v<versionName>-<versionCode>/, indexed in the git-trackedreverse-engineering/APK_VERSIONS.md; the APK/decompiled/pbtk output itself is never committed, per an updated.gitignorecovering the wholereverse-engineering/apk/tree);APK_REVERSE_ENGINEERING_PROCEDURE.md(pull/store → diff-against-previous-version → decompile →pbtkextract → keyword search, with an explicit out-of-scope exclusion list for AccountLinking/OwnershipTransfer/AccessoryNonOwner/Firebase-Analytics-Crashlytics); andREVERSE_ENGINEERING.mdtemplate updates (mandatory file+line citations, a per-finding hypothesis-to-capture-test link, and the same non-destructive-rewrite-in-place conventionCAP-NNN-FINDINGS.mdfiles use).TODO.md's Phase 2 checklist updated to reflect this groundwork without checking off any actual analysis work, since no APK has been pulled yet. -
2026-08-30: Tier 0 (existing-capture re-decode) + Tier 2 (
qjc/qja's remaining oneof groups) static-analysis session, then four pending FACT promotions reviewed and approved by the maintainer per-point (AGENTS.md§6), recorded inDECISIONS.mdADR-019: §2.2a — DLCI 0x02'sfield5{field4{...}}wrapper's "..." confirmed 🟢 FACT to belibmaestro's own recoveredWriteSettingschema (qhr), byte-decoded for 2 sampled fields (4, 29) againstCAP-020. §4.5.3 — the top-level "Use touch controls" toggle (field 4) and the press-and-hold action-selection opcode (field 7/qju, with a correctedqik→qhonesting level) promoted to 🟢 FACT in full, each backed by both wire+video correlation and a self-describing app-code log message. The ANC-mode-rotation-checklist opcode's field number (field 12/qht) promoted to 🟢 FACT; its equivalence to the app's own "ANC gesture loop" name explicitly declined by the maintainer, staying 🟡 HYPOTHESIS. Separately (Tier 2, not promoted, static-analysis-only): found thatqjc/qja's other 4 oneof groups (qhx/qjn/qjt/qjv) are very likely an alternate product's settings schema, not additional Buds Pro 2 categories — the app'sfyasettings-write interface has 3 disjoint, DI-separated implementations, one per product variant, andqjn's own internal codename (found in a log string) is literally "presto."qjvconfirmed fully unused in this app version (zero construction sites anywhere in the decompiled tree). -
2026-08-30:
CAP-027(Group N, touch gestures) captured and analyzed.TOUCH-002–TOUCH-006(tap/double-tap/triple-tap/swipe forward/swipe backward) confirmed 🟢 FACT as standard AVRCPPass Through/RegisterNotification(VolumeChanged)traffic — a spec-compliant profile carried over its own L2CAP PSM, not an RFCOMM DLCI at all, the single most important structural finding of this capture.TOUCH-007(press-and-hold) instead rides DLCI 0x04's official Fast Pair Message Stream, Group0x08Code0x13("Notify ANC state") — the same shapePROTOCOL.md§4.1 already documents for app-driven ANC taps, now also confirmed produced by the hardware gesture itself. SeeCAP-027-FINDINGS.md. -
2026-08-30:
CAP-033(Group AA, SDP isolation) captured and analyzed. Tested whether the companion app's own "MAESTRO APP"/"default" internal-RFCOMM-socket SDP UUIDs (DECISIONS.mdADR-018) are visible in an OS-only, app-force-stopped SDP browse (SDP-001) — result capped at 🟡 HYPOTHESIS by two isolation issues (Forget performed before Force-stop, not after as the procedure requires; step 3's app-open baseline comparison never executed), so this is not yet a clean answer either way; a repeat is needed. The browse's full named-service table is new, previously undocumented content: it independently corroborates ADR-018's DLCI 0x02 = "MAESTRO APP" finding at the wire/SDP level (not just APK code), and names DLCI 0x08 "GSND CONTROL" and DLCI 0x0a "GSND AUDIO" for the first time — new leads forPROTOCOL.md§2.3's/§6's open DLCI-0x08-identity question, proposed for maintainer review, not committed as a promotion. SeeCAP-033-FINDINGS.md. -
2026-09-01:
CAP-034(Group W, 4th attempt) captured and analyzed — resolves the0x0c0X/0x0f2XGATT handle↔UUID mapping, maintainer sign-off obtained. CombinedCAP-014's confirmed-unlimited HCI snaplen with Group W's own long-untried cache-busting method (pm clear com.android.bluetoothon a Pixel 9a never before connected to this Buds unit) for the first time. The resulting discovery burst resolves the full 15-primary-service GATT profile:0x0c00–0x0c14= Google Fast Pair Service (all 5 spec-defined characteristics, plus Message Stream PSM and one still-unnamed characteristic),0x0f20–0x0f2a= Device Information,0x0f30–0x0f33= Battery Service. Corrects an earlierCAP-017-FINDINGS.mdhypothesis that "Unknown Service" (109b862f-…) contained this cluster — it occupies a separate handle range and its own purpose remains unidentified. SeeCAP-034-FINDINGS.mdandPROTOCOL.md§4.3 Option D/§6. -
2026-09-02:
CAP-035(Group AB, GMS-independence check) captured and analyzed, maintainer sign-off obtained. Tested whether DLCI 0x08 ("GSND CONTROL")/0x0a ("GSND AUDIO")/0x06 ("DEBUG APP")/0x12 ("BTIS") depend on Google Play Services, on a GrapheneOS phone with GMS present butdumpsys-verified disabled. DLCI 0x08's content reproduces byte-identical across a fresh connect and a reconnect; DLCI 0x0a opens in lockstep but stays payload-silent both times; DLCI 0x06/0x12 never open at all — clean negatives for both, the first time either has been specifically checked. Strengthens (does not fully close)CAP-004-FINDINGS.md§4a's existing "GMS present but disabled" finding — a repeat with GMS genuinely uninstalled would close it fully. SeeCAP-035-FINDINGS.md. -
2026-09-03: documentation audit remediation (maintainer-directed fixes following a 2026-09-02 documentation audit): registered
CAP-034/CAP-035inid_registry.csv(both had full Capture Index rows and were cited throughoutPROTOCOL.md/TESTPLAN_BLUETOOTH_HCI_SNOOP.mdbut were never added to the registry); fixed a live CI "Lint docs" failure (added the deliberately-referenced, deletedREVIEW_REPORT.mdtoscripts/lint_docs.py's historical-reference allowlist; repairedCAP-035-EVENT-NOTES.md's footer, which pointed at a truncated folder path); corrected a stale, self-contradictory "not yet traced" note inREVERSE_ENGINEERING.md's Call graph notes section (thefsz/fux→MethodClientchain it described as untraced had in fact been fully traced earlier in the same document); populatedREVERSE_ENGINEERING.md's previously-empty "Native libraries" table from the already-documented finding; added the missing extraction commands and raw hex toCAP-008-FINDINGS.md's HFP-handshake and eSCO-setup sections, perPROJECT_RULES.md§1's hex-and-script rule (all of that capture's original conclusions were independently re-verified and confirmed correct in the process); refreshed two staleTODO.mdstatus descriptions (the UUID register is no longer an empty template; the APK keyword-search pass has grown well past its originally-cited class-entry count).DECISIONS.mdADR-020 — EQ'sFrameEncoder/FrameDecoderimplementation explicitly unblocked, closing a gap whereADR-016had promoted EQ's protocol knowledge to FACT without ever stating theARCHITECTURE.md§5 implementation gate was cleared (unlike ANC/ADR-009and Find My Buds/ADR-011); no new protocol knowledge, maintainer-approved. -
2026-09-06:
CAP-037–CAP-042(Groups AD–AI) captured and analyzed — six purpose-built repeats ofCAP-036's own open questions. No new FACT promotions; large-scale replication of already-FACT findings (CAP-037: 26/26 same-sessionADR-022/ADR-024replications;CAP-039: 10 same-sessionADR-024Set-vs-Get samples) plus several new open items (DLCI 0x08's unmapped Get-shaped codes still unattributed; the app's in-app Connect/Disconnect buttons producing zero wire signal; aSettable-togglesreading in tension withADR-024immediately after physical case-removal; DLCI 0x02's connect-time burst shown length-invariant across differing settings states; the periodic cross-channel push shown far sparser over a genuinely idle window thanCAP-036's short sample suggested). See each capture's own findings file. -
2026-09-07: project-wide audit + cross-validation review cycle, processed and closed out.
AUDIT_REPORT_2026-09-07.md(this session's own Phase-1/Phase-2 audit, cross-checkingCAP-037–CAP-042against the decompiled APK source and auditing the project documentation) andANTIGRAVITY_AUDIT_REPORT_2026-09-07.md(an independent external review, Antigravity/Gemini 3.1 Pro) were cross-validated against each other inEXTERNAL_REVIEW_VALIDATION_2026-09-07.md, which rejected the external review's🟢 FACT-labeledmaestro_pw.Maestroconnect-burst-identity claim (an evidentiary overclaim and a governance violation — an AI report self-assigning FACT status and recommending an ADR, whichAGENTS.md§6/DECISIONS.mdADR-017 do not permit) and itsREVIEW_REPORT.md/"active workspace state" item (not a genuine finding about this repository). Confirmed findings were applied directly:DECISIONS.mdADR-025 records that Google Play Services reverse-engineering is out of scope (no DLCI 0x04/0x08 transport code was found anywhere in the companion app's own decompiled source — both channels are implemented clean-room, from wire evidence alone, exactly as ANC/Find My Buds/EQ already are), with a matchingPROJECT.mdnon-goals bullet and anARCHITECTURE.mdnote correcting the external review's "Impossibility" mischaracterization of this same situation.PROTOCOL.md§8's changelog backfilled for 2026-09-04/05/06; §4.3 Option C's HFP DLCI corrected from a fixed0x09to session-local (0x0cin the clear majority of captures); §6 gained aqhr-field-13 candidate forCAP-038's unexplained ANC Notify frames, an app-foreground-vs-IPC refinement forCAP-042's open push-cadence question, and themaestro_pw.Maestroburst-identity claim recorded at the🟡 HYPOTHESISlevel the evidence actually supports (not the rejected🟢 FACT).README.md's two dangling references to a never-existent roadmap file removed and its "Current state" snapshot refreshed;TESTPLAN_BLUETOOTH_HCI_SNOOP.md§9's staleOBS-002open-item removed;reverse-engineering/APK_VERSIONS.md/WORKSTATION_PREPARATIONS.md'spbtkroot-cause explanation reconciled withTODO.md's more precise diagnosis;REVERSE_ENGINEERING.mdgained a missing###header, a note explaining why the Message Group/Code register stays empty for DLCI 0x04/0x08, and a low-priority citation-fragility note. All three review documents retired after processing (same lifecycle asAUDIT_REPORT_2026-08-22.md) — added toscripts/lint_docs.py's historical-reference allowlist so the citations to them throughout the docs above don't lint as dead references.
PROTOCOL_NOTES.md,EXPERIMENTS.md(retired 2026-08-15, see above).AUDIT_REPORT_2026-09-07.md,ANTIGRAVITY_AUDIT_REPORT_2026-09-07.md,EXTERNAL_REVIEW_VALIDATION_2026-09-07.md(retired 2026-09-07, see above — findings applied, historical references kept where cited).
https://github.com/tedsluis/opencontrolpixelbudspro2/blob/main/CHANGELOG.md - https://tedsluis.github.io/opencontrolpixelbudspro2/CHANGELOG