)]}'
{
  "log": [
    {
      "commit": "f7bd10420da33d59661daa773e8fbf432a1616af",
      "tree": "7fc26d7056ff33adf1fb1e6ff051568d7f6c72a2",
      "parents": [
        "cefd69ffd46085e63b369fc2ff70405fc18b6f3e"
      ],
      "author": {
        "name": "pigweed-roller",
        "email": "pigweed-roller@pigweed-service-accounts.iam.gserviceaccount.com",
        "time": "Sun Nov 01 04:35:05 2026 -0800"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Sun Nov 01 04:35:05 2026 -0800"
      },
      "message": "roll: luci\n\nbb\nFrom git_revision:013f9ed45de42a75ad1cbbe8f743fb5d7c418124\nTo git_revision:07586c787b4070ec84193aa135b68decb25a81ba\n\nluci-auth\nFrom git_revision:013f9ed45de42a75ad1cbbe8f743fb5d7c418124\nTo git_revision:07586c787b4070ec84193aa135b68decb25a81ba\n\ngerrit\nFrom git_revision:013f9ed45de42a75ad1cbbe8f743fb5d7c418124\nTo git_revision:07586c787b4070ec84193aa135b68decb25a81ba\n\ngitiles\nFrom git_revision:013f9ed45de42a75ad1cbbe8f743fb5d7c418124\nTo git_revision:07586c787b4070ec84193aa135b68decb25a81ba\n\ncas\nFrom git_revision:013f9ed45de42a75ad1cbbe8f743fb5d7c418124\nTo git_revision:07586c787b4070ec84193aa135b68decb25a81ba\n\nled\nFrom git_revision:013f9ed45de42a75ad1cbbe8f743fb5d7c418124\nTo git_revision:07586c787b4070ec84193aa135b68decb25a81ba\n\nswarming\nFrom git_revision:013f9ed45de42a75ad1cbbe8f743fb5d7c418124\nTo git_revision:07586c787b4070ec84193aa135b68decb25a81ba\n\nlogdog\nFrom git_revision:013f9ed45de42a75ad1cbbe8f743fb5d7c418124\nTo git_revision:07586c787b4070ec84193aa135b68decb25a81ba\n\nprpc\nFrom git_revision:013f9ed45de42a75ad1cbbe8f743fb5d7c418124\nTo git_revision:07586c787b4070ec84193aa135b68decb25a81ba\n\nluci-cv\nFrom git_revision:013f9ed45de42a75ad1cbbe8f743fb5d7c418124\nTo git_revision:07586c787b4070ec84193aa135b68decb25a81ba\n\nRoll-Count: 10\nRoller-URL: https://cr-buildbucket.appspot.com/build/8666336265476624193\nGitWatcher: ignore\nCQ-Do-Not-Cancel-Tryjobs: true\nChange-Id: Ibd75ae7a0dac3d9fee47f5d1cc714c0ba81128a3\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/519045\n"
    },
    {
      "commit": "cefd69ffd46085e63b369fc2ff70405fc18b6f3e",
      "tree": "76f7f195064e6a037e4fef03c7c3483606525dee",
      "parents": [
        "55873baa1b37eaf7d0a830515a0846e3fc3a79e2"
      ],
      "author": {
        "name": "pigweed-roller",
        "email": "pigweed-roller@pigweed-service-accounts.iam.gserviceaccount.com",
        "time": "Sat Oct 31 18:55:48 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Sat Oct 31 18:55:48 2026 -0700"
      },
      "message": "roll: ninja\n\nFrom git_revision:0fde9fdcbbd2c8ec826344fdedbe2bd615f162bf\nTo git_revision:0304bd8b8a780d29a065122cc6a2c7d900d0a4b9\n\nRoll-Count: 1\nRoller-URL: https://cr-buildbucket.appspot.com/build/8666376342213896673\nGitWatcher: ignore\nCQ-Do-Not-Cancel-Tryjobs: true\nChange-Id: I823cf72a5e37e6af180146f3223169a02d6fa076\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/518745\n"
    },
    {
      "commit": "55873baa1b37eaf7d0a830515a0846e3fc3a79e2",
      "tree": "854750392f5d6aff40b4866cff513de1bfe8617f",
      "parents": [
        "ae01bd7fe068c0b04910d585f53327732e72f01b"
      ],
      "author": {
        "name": "Anthony DiGirolamo",
        "email": "tonymd@google.com",
        "time": "Fri Oct 30 15:12:26 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Fri Oct 30 15:12:26 2026 -0700"
      },
      "message": "pw_env_setup: Add Python 3.14 pip_cache cipd package\n\nBug: 575911232\nChange-Id: I7e86cbdb7d344d3befa6da8fe797fa571f66af27\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/518067\n"
    },
    {
      "commit": "ae01bd7fe068c0b04910d585f53327732e72f01b",
      "tree": "931a9fdb77733293a44dc4492b4b7b890aa72369",
      "parents": [
        "a1060ec7e68be9652e9501616d9ea4ce09d263b2"
      ],
      "author": {
        "name": "Rob Mohr",
        "email": "mohrr@google.com",
        "time": "Fri Oct 30 14:03:40 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Fri Oct 30 14:03:40 2026 -0700"
      },
      "message": "OWNERS: Add erahm as owner\n\nAdd erahm@google.com to root OWNERS and pw_ghish/OWNERS.\n\nChange-Id: Ib6a67bd63770b88a9479ba1e900860b5b96ee198\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/518066\n"
    },
    {
      "commit": "a1060ec7e68be9652e9501616d9ea4ce09d263b2",
      "tree": "b489653f821accef8dfe822a0f9f17cb22f444f6",
      "parents": [
        "a3f28bf8255b22cd97e3430f5fb934de0a8591a3"
      ],
      "author": {
        "name": "Eric Rahm",
        "email": "erahm@google.com",
        "time": "Fri Oct 30 13:52:22 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Fri Oct 30 13:52:22 2026 -0700"
      },
      "message": "pw_ghish: Authenticate HTTPS git push with Gerrit OAuth2 tokens\n\nFresh clones and Corp Linux/macOS setups without `.gitcookies` fail\n`git push` over HTTPS with `terminal prompts disabled` or HTTP 401\neven when `luci-auth` has valid OAuth2 credentials.\n\nWhen `git push` to an `https://*.googlesource.com` remote fails with\nan authentication error, retry once with the Gerrit OAuth2 token in\n`http.\u003curl\u003e.extraHeader`. The first attempt uses the user\u0027s own git\ncredentials with terminal prompts disabled, and no token is attached\nwhen authentication is disabled (`--auth-mode\u003dnone`).\n\nAlso surface remediation for CLA push rejections and first-time Gerrit\naccount HTTP 400 responses in `gh auth status`, and treat an installed\n`/usr/bin/sso-cred-helper` as a `googler` auto-detection signal.\n\nBug: b/575891963, b/575892726, b/575892646\nChange-Id: I81d40ec2be0f819956a9291ea991d24cbb4add08\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/514149\n"
    },
    {
      "commit": "a3f28bf8255b22cd97e3430f5fb934de0a8591a3",
      "tree": "162baefea4fccd3592d3285a57b8b0191a1e4494",
      "parents": [
        "0545fb8204a9bdd589cfffc5c7a91bd46b6d6de0"
      ],
      "author": {
        "name": "Eric Rahm",
        "email": "erahm@google.com",
        "time": "Fri Oct 30 13:50:33 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Fri Oct 30 13:50:33 2026 -0700"
      },
      "message": "pw_ghish: Migrate Gerrit callers and tests to native GerritClient\n\nSwitch `NewGerritClient`, `ChangeContext`, `MockGerritServer`,\n`pw_ghish/worktree`, and all CLI commands and tests from `go-gerrit`\n(`*gerrit.Client`) to the native `*GerritClient`. Removing\n`SetReviewSafe`, legacy HTTP auth transports, and the `go-gerrit`\nmodule/Bazel dependency follows in pwrev/514150.\n\nCallers now check HTTP status codes via `IsGerritHTTPStatus` instead of\nscraping error strings and adopt `GerritClient`\u0027s existing per-request\nOAuth2 token refresh and anonymous GET fallback.\n\nUser-visible changes:\n- Gerrit REST auth now goes through `resolveGerritClientAuth`\n  (`GERRIT_TOKEN`, then `luci-auth` on Google hosts, else anonymous),\n  intentionally dropping `gob-curl`, `.gitcookies`, `.netrc`, and HTTP\n  Basic `user:pass` tokens for Gerrit REST.\n- Unauthenticated `pr status` skips personal owner/reviewer queries and\n  reports that the user is not signed in (`\"authenticated\": false` in\n  `--json`).\n- Unauthenticated `pr list` ignores any cached self-account ID.\n- Unauthenticated `pr status`, `pr view --comments`, and `gh sense` skip\n  draft comment lookups.\n- `auth status` avoids repeating `\"account #N (account #N)\"` when only a\n  numeric account ID is known.\n\nBug: b/575891963, b/575892646\nChange-Id: I087e1823c673a124d0beb7aa8b8a8d7f156ccc46\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/514158\n"
    },
    {
      "commit": "0545fb8204a9bdd589cfffc5c7a91bd46b6d6de0",
      "tree": "c7dbcbcdaac583002b1e8c5ed22d773113ce1ab1",
      "parents": [
        "cf264ce1f79533a6f4802b5b22c5c237a98e5561"
      ],
      "author": {
        "name": "Eric Rahm",
        "email": "erahm@google.com",
        "time": "Fri Oct 30 13:49:20 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Fri Oct 30 13:49:20 2026 -0700"
      },
      "message": "pw_ghish: Consolidate CLI command tests onto MockGerritServer helpers\n\nMigrate CLI command tests onto the declarative `MockGerritServer`\nmethods (`OnDefaultChange`, `OnReview`, `OnComments`, `OnDrafts`,\n`OnAccountSelf`, `OnSearchBuilds*`), `DecodeRequest`,\n`NewKindSmokeFixture`, and `MockGitRunner` builders, and collapse\nrepetitive per-flag test functions into table-driven subtests. Also make\n`OnSearchBuildsByPatchset` fail on unlisted patchsets or\n`len(GerritChanges) !\u003d 1`.\n\nBeyond the mechanical migration:\n- Remove redundant tests or fold them into existing suites:\n  `TestDefaultViewTemplate` (field order remains pinned by\n  `TestGolden_PrView`), `TestStatusIntegration`,\n  `TestStatus_WritesToCmdOut`, `TestView_WritesToCmdOut`,\n  `TestListIntegration` (folded into `TestList_WritesToCmdOut`),\n  `TestChecks_Watch_FailFast` (folded into\n  `TestChecks_Watch_FailFast_BreadcrumbAndDiagnostics`), and the\n  separate `TestStatus_CurrentBranch_WithComments_*` / `WithDrafts`\n  functions (consolidated into sibling subtests of\n  `TestStatus_CurrentBranch_WithCommentsAndDrafts`).\n- Update scenarios: `TestChecks_Watch_FailFast_BreadcrumbAndDiagnostics`\n  adds a second builder to verify `[1/2]` progress,\n  `TestEdit_CQAndTrigger` and `TestReviewCmd_FlagsAndLabels` explicitly\n  distinguish `WithLabels` change detection from 404 fallback (plus a\n  `trigger explicit` row), `TestMergeIntegration_LabelSelection`\n  verifies `DETAILED_LABELS` query options, and\n  `TestPerfBudget_Commands` runs on `NewKindSmokeFixture`.\n- Document shared test-harness guidance in `pw_ghish/AGENTS.md` and\n  `.agents/agents/go_ghish_reviewer.md`.\n\nBug: b/575891963\nChange-Id: I0257a0922d52cdfb8a6678a3b32d7abc5a00a273\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/514157\n"
    },
    {
      "commit": "cf264ce1f79533a6f4802b5b22c5c237a98e5561",
      "tree": "dc27dec28867a87fa68ec81b3d2f25fa85d272b1",
      "parents": [
        "8c5ad81bc9a0dffbc3226ec138bd2959d52a64d8"
      ],
      "author": {
        "name": "Anthony DiGirolamo",
        "email": "tonymd@google.com",
        "time": "Fri Oct 30 12:25:45 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Fri Oct 30 12:25:45 2026 -0700"
      },
      "message": "python: Update tooling and build configs for Python 3.11\n\nUpdate Black, Ruff, Bazel pip.parse, pw_doctor, pw_env_setup, and Python\ndistributable scripts to target Python 3.11 as the minimum supported\nversion.\n\nBug: 575911232\nChange-Id: I0418b380054418853c749ca87bea7c9ad3a846df\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/517345\n"
    },
    {
      "commit": "8c5ad81bc9a0dffbc3226ec138bd2959d52a64d8",
      "tree": "05c865accbf0c0604302cba090d86ca820036de9",
      "parents": [
        "e88eccbee4f8666717101a24d3bb53717f715870"
      ],
      "author": {
        "name": "Wyatt Hepler",
        "email": "hepler@google.com",
        "time": "Fri Oct 30 12:19:33 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Fri Oct 30 12:19:33 2026 -0700"
      },
      "message": "pw_enum: Load and resolve JSON enum definitions\n\nAllow defining enums in language-neutral JSON files so C++ firmware and\nPython host tools can share a single source of truth.\n\npw_enum.json_source validates JSON enum files, evaluates constant\ninteger expressions with cycle-checked references across enums and\ndependencies, enforces protobuf-style explicit aliasing, and resolves\ndefinitions into EnumDescriptor objects.\n\nChange-Id: Ie2fed2fceb024c99848c95622f84b51fed5eac50\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/512105\n"
    },
    {
      "commit": "e88eccbee4f8666717101a24d3bb53717f715870",
      "tree": "d045e7ffbcfd567a597fdd0fc35539ea99f4d717",
      "parents": [
        "a3ee103b7aea55693cf45e2791041a33eb8db56a"
      ],
      "author": {
        "name": "Yen-Pu Wang",
        "email": "yenpuwang@google.com",
        "time": "Fri Oct 30 11:49:30 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Fri Oct 30 11:49:30 2026 -0700"
      },
      "message": "pw_bluetooth_sapphire: Disallow BR/EDR CTKD during LE pairing\n\nDisallow BR/EDR cross-transport key derivation in SecurityManagerImpl\nwhile Low Energy pairing is in progress for the same peer. Re-check\neligibility after SMP feature exchange, on incoming Phase 3 key PDUs\n(before Initiator distributes local keys), and before storing the\nderived LE bond.\n\nPreviously IsBrEdrCrossTransportKeyDerivationAllowed only considered a\nstored LE bond, so CTKD could derive and store an LE key while LE\npairing with the same peer was still in progress.\n\nFix: 521638450\nTest: bazelisk test --config\u003dgoogletest \\\n        //pw_bluetooth_sapphire/host/sm:sm_test\nChange-Id: Ib3cbf942ff6fffe82137d8c90b1ba5cc118ffb47\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/516965\n"
    },
    {
      "commit": "a3ee103b7aea55693cf45e2791041a33eb8db56a",
      "tree": "f95cfa423978c618b143fd92d925ae72ad2d2bdb",
      "parents": [
        "b2490dd66bbc42872685e9ba4b8b324fe7c33027"
      ],
      "author": {
        "name": "Wyatt Hepler",
        "email": "hepler@google.com",
        "time": "Fri Oct 30 11:49:09 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Fri Oct 30 11:49:09 2026 -0700"
      },
      "message": "pw_codegen: Utilities for source code generation\n\nConsolidate low-level code generation functionality and unit tests from\nvarious modules into the pw_codegen module, supporting C++, Java,\nPython, Rust, and TypeScript.\n\nChange-Id: Id71c38d29ca9d71fb3ec67e9cf922c8fe8bccd10\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/516005\n"
    },
    {
      "commit": "b2490dd66bbc42872685e9ba4b8b324fe7c33027",
      "tree": "faca5c58a9ba4e6746ecb82ae9b31d6028266be6",
      "parents": [
        "bf43d52c9558989f5771bd3acf140dd55b29bc33"
      ],
      "author": {
        "name": "Amit Uttamchandani",
        "email": "amituttam@google.com",
        "time": "Fri Oct 30 11:48:52 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Fri Oct 30 11:48:52 2026 -0700"
      },
      "message": "agents: Enable default multi-perspective review agent\n\nAdd a default `use_default_subagents: true` entry to\n.agents/code-review/agent_configs.textproto so CRACS attaches the\ndefault multi-perspective review orchestrator (6 reviewer perspectives\nand 2 verifiers, matching Fuchsia and Turquoise) instead of running\nPigweed\u0027s code_review skill as a single-pass reviewer.\n\nExisting path-matched Pigweed skills (code_review, pw_async2,\npw_rpc_creating_services, bluetooth, docs) continue to be injected into\neach perspective. End-to-end review latency increases from ~5 minutes\nto ~10-15 minutes.\n\nBug: b/577217936\nChange-Id: I07b9f339958a3a95c782493020339d02b6c873b7\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/516245\n"
    },
    {
      "commit": "bf43d52c9558989f5771bd3acf140dd55b29bc33",
      "tree": "bd86e1d89062d5fcd74922360e5bc9dae86a2ad2",
      "parents": [
        "2ab1ef3e2ec8c777c1e830b5a00b9fda299b3c7c"
      ],
      "author": {
        "name": "Yen-Pu Wang",
        "email": "yenpuwang@google.com",
        "time": "Fri Oct 30 11:47:19 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Fri Oct 30 11:47:19 2026 -0700"
      },
      "message": "pw_bluetooth_sapphire: Reject BR/EDR SSP during LE pairing\n\nReject peer-initiated BR/EDR Secure Simple Pairing in\nSecureSimplePairingState while Low Energy pairing is in progress for\nthe same peer, without disconnecting the BR/EDR link or dropping queued\nlocal pairing requests.\n\nPreviously InitiateNextPairingRequest deferred locally initiated BR/EDR\nSSP while LE pairing was active, but OnIoCapabilityResponse still\naccepted peer-initiated SSP and enabled automatic Just Works\nconfirmation on outgoing links.\n\nBug: 521638450\nTest: bazelisk test --config\u003dgoogletest \\\n        //pw_bluetooth_sapphire/host/gap:gap_test\nChange-Id: I9d0d5aef4b35b16dca4bbd1fa7472394a3d1d831\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/516945\n"
    },
    {
      "commit": "2ab1ef3e2ec8c777c1e830b5a00b9fda299b3c7c",
      "tree": "7d2b545c516b8930bb20394f25f1556edda63826",
      "parents": [
        "22b46643eb52183e7b8aa9bf7bc53bf7cde388aa"
      ],
      "author": {
        "name": "Marie Janssen",
        "email": "jamuraa@google.com",
        "time": "Fri Oct 30 11:43:57 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Fri Oct 30 11:43:57 2026 -0700"
      },
      "message": "pw_bluetooth_sapphire: Enforce AES-CCM on bonded SC reconnect\n\nOn reconnections with a bonded BR/EDR peer that uses Secure\nConnections, the host recalled stored P-256 keys without updating\nuse_secure_connections_ on the new AclConnection. This allowed a\ncompromised controller or on-path attacker to downgrade link\nencryption to the E0 cipher while upper layers treated the link as\nSecure Connections.\n\nConfigure use_secure_connections_ when returning recalled link keys to\nthe controller. In Secure Connections Only mode, require stored keys to\nbe authenticated Secure Connections keys with 128-bit key size. Verify\nthat active encryption uses AES-CCM in CompletePairingRequests and key\nrefresh handlers, and reject re-pairing attempts that downgrade bonded\nSecure Connections peers to legacy keys. Guard encryption checks to\npreserve controller error codes on failure.\n\nBug: b/523274972\nChange-Id: I60b40178c3702c52efa1a12ad40700086a6a6964\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/516145\n"
    },
    {
      "commit": "22b46643eb52183e7b8aa9bf7bc53bf7cde388aa",
      "tree": "8fdd487713587f6131feb6d6e0661bfc207db01f",
      "parents": [
        "3f1e1a0797e4583785e8a1e4dd84455932c1f4e0"
      ],
      "author": {
        "name": "Andrew Ellem",
        "email": "aellem@google.com",
        "time": "Fri Oct 30 11:04:39 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Fri Oct 30 11:04:39 2026 -0700"
      },
      "message": "pw_tokenizer: Append to default linker script on Linux in Bazel\n\nAdd explicit tokenizer_linker_sections and\nadd_tokenizer_sections_to_default_script pw_linker_script targets in\npw_tokenizer/BUILD.bazel, and update @pigweed//pw_tokenizer:linker_script\nto select between them based on @platforms//os:linux (matching the\nexisting GN and CMake behavior).\n\nWithout INSERT AFTER .debug_info, passing the tokenizer linker script to\nthe host linker on Linux (such as in Zephyr native_sim builds) replaces\nthe default host linker script instead of augmenting it.\n\nChange-Id: Id43351361b0a82ae89f904aac95e7db0fa913126\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/517985\n"
    },
    {
      "commit": "3f1e1a0797e4583785e8a1e4dd84455932c1f4e0",
      "tree": "3c9cd48012bdab1b3c6ee79cbf819be9e37f1785",
      "parents": [
        "f13a3f8b9415733382cc3a4f542ba99bc05523ad"
      ],
      "author": {
        "name": "Eric Rahm",
        "email": "erahm@google.com",
        "time": "Fri Oct 30 10:35:07 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Fri Oct 30 10:35:07 2026 -0700"
      },
      "message": "pw_env_setup: Set PW_ROOT before _PW_ENVIRONMENT_CONFIG_FILE\n\nGenerated activation scripts previously referenced $PW_ROOT in\n_PW_ENVIRONMENT_CONFIG_FILE before defining PW_ROOT. Sourcing\nenvironment/activate.sh directly in a fresh shell (without bootstrap.sh\npre-setting PW_ROOT) resolved _PW_ENVIRONMENT_CONFIG_FILE to\n\"/pigweed.json\" and failed under set -u.\n\nDefine PW_ROOT and PW_PROJECT_ROOT before _PW_ENVIRONMENT_CONFIG_FILE,\nand avoid exporting PW_ROOT twice when it is also configured as the\nproject\u0027s root_variable.\n\nBug: b/576053529\nChange-Id: I3862fc1ae7efe260c48de6af76c56aa6abaff6e4\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/516067\n"
    },
    {
      "commit": "f13a3f8b9415733382cc3a4f542ba99bc05523ad",
      "tree": "b217cf38896c3aca5dbc4bfed84cc65576b90ec0",
      "parents": [
        "3f48252c102b61bae8229fa43e0449cad21f6e74"
      ],
      "author": {
        "name": "Eric Rahm",
        "email": "erahm@google.com",
        "time": "Fri Oct 30 10:33:36 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Fri Oct 30 10:33:36 2026 -0700"
      },
      "message": "pw_env_setup: Respect PW_ENVSETUP_QUIET when skipping doctor\n\nSkipping environment checks via PW_ACTIVATE_SKIP_CHECKS previously\nprinted a notice unconditionally, polluting stdout in non-interactive\nshells even when PW_ENVSETUP_QUIET was set (and failing under set -u\nwhen PW_ACTIVATE_SKIP_CHECKS was unset).\n\nSuppress the skip notice when PW_ENVSETUP_QUIET is set and make the\ncheck safe under set -u.\n\nBug: b/576053529\nChange-Id: Ic59df3af1b3b04ae824d9d2090b7f04831495055\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/516066\n"
    },
    {
      "commit": "3f48252c102b61bae8229fa43e0449cad21f6e74",
      "tree": "d511ccfefd54b6ee60a556ed30956cfce4305227",
      "parents": [
        "0bdc22deb313034d56efa514896b8759bd3aa3ee"
      ],
      "author": {
        "name": "Yuval Peress",
        "email": "yuval.peress@gmail.com",
        "time": "Fri Oct 30 09:56:54 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Fri Oct 30 09:56:54 2026 -0700"
      },
      "message": "zephyr: 4.4 migration and build system cleanup\n\nZephyr 4.4 generates headers such as heap_constants.h at build time, so\nanything that includes Zephyr headers has to build after\nzephyr_generated_headers. pw_add_library_generic() now adds that\ndependency to every non-INTERFACE library in a Zephyr build.\n\npw_zephyrize_libraries_ifdef() no longer links libraries into\nzephyr_interface. A static library linked into zephyr_interface creates\na dependency cycle with Zephyr\u0027s header generators. Instead, the\nlibraries get Zephyr\u0027s compile flags and include paths, and Zephyr\u0027s\nsources get theirs through $\u003cCOMPILE_ONLY:...\u003e, which needs CMake 3.27\n(Zephyr 4.4 requires 3.28). That keeps headers such as an application\u0027s\nzephyr_custom_log.h visible to all of Zephyr, and replaces the include\npaths pw_log_zephyr added to zephyr_interface by hand.\n\nPigweed libraries are also no longer added to ZEPHYR_LIBS, whose\n--whole-archive linking turns harmless static-library cycles (such as\npw_rpc and pw_log) into \"multiple definition\" errors. They now link by\nreference, as on other build systems. Two exceptions remain, for code\nthe application can\u0027t declare a dependency on:\n- pw_sys_io_zephyr registers itself with SYS_INIT and has no callers.\n- pw_log_zephyr.pigweed_overrides, when Zephyr\u0027s log macros are mapped\n  to Pigweed. Zephyr\u0027s own code then logs through pw_log, so the\n  overrides library depends on pw_log (with its backend) and\n  pw_hex_dump.log_bytes.\n\nLinking by reference exposed missing dependencies:\npw_sys_io.default_putget_bytes now depends on pw_sys_io,\npw_system.init on pw_system.target_hooks, and\npw_log_zephyr.tokenized_handler on pw_sync.interrupt_spin_lock.\n\nEach Zephyr facade\u0027s backend is now a Kconfig choice, so only one\nbackend can be selected per facade, and pw_set_zephyr_backend() fails\nthe build if two conditions set different backends. A choice with one\nPigweed backend defaults to it and has a _NONE member for projects that\nprovide their own. pw_sys_io defaults to none, since selecting its\nbackend always links it in. The tokenized log handler defaults to\npw_system\u0027s log backend when tokenized RPC logging is enabled, to none\nwith CONFIG_PIGWEED_LOG_TOKENIZED_LIB (the application provides it),\nand to Zephyr\u0027s otherwise. Backend wiring moves from the root\nCMakeLists.txt to zephyr/backends.cmake.\n\nChanges for downstream projects:\n- A Kconfig option can\u0027t `select` a backend anymore, since backends are\n  choice members. Choose the backend in prj.conf instead.\n- Enabling a CONFIG_PIGWEED_* option sets the backend but no longer\n  links it, as with pw_set_backend(). Code that uses a Pigweed library,\n  including prebuilt libraries from other build systems, links it.\n  See \"Linking libraries in a Zephyr build\" in\n  docs/sphinx/os/zephyr/backends.rst.\n- CMake 3.27 or newer is required.\n\nChange-Id: Ic743a9bb0c42865411a24f7b56b796af35d0b102\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/473645\n"
    },
    {
      "commit": "0bdc22deb313034d56efa514896b8759bd3aa3ee",
      "tree": "61850823b4fad6f6b8f05aea5f209d03cb0f7d4b",
      "parents": [
        "df0617c2b7c7038072a4c04964edcada516ead16"
      ],
      "author": {
        "name": "Devan Yu",
        "email": "devanyu@google.com",
        "time": "Thu Oct 29 22:22:08 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Thu Oct 29 22:22:08 2026 -0700"
      },
      "message": "pw_bluetooth_sapphire: Limit the number of temporary peers in PeerCache\n\nTemporary peers were only removed after a 60 second timeout, but the\ncache could still grow without bound within that window. Limit the\nnumber of temporary peers and remove the least recently updated one\nwhen a new peer would exceed the limit.\n\nBug: 42171643, 525193229\nTest: bazelisk test --config\u003dgoogletest\n      pw_bluetooth_sapphire/host/gap:gap_test\nChange-Id: Ifb85ffa30881b05e3e24787f5a9b5ffdbfc3ffe8\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/514405\n"
    },
    {
      "commit": "df0617c2b7c7038072a4c04964edcada516ead16",
      "tree": "908dfee0af9f0a585ff20c0c8535846f011946d0",
      "parents": [
        "2e54cc48ad41354d9702f004393f624427dc0061"
      ],
      "author": {
        "name": "Marie Janssen",
        "email": "jamuraa@google.com",
        "time": "Thu Oct 29 21:42:33 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Thu Oct 29 21:42:33 2026 -0700"
      },
      "message": "pw_bluetooth_sapphire: Harden Bearer transaction callbacks\n\nSynchronous destruction of a Bearer during transaction callbacks causes\nuse-after-free errors in HandleEndTransaction. In addition, starting\nqueued transactions while a security upgrade is in flight violates ATT\nsequentiality and reorders requests.\n\n- Resolve transaction queues through weak self pointers and move\n  callbacks to stack locals before invoking them.\n- Hold queued requests while security upgrades are in flight, and retry\n  elevated requests at the head of the queue.\n- Support safe handler self-unregistration by copying handler closures\n  before execution.\n- Erase unregistered handler IDs from handler_id_map_.\n\nBug: b/512561435\nChange-Id: I969cb0deeb7e22e7e7aab459453f57de6a6a6964\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/514891\n"
    },
    {
      "commit": "2e54cc48ad41354d9702f004393f624427dc0061",
      "tree": "f57bd848614e0f6b7439b7cf32720f9d09dbd96f",
      "parents": [
        "347f56e7b629d4a9a61a9dcdcda3da0828337f71"
      ],
      "author": {
        "name": "Marie Janssen",
        "email": "jamuraa@google.com",
        "time": "Thu Oct 29 21:24:39 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Thu Oct 29 21:24:39 2026 -0700"
      },
      "message": "pw_bluetooth_sapphire: Enforce min_enc_key_size on auth attributes\n\natt::CheckSecurity enforced min_enc_key_size only when\nencryption_required() was true. Attributes that required\nauthentication without explicit encryption skipped key size checks,\nallowing access over links encrypted with weak keys. BR/EDR\nconnections also failed to propagate negotiated key sizes to L2CAP\nchannels, leaving ATT channels vulnerable to KNOB downgrade attacks.\n\nEnforce min_enc_key_size in CheckSecurity whenever an encrypted link\nrequires encryption or authentication. Decouple authorization from\nencryption key sizes, and return kInsufficientAuthorization when\nauthorization requirements are unmet. Propagate negotiated BR/EDR\nsecurity properties to L2CAP channels in BrEdrConnection, and keep\nClient Characteristic Configuration read permissions unrestricted.\n\nBug: b/523384924\nChange-Id: I638eeac6e63fd5526949c89c8ff94dfa6a6a6964\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/516146\n"
    },
    {
      "commit": "347f56e7b629d4a9a61a9dcdcda3da0828337f71",
      "tree": "82f08771f19a7c443a6a545a4fa94264ef61998c",
      "parents": [
        "3962bb00d3eaa118bff8b2bff6b2b00def1787d7"
      ],
      "author": {
        "name": "Samrit Grover",
        "email": "samrit@google.com",
        "time": "Thu Oct 29 17:55:15 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Thu Oct 29 17:55:15 2026 -0700"
      },
      "message": "pw_{env_setup,rpc}: Exclude unused modules from Android.bp\n\nAndroid\u0027s Soong build is enabling strict dependency checking for Python\nmodules: every module imported at the top level of a python_* module\u0027s\nsources must come from its own srcs or from a module listed in libs.\n\nIn pw_rpc/py/Android.bp, the three protoc plugin binaries\n(pw_rpc_plugin_nanopb_py, pw_rpc_plugin_rawpb_py, and\npw_rpc_plugin_pwpb_py) glob pw_rpc/**/*.py, which pulls in\npw_rpc/client_utils.py and the pw_rpc/console_tools/ package.\nclient_utils.py imports pw_stream (pw_stream/py has no Android.bp), and\nconsole_tools/__init__.py imports console.py, which imports\nclient_utils. None of the plugin entry points (plugin_nanopb.py,\nplugin_raw.py, plugin_pwpb.py) or the codegen modules they use import\nclient_utils or console_tools.\n\nIn pw_env_setup/py/Android.bp, pw_env_setup_py_lib globs\npw_env_setup/*.py, which pulls in env_setup.py (a standalone bootstrap\nCLI that imports the cipd_setup and virtualenv_setup subpackages,\nneither of which is in srcs). The only Android target that depends on\npw_env_setup_py_lib (pw_emu_py) imports pw_env_setup.config_file.\n\nExclude these unused modules from srcs so all four targets satisfy\nPython strict_deps with zero runtime impact.\n\nBug: 575970774\nTest: m nothing\nChange-Id: Id5dbdb8f0e4f4eb5ec4f8b9d5b012a101ec22f5e\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/516075\n"
    },
    {
      "commit": "3962bb00d3eaa118bff8b2bff6b2b00def1787d7",
      "tree": "509b2b5b9ba34e5d12f9c398fb526a2deea37fe6",
      "parents": [
        "6ba3d6d2e36bf3487205857db5f3144364ac56d5"
      ],
      "author": {
        "name": "Samrit Grover",
        "email": "samrit@google.com",
        "time": "Thu Oct 29 17:49:38 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Thu Oct 29 17:49:38 2026 -0700"
      },
      "message": "pw_{protobuf,rpc}: Declare libprotobuf-python in Android.bp\n\nAndroid\u0027s Soong build is enabling strict dependency checking for Python\nmodules: every python_* module must list, in libs, each library that\nits own sources import. The generated *_pb2.py modules in the three\nlibraries below import google.protobuf, which they currently get only\nbecause each of their consumers also lists libprotobuf-python.\n\nAdd libprotobuf-python to the libs of:\n- pw_protobuf_codegen_protos_py_lib\n- pw_protobuf_protos_py_lib\n- pw_rpc_internal_packet_py_lib\n\nEvery consumer already depends on libprotobuf-python, so the contents\nof the built Python binaries do not change.\n\nBug: 571254697\nTest: m checkbuild\nChange-Id: Ia60d0c2420ac74c9fefb2da809f94e66f0ce0e8f\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/516074\n"
    },
    {
      "commit": "6ba3d6d2e36bf3487205857db5f3144364ac56d5",
      "tree": "65ab1741fa11006b37e34f3d42cd7d674d832da7",
      "parents": [
        "20df80ebc524afce7ce530979b3ba024257653c5"
      ],
      "author": {
        "name": "Anthony DiGirolamo",
        "email": "tonymd@google.com",
        "time": "Thu Oct 29 17:21:35 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Thu Oct 29 17:21:35 2026 -0700"
      },
      "message": "pw_env_setup: Update pip and associated packages\n\nBug: 577168466\nChange-Id: I0bff607043268073316b7962e1773d5d4cf6a187\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/512185\n"
    },
    {
      "commit": "20df80ebc524afce7ce530979b3ba024257653c5",
      "tree": "8fddd61e33257e5c1a94142de5639995344bc7b7",
      "parents": [
        "10317ab2af4120a2fccc020bef5c819ea4b7d7fb"
      ],
      "author": {
        "name": "Anthony DiGirolamo",
        "email": "tonymd@google.com",
        "time": "Thu Oct 29 17:06:59 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Thu Oct 29 17:06:59 2026 -0700"
      },
      "message": "pw_env_setup: Update cffi and aiohttp\n\nUpdate cffi to 2.1.1 and aiohttp to 3.14.5 (along with its required\naiosignal 1.4.0 and yarl 1.25.1 dependencies) so prebuilt wheels are\navailable for Python 3.11, 3.13, and 3.14.\n\nBug: b/575911232\nChange-Id: Icb00c7c7703a286ac7af0a72b847c42d670658d3\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/517048\n"
    },
    {
      "commit": "10317ab2af4120a2fccc020bef5c819ea4b7d7fb",
      "tree": "1ede28af1f91b1a5acbd7bf592607a9817fe4d4f",
      "parents": [
        "cd0796482e56b94f8cacb00fece46e2355e5d2d5"
      ],
      "author": {
        "name": "Tri Pho",
        "email": "tripho@google.com",
        "time": "Thu Oct 29 17:02:30 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Thu Oct 29 17:02:30 2026 -0700"
      },
      "message": "pw_build: Filter transitive python deps in ruff template\n\n_pw_python_static_analysis_ruff omitted the checks against\npw_build_TEST_TRANSITIVE_PYTHON_DEPS and\npw_build_TEST_TRANSITIVE_PYTHON_DEPS_FILTER_EXCLUDES that\n_pw_python_static_analysis_mypy and _pw_python_static_analysis_pylint\ninclude. This caused downstream projects with excluded transitive\ndependencies (e.g. projects excluding dir_pigweed/*) to transitively\nlint upstream packages with ruff.\n\nAdd the pw_build_TEST_TRANSITIVE_PYTHON_DEPS and filter_exclude check\nto match the mypy and pylint static analysis templates.\n\nBug: b/579544640\nTAG\u003dagy\nCONV\u003d5a8838cc-f5c0-4f41-bec7-d49c9df80fc9\n\nChange-Id: I4aa134009f647eb3ed517f274d0af0a74ae814ec\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/517046\n"
    },
    {
      "commit": "cd0796482e56b94f8cacb00fece46e2355e5d2d5",
      "tree": "51c6fcebf10757e2831bef325a0c72da960721ff",
      "parents": [
        "6257cb5946b7c88c78c84546fdd47eed7b26c964"
      ],
      "author": {
        "name": "Anthony DiGirolamo",
        "email": "tonymd@google.com",
        "time": "Thu Oct 29 15:45:06 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Thu Oct 29 15:45:06 2026 -0700"
      },
      "message": "pw_env_setup: Use mac-arm64 for Python wheels\n\nReplace mac-amd64 with mac-arm64 in the pip_cache CIPD package\ndefinitions for Python 3.10 and 3.11 and update their git_revision tags\nso python-wheel-roller can find common tags across platforms.\n\nBug: b/575911232\n\nChange-Id: I236f78be9e113b4cd645e4fd99f1b11709d2245f\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/517165\n"
    },
    {
      "commit": "6257cb5946b7c88c78c84546fdd47eed7b26c964",
      "tree": "c01cad06a7298d73f7e2bb7347b31acd79c08fa9",
      "parents": [
        "3d81c50ea19ebf3152c7b8573ea85ea50e9bce10"
      ],
      "author": {
        "name": "Anthony DiGirolamo",
        "email": "tonymd@google.com",
        "time": "Thu Oct 29 14:53:34 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Thu Oct 29 14:53:34 2026 -0700"
      },
      "message": "pw_env_setup: Set Python 3.11 as the minimum supported version\n\nBug: 575911232\nChange-Id: I54f79ff6760566a4738f70b706d552d93a61ff8a\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/510045\n"
    },
    {
      "commit": "3d81c50ea19ebf3152c7b8573ea85ea50e9bce10",
      "tree": "9d357f486ddf605da91a36556205a64cae8ce41d",
      "parents": [
        "7392fa69a1de05ed48f96eb6654a8844bc70e411"
      ],
      "author": {
        "name": "Myles Watson",
        "email": "mylesgw@google.com",
        "time": "Thu Oct 29 14:43:31 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Thu Oct 29 14:43:31 2026 -0700"
      },
      "message": "pw_build: Drop --upgrade for compiled 3p deps\n\n`${target_name}._install_3p_deps` installs packages from\n`compiled_requirements.txt`, which is generated by `pip-compile` and\nalready pins every requirement with `\u003d\u003d`. Passing `--upgrade` forces\n`pip` to query the package index for every package even when the exact\npinned version is already installed in the virtualenv.\n\nBug: b/578591704\nChange-Id: I05e89af751c3174b1b6e05694e3baed49a4b830d\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/515965\n"
    },
    {
      "commit": "7392fa69a1de05ed48f96eb6654a8844bc70e411",
      "tree": "7948fe0ef9412d52c0319107a90024767b4239d8",
      "parents": [
        "3e9cab83a1c0f02958db8c5f79d3a5ab8c7b821d"
      ],
      "author": {
        "name": "Wyatt Hepler",
        "email": "hepler@google.com",
        "time": "Thu Oct 29 14:25:43 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Thu Oct 29 14:25:43 2026 -0700"
      },
      "message": "pw_channel: Remove unused functionality and deprecate\n\n- Remove seekable support (kSeekable, Whence, Seek, Position),\n  PacketChannel, IgnoreDatagramBoundaries, and\n  LoopbackDatagramChannel.\n- Add deprecation warnings and update docs to direct users to\n  pw::transport::Socket and pw::transport::ReliableSocket in\n  pw_transport.\n- Clean up pw_channel documentation and remove pw_channel/guides.rst.\n\nChange-Id: Ie21acdbc6d9847b335d9892f39b2fc970ba3c8b1\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/515885\n"
    },
    {
      "commit": "3e9cab83a1c0f02958db8c5f79d3a5ab8c7b821d",
      "tree": "b99f36003173f33599a4a269c303881a9c87e769",
      "parents": [
        "bddd0b63166c6f790c548dc25f6769a3de4d2035"
      ],
      "author": {
        "name": "Wyatt Hepler",
        "email": "hepler@google.com",
        "time": "Thu Oct 29 13:44:37 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Thu Oct 29 13:44:37 2026 -0700"
      },
      "message": "pw_rpc2: Add features for upcoming pw_rpc adapter\n\n- Add internal::ConnectionId, which identifies a ServerConnectionTask\n  without referring to it. An ID may be kept and checked with\n  ServerTask::HasConnection(ConnectionId) after its connection closes or\n  is destroyed.\n- Add ServerConnectionTask::server_task() and\n  ServerCall::server_connection_task() so code running in a method\n  invoker can reach its connection and server.\n\nThe upcoming pw::rpc::Rpc2Adapter will use connection IDs to map pw_rpc2\nconnections to pw_rpc channel IDs.\n\nChange-Id: I472590e3548a02bec303e3a1dae1a72e76190f10\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/514125\n"
    },
    {
      "commit": "bddd0b63166c6f790c548dc25f6769a3de4d2035",
      "tree": "1fbf5cfcb084c93675e8786442308bab42da31d4",
      "parents": [
        "0b7152ee3295331201ebb093ffef374686836c2d"
      ],
      "author": {
        "name": "Anthony DiGirolamo",
        "email": "tonymd@google.com",
        "time": "Thu Oct 29 13:24:15 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Thu Oct 29 13:24:15 2026 -0700"
      },
      "message": "pw_env_setup: Remove pkg_resources requirement\n\nReplace deprecated pkg_resources usage in python_packages.py with\nimportlib.metadata and packaging (Requirement, Version, and\ncanonicalize_name), and update the package dependencies in setup.cfg\nand BUILD.bazel accordingly.\n\nAlso fix the ignored_transitive_deps membership check in diff() so\nthat unexpected packages are no longer masked when\nignored_transitive_deps is non-empty, and add the missing transitive\ndependency pins to constraint.list.\n\nBug: 431912506\nFixed: 563000549\nChange-Id: Iac3eec20eef62da1129e6dae57f5259e11ab5dd7\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/514925\n"
    },
    {
      "commit": "0b7152ee3295331201ebb093ffef374686836c2d",
      "tree": "d4f7f29b31d883418c6f8718407b8f53851ab895",
      "parents": [
        "0c2697e760fff730b7d607bfde4c47c3f5f7a6dc"
      ],
      "author": {
        "name": "Alexei Frolov",
        "email": "frolv@google.com",
        "time": "Thu Oct 29 10:57:37 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Thu Oct 29 10:57:37 2026 -0700"
      },
      "message": "pw_async2: Reset endpoint counts when reopening ChannelStorage\n\nBaseChannel::remove_object() stops decrementing sender_count_,\nreceiver_count_, and handle_count_ once the channel is closed. Any\nendpoints or handles that outlive channel closure leave non-zero counts\nbehind after ref_count_ reaches zero.\n\nReset sender_count_, receiver_count_, and handle_count_ to zero in\nBaseChannel::ReopenLocked() so reused ChannelStorage instances start\nwith clean endpoint counts.\n\nChange-Id: I9c20d3615f3463c7a555f029f18b472ddaf75a04\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/516126\n"
    },
    {
      "commit": "0c2697e760fff730b7d607bfde4c47c3f5f7a6dc",
      "tree": "5fed34039e0ead45ae1d5ecdc2d1d6f0fe7c7c29",
      "parents": [
        "d8d7bfabb6764f45af1d0819a921674ef085b952"
      ],
      "author": {
        "name": "jgraff",
        "email": "jgraff@google.com",
        "time": "Thu Oct 29 10:20:03 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Thu Oct 29 10:20:03 2026 -0700"
      },
      "message": "pw_bluetooth_sapphire: Guard L2CAP disconnect callbacks against teardown\n\nGuard LogicalLink::OnChannelDisconnectRequest and\nDynamicChannelRegistry::OnChannelDisconnected with WeakPtr liveness\nchecks in case the closed callback synchronously tears down the link.\n\nBug: b/523289972\nChange-Id: I2fea8f8cb4d16bba9b3d79745573bc03714d0cfd\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/515405\n"
    },
    {
      "commit": "d8d7bfabb6764f45af1d0819a921674ef085b952",
      "tree": "32c2e7f96c21ea14ac1032efd3d9bd53e31fa7b1",
      "parents": [
        "ffd68d75b32f444b4ab1ee3c0ba2d2e287e99baa"
      ],
      "author": {
        "name": "Kayce Basques",
        "email": "kayce@google.com",
        "time": "Thu Oct 29 10:05:03 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Thu Oct 29 10:05:03 2026 -0700"
      },
      "message": "pw_trace: Migrate C/C++ API reference to Doxygen\n\nDocument the pw_trace facade and backend macros with Doxygen and add\nthem to the C/C++ API reference. Replace the cpp:function directives\nin docs.rst with :cc: links to the new reference.\n\nBug: 533550134\nChange-Id: If76a9cecc47dd5d4dbd07218e265d5bb8f51d3ce\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/516125\n"
    },
    {
      "commit": "ffd68d75b32f444b4ab1ee3c0ba2d2e287e99baa",
      "tree": "19f74cc15f18e6a395fba7a939e14a68a971143d",
      "parents": [
        "b2f85caf1e7aa06de47e7c4d2e3ee87b89e12324"
      ],
      "author": {
        "name": "Michael Mogenson",
        "email": "mogenson@google.com",
        "time": "Thu Oct 29 08:26:10 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Thu Oct 29 08:26:10 2026 -0700"
      },
      "message": "pw_bluetooth_proxy: Retry failed sniff transitions\n\nTrack retry counts, pending backoff timers, and the last ACL activity\ntimestamp in TransitionActiveToSniff and TransitionSniffToActive, and\nqueue in-flight CommandStatus commands in a FIFO DynamicQueue in\nSniffOffloadManager::SendCommand().\n\nWhen ProcessCommandStatus() receives a non-SUCCESS status for\nSNIFF_MODE or EXIT_SNIFF_MODE:\n- Ignore the failure with a debug log if the connection has already\n  transitioned to the target mode (Sniff or Active).\n- Retry the command up to 5 times with exponential backoff (50 ms,\n  100 ms, 200 ms, 400 ms, 800 ms) using a timer stored in the transition\n  state if the connection is still in the corresponding transition state,\n  reverting to Active (restarting the idle timer) or Sniff and reporting\n  kCommandStatusFailed only after retries are exhausted.\n- Skip retrying EXIT_SNIFF_MODE and return to Sniff if\n  link_inactivity_timeout has already elapsed since the last ACL\n  activity.\n- Cancel any pending transition retry timers on a mode change event,\n  and cancel a pending TransitionActiveToSniff retry timer on ACL\n  activity that should exit sniff mode (returning to Active and\n  restarting the idle timer).\n\nNO_IFTTT\u003dAndroid.bp already depends on pw_containers\n\nBug: 573570547\nTest: bazelisk test //pw_bluetooth_proxy/hci/...\nChange-Id: Ic409511c21778f2ef70e9af4a95b5a29cf472d04\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/510565\n"
    },
    {
      "commit": "b2f85caf1e7aa06de47e7c4d2e3ee87b89e12324",
      "tree": "dd2b8d3ad813626e1d4e83b5cfcf6e9c932a4421",
      "parents": [
        "f31658c73c3450f3bbe4f5268240fe0eefc6c7be"
      ],
      "author": {
        "name": "Michael Mogenson",
        "email": "mogenson@google.com",
        "time": "Thu Oct 29 07:23:07 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Thu Oct 29 07:23:07 2026 -0700"
      },
      "message": "pw_bluetooth_proxy: Make ConnectionMode a variant\n\nConvert ConnectionMode from an enum to a std::variant sum type and move\nmode-specific state (the link inactivity timer and the hardware\nresynchronization flag) into the Active state struct.\n\nBug: 573570547\nTest: bazelisk test //pw_bluetooth_proxy/hci/...\nChange-Id: I641380b7a76b1ed0f042ece0d0f1c20c2ea28251\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/511985\n"
    },
    {
      "commit": "f31658c73c3450f3bbe4f5268240fe0eefc6c7be",
      "tree": "312686a693ba140f8efa89ebceb0730bf768b890",
      "parents": [
        "312e7b9aa44745801b1ada9a29c093576a739bee"
      ],
      "author": {
        "name": "Michael Mogenson",
        "email": "mogenson@google.com",
        "time": "Thu Oct 29 07:15:36 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Thu Oct 29 07:15:36 2026 -0700"
      },
      "message": "pw_bluetooth_proxy: Fix deadlock in CommandMultiplexer::DoReset\n\nCommandMultiplexer::Reset() acquires event_interceptors_mutex_ and\nmutex_ before calling DoReset(). When active_command_queue_ is non-empty,\ncalling active_command_queue_.clear() destroys ActiveSentCommandData\ninstances whose EventInterceptor (completer_) destructors call\nUnregisterInterceptor(), attempting to re-acquire mutex_ and\nevent_interceptors_mutex_ on the same thread and deadlocking.\n\nExplicitly unregister each active command\u0027s completion interceptor via\nRemoveEventInterceptor() while the locks are already held before clearing\nactive_command_queue_.\n\nBug: 574494043\nChange-Id: Id00d4dacf63e8a3f623097ed1c1bc83abb54ef05\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/505445\n"
    },
    {
      "commit": "312e7b9aa44745801b1ada9a29c093576a739bee",
      "tree": "68700852af9374d25da913ceadeb7a26544a55da",
      "parents": [
        "bca990eeea3cb6b31d8255c6fb6941b28fb265ba"
      ],
      "author": {
        "name": "Austin Foxley",
        "email": "afoxley@google.com",
        "time": "Wed Oct 28 21:00:45 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 21:00:45 2026 -0700"
      },
      "message": "pw_rpc: Destroy callbacks outside rpc_lock()\n\nCallbacks may capture objects, such as a std::shared_ptr or\npw::IntrusivePtr to the call\u0027s owner, whose destructors acquire locks or\ncall into pw_rpc. pw_rpc destroyed callbacks while holding rpc_lock()\nwhen they were replaced, when a call was overwritten by move assignment\n(e.g. `call \u003d {}`), and when a call closed. This could deadlock or\ninvert lock order.\n\n- The *_locked callback setters swap in the new callback, and the public\n  setters take the callback by value, so the old callback is destroyed\n  after rpc_lock() is released. Move assignment uses the same setters,\n  so the destination\u0027s old callbacks are destroyed with the moved-from\n  call.\n- When a call errors or completes, its remaining raw callbacks are\n  released after the final callback returns.\n- pwpb and Nanopb calls destroy an unrestored on_next or on_completed\n  callback after the callback finishes, so its captures may destroy the\n  call.\n\nBug: 458381888\nChange-Id: Ied694432750beb51e5e32d2bb8de84340b7e36c4\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/513145\n"
    },
    {
      "commit": "bca990eeea3cb6b31d8255c6fb6941b28fb265ba",
      "tree": "38aa181d84f038e3bf523662d0bebca9ebad3904",
      "parents": [
        "0b402f6582da979c5ac186e34168e382cca30f16"
      ],
      "author": {
        "name": "Liam Bucci",
        "email": "liambucci@google.com",
        "time": "Wed Oct 28 16:02:07 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 16:02:07 2026 -0700"
      },
      "message": "pw_rpc: Add QueryService\n\nAdd a new RPC service to pw_rpc and pw_system that allows a client to\nquery the current RPC server for any registered services and their\nmethods.\n\nThe new service adds four new methods:\n- ListServices - Stream all the service IDs registered on the current\n  RPC server.\n- ListMethods - Stream all method IDs supported by the given service.\n- IsServiceAvailable - Check if the given service is currently\n  registered.\n- IsMethodAvailable - Check if the given method is supported by the\n  given service.\n\nAlong with the device.rpcs collection, this can be used to query the\nrunning system for RPC services and methods.\n\nTests: Added unit tests for Server and Service.\nTests: Added unit tests for QueryService.\nTests: Added unit tests for QueryService client and descriptors.\nTests: Flashed rp2350_system_example to a pico2 and used all new\nmethods.\n\nChange-Id: Ibdd55977c5381d33a81a6f76d5d19a6c0bb80540\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/445253\n"
    },
    {
      "commit": "0b402f6582da979c5ac186e34168e382cca30f16",
      "tree": "049b26f512adee3bfdbf4becf18bf8f2289a09d4",
      "parents": [
        "aaae3ac68b1631c19aca5d8c26e21239d0c01f55"
      ],
      "author": {
        "name": "Dave Roth",
        "email": "davidroth@google.com",
        "time": "Wed Oct 28 15:57:57 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 15:57:57 2026 -0700"
      },
      "message": "pw_kernel: Reset NVIC enable/pending state at init\n\nThe NVIC enable and pending registers are not architecturally reset on\na warm reset, so a bootloader or prior stage can leave external IRQs\narmed that would fire as soon as the kernel enables interrupts.\n\nHave `Nvic::early_init()` disable (`ICER`) and clear pending (`ICPR`)\nevery external IRQ alongside setting its priority, matching the\ncontract already used by the RISC-V PLIC and PIC: nothing is enabled\nuntil a kernel driver or interrupt object asks for it. Drop the\ncorresponding bullet from the Cortex-M early-init TODO.\n\nTest: bazelisk test --config\u003dk_qemu_mps2_an505 //pw_kernel/...\n\nChange-Id: I68e555da1025e3c693465e084088f8a0d1867e62\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/515967\n"
    },
    {
      "commit": "aaae3ac68b1631c19aca5d8c26e21239d0c01f55",
      "tree": "aaa78b10182630ebe94d668858de3032efe75a6d",
      "parents": [
        "7fbdc1ef8d1ea9717b222f3b667c73b28c9f0ac6"
      ],
      "author": {
        "name": "Ali Saeed",
        "email": "saeedali@google.com",
        "time": "Wed Oct 28 15:38:32 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 15:38:32 2026 -0700"
      },
      "message": "pw_bluetooth_sapphire: Check LE identity and CTKD\n\nHarden LE pairing identity validation and cross-transport key derivation\n(CTKD) persistence in sm and gap:\n\n- Require AddressType::kStaticRandom in\n  Phase3::OnIdentityAddressInformation to satisfy\n  DeviceAddress::IsStaticRandom() (MSBs \u003d\u003d 0b11).\n- Require LE Phase3::OnIdentityAddressInformation to match either the\n  active public/static link address or an IRK-resolvable RPA, while\n  preserving non-aborting drop behavior for BR/EDR CTKD.\n- Gate LE-to-BR/EDR CTKD bond storage in PeerCache::StoreLowEnergyBond\n  on Peer::address().IsPublic() instead of Peer::identity_known().\n\nFixed: b/523313481, b/521638307\nBug: b/521638622\nTest: bazelisk test --config\u003dgoogletest //pw_bluetooth_sapphire/...\nChange-Id: I14105b579d0b9cada3ac203028a65e22c3799727\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/510806\n"
    },
    {
      "commit": "7fbdc1ef8d1ea9717b222f3b667c73b28c9f0ac6",
      "tree": "823ec424b0728f0b6cefcf26b217f32449eceb37",
      "parents": [
        "765919e21a4a4c536a641a61b0e2c1bd1860bf1d"
      ],
      "author": {
        "name": "Alexei Frolov",
        "email": "frolv@google.com",
        "time": "Wed Oct 28 15:12:41 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 15:12:41 2026 -0700"
      },
      "message": "pw_async2: Forward arguments in Poll in-place constructor\n\nPoll(std::in_place_t, Args\u0026\u0026...) previously passed std::move(args)...\nto std::optional, which silently moved from non-const lvalues passed\ndirectly or forwarded through Poll(U\u0026\u0026) and Ready(T\u0026\u0026). Forward the\narguments with std::forward\u003cArgs\u003e(args)... instead.\n\nAlso use std::decay_t\u003cT\u003e in Ready(T\u0026\u0026) so passing a const lvalue\nproduces Poll\u003cT\u003e rather than Poll\u003cconst T\u003e.\n\nChange-Id: Ic79328c5663bbbaf62d27e4d30cdef43b2eaf103\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/516046\n"
    },
    {
      "commit": "765919e21a4a4c536a641a61b0e2c1bd1860bf1d",
      "tree": "ee37a65c6ee9cea95b628706f35dd4378677fb9a",
      "parents": [
        "2ccbafb001ef2ba46dc9768e9c7e77f3a4b8cc1b"
      ],
      "author": {
        "name": "Hoang Le",
        "email": "hoangmle@google.com",
        "time": "Wed Oct 28 14:13:33 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 14:13:33 2026 -0700"
      },
      "message": "docs: Add review-time Python and Bazel checks to style guides\n\nAdd rules that reviewers routinely apply but that the guides did not\nstate, so that the code review checklist can link to them instead of\nrestating them:\n\n- python.rst: error handling (narrow try blocks, raise instead of\n  returning a sentinel, check\u003dTrue for subprocess.run), type annotations\n  and defaults, tests that prefer real implementations over mocks, and\n  listing new modules in both build systems.\n- bazel.rst: keep deps minimal and put private dependencies in\n  implementation_deps. Naming, visibility, and strip_include_prefix\n  were already covered.\n\nChange-Id: I3c6ffd270e4ab9fbaf4e869cc1a7a18090b888b1\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/499354\n"
    },
    {
      "commit": "2ccbafb001ef2ba46dc9768e9c7e77f3a4b8cc1b",
      "tree": "6169856e0f0bbd8ad04201edd738fd51df6f9879",
      "parents": [
        "169b6f0c00866aea2442e2d961a28fa75543724e"
      ],
      "author": {
        "name": "Dave Roth",
        "email": "davidroth@google.com",
        "time": "Wed Oct 28 12:40:53 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 12:40:53 2026 -0700"
      },
      "message": "pw_env_setup: Roll cipd\n\nRolls CIPD client version to git_revision:509ce13299eeacebb825204bdd83b4f075084714.\n\nBug: 315378787\n\nChange-Id: Ie70cf9aaa37a10d7f42991e67870415e68dd8780\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/516045\n"
    },
    {
      "commit": "169b6f0c00866aea2442e2d961a28fa75543724e",
      "tree": "00602948b6eb87ebaca6ef5a5777a0266f6e70e5",
      "parents": [
        "832d7a21280c355c451e4ebe5e8648411e6e01a2"
      ],
      "author": {
        "name": "Keir Mierle",
        "email": "keir@google.com",
        "time": "Wed Oct 28 12:13:26 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 12:13:26 2026 -0700"
      },
      "message": "pw_transfer: Require status on completion chunks\n\nReject terminating chunks (Type::kCompletion) that omit the status field\nin Chunk::Parse() with Status::DataLoss() so Context::HandleChunkEvent()\ncannot dereference an empty status optional.\n\nFixed: b/525189381\n\nChange-Id: I974f3874c6e7865c9e78a25b7dcf6f4c1be1aff4\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/500014\n"
    },
    {
      "commit": "832d7a21280c355c451e4ebe5e8648411e6e01a2",
      "tree": "108c9a22163f40202610f03085ddc109c5773296",
      "parents": [
        "d685643ce69ab94fe0beeaabe373e68014159026"
      ],
      "author": {
        "name": "Myles Watson",
        "email": "mylesgw@google.com",
        "time": "Wed Oct 28 12:12:28 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 12:12:28 2026 -0700"
      },
      "message": "pw_env_setup: Fix --trust-cipd-hash env vars\n\nWhen `trust_hash\u003dTrue` and `packages.sha256` matched the computed digest,`update()` returned `True` early before populating `PATH` and\n`PW_*_CIPD_INSTALL_DIR` in `env_vars`. Skip `check_auth()` and `cipd\nensure` when the hash matches while still setting the environment\nvariables.\n\nBug: b/578591704\nChange-Id: Id1ec5ae66c4b69627dfe9efd60128d578fe18c15\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/515945\n"
    },
    {
      "commit": "d685643ce69ab94fe0beeaabe373e68014159026",
      "tree": "cf97231937761e5d2062a03c7e0e9d77c395e968",
      "parents": [
        "8b15a322d603257c123b38b6d6efeb2f7454417f"
      ],
      "author": {
        "name": "Dave Roth",
        "email": "davidroth@google.com",
        "time": "Wed Oct 28 11:52:48 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 11:52:48 2026 -0700"
      },
      "message": "pw_kernel: Route RISC-V interrupts via the controller\n\nReplace the unsound `core::mem::transmute` in `MCauseVal::cause()` with\nsafe `from_raw_cause()` / `raw_cause()` conversions on `Interrupt` and\n`Exception`. Hart-local interrupts (`mcause` codes \u003e\u003d 16) now decode to\n`Interrupt::Local(line)` and reserved codes to `Unknown(code)` instead\nof invoking undefined behavior.\n\nDefine a `RiscVInterruptController` trait with a single\n`handle_interrupt(Interrupt, from_userspace)` hook. The trap handler\ndecodes `mcause` and hands every interrupt to the controller, which\nowns the routing policy. `Plic` and `VeerPic` route the machine timer\nand machine external interrupts; neither in-tree controller has\nhart-local lines, so they panic on `Local(_)`. Platforms with\nhart-local interrupts can implement the `Local(line)` arm and use the\nnew `Mie` / `MieVal` helpers to manage `mie[16 + line]`.\n\nSince `mie` has no architecturally defined reset value, have\n`exceptions::early_init()` mask every `mie` source other than `MTIE`\nand `MEIE` so a stale enable left by a bootloader cannot deliver an\ninterrupt the kernel does not service.\n\nFixes: 574387059\nTest: bazelisk test --config\u003dk_qemu_virt_riscv32 //pw_kernel/...\n\nChange-Id: I730112913ad3402bf0c34a6cd552e3926e53da0b\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/505988\n"
    },
    {
      "commit": "8b15a322d603257c123b38b6d6efeb2f7454417f",
      "tree": "68502b08cb6faff873a1f2614747d5483cf41424",
      "parents": [
        "52108862b0f317d2937e8c01dba0227a420844a1"
      ],
      "author": {
        "name": "Hoang Le",
        "email": "hoangmle@google.com",
        "time": "Wed Oct 28 11:30:58 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 11:30:58 2026 -0700"
      },
      "message": "pw_ghish: Mark agent comments with is_ai\n\nAdd --agent\u003dauto|true|false to `pr comment` and `pr review`. Marked\ncomments are sent with Gerrit\u0027s is_ai field, which Google-hosted Gerrit\nshows with a Gemini icon. auto, the default, marks comments when\nIsAgentEnv detects a coding agent.\n\nis_ai is not in any released Gerrit version (only upstream master), and\ngo-gerrit does not model it, so comment.go builds these requests itself.\nReview messages cannot carry is_ai, so marked change-level text is\nposted as a patchset-level comment in the same review.\n\nChange-Id: Ie9fbdf4f8ed924418d0e4f902c4434b20def9e79\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/511065\n"
    },
    {
      "commit": "52108862b0f317d2937e8c01dba0227a420844a1",
      "tree": "9613726802bde2b3498440303edec960053e533c",
      "parents": [
        "c8526951e5bea292afb0af7244c040405f507df4"
      ],
      "author": {
        "name": "Wyatt Hepler",
        "email": "hepler@google.com",
        "time": "Wed Oct 28 11:02:36 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 11:02:36 2026 -0700"
      },
      "message": "pw_transport, pw_rpc2: Remove deprecated socket aliases\n\nRemove the deprecated socket naming backwards compatibility aliases:\n- DatagramSocket\n- ReliableDatagramSocket\n- DatagramSocketImpl\n- ReliableDatagramSocketImpl\n- ReliableDatagramListener\n- ReliableDatagramConnector\n\nUpdate all remaining references across pw_transport and pw_rpc2 to use\nSocket, ReliableSocket, SocketImpl, ReliableSocketImpl,\nReliableListener, and ReliableConnector.\n\nChange-Id: Icb559cd7ea4780eb8449338410b46b0482184e66\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/515125\n"
    },
    {
      "commit": "c8526951e5bea292afb0af7244c040405f507df4",
      "tree": "68bcbeba506790b4b7146b07f59fe78d8efefcd8",
      "parents": [
        "ed4317d8307e1d6a7d6d0b5617250aa512247b98"
      ],
      "author": {
        "name": "Rob Mohr",
        "email": "mohrr@google.com",
        "time": "Wed Oct 28 09:45:39 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 09:45:39 2026 -0700"
      },
      "message": "pw_ghish: Add --add-cc and --remove-cc to issue edit\n\nCCs could previously only be set when creating an issue. Add\n--add-cc and --remove-cc to `gh issue edit` so CCs can be managed on\nexisting issues. Both accept comma-separated emails or \"me\", like\n`issue create --cc` and `issue edit --add-assignee`.\n\nChange-Id: Id47d76040053895ea0ffd44294ad9c0618e48486\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/509709\n"
    },
    {
      "commit": "ed4317d8307e1d6a7d6d0b5617250aa512247b98",
      "tree": "c07148b60f0a72eae17eba4720e9b0c58f8b5330",
      "parents": [
        "4679cd3b35a486bb7073a29e05b4064587be18ee"
      ],
      "author": {
        "name": "Adam Snaider",
        "email": "asnaider@google.com",
        "time": "Wed Oct 28 09:03:43 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 09:03:43 2026 -0700"
      },
      "message": "pw_bluetooth_sapphire: Bound prepared write offsets in ExecuteWriteQueue\n\nVerify offset validity before sending a queued GATT write to the\nattribute\u0027s write handler, rejecting writes that start or end past\nkMaxAttributeValueLength with Invalid Offset or Invalid Attribute Value\nLength, respectively.\n\nBug: b/521639511\nTest: bazelisk test --config googletest //pw_bluetooth_sapphire/host/att:att_test --test_arg\u003d--gtest_filter\u003d\u0027DatabaseExecuteWriteQueueTest.*\u0027\nTAG\u003dagy\nCONV\u003df8c894db-1655-4f80-ad77-faa570d60da3\n\nChange-Id: I5c05e1238ab19f0016df4151b84883406a6a6964\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/511993\n"
    },
    {
      "commit": "4679cd3b35a486bb7073a29e05b4064587be18ee",
      "tree": "2e29b6b5d2bb0ff736455318424e808cebd9b8fa",
      "parents": [
        "00cb52c06707a5e73a43628fff31613efa066f06"
      ],
      "author": {
        "name": "Adam Snaider",
        "email": "asnaider@google.com",
        "time": "Wed Oct 28 09:02:28 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 09:02:28 2026 -0700"
      },
      "message": "pw_bluetooth_sapphire: Trust bonded peer GAP name only when encrypted\n\nLowEnergyConnection stored the Device Name and Appearance read from the\npeer\u0027s GAP service regardless of link security. A device spoofing a\nbonded peer\u0027s address could therefore overwrite the bonded peer\u0027s name\nand appearance over an unencrypted link.\n\nFor bonded peers, defer reading these values until the link is\nencrypted. Unbonded peers are unaffected.\n\nBug: b/523274478\nTest: bazelisk test --config googletest //pw_bluetooth_sapphire/host/gap:gap_test --test_arg\u003d--gtest_filter\u003d\u0027*BondedPeerNameAndAppearance*\u0027\nTAG\u003dagy\nCONV\u003df8c894db-1655-4f80-ad77-faa570d60da3\n\nChange-Id: I7f012d834b5ac254d39f3c7b429912586a6a6964\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/511992\n"
    },
    {
      "commit": "00cb52c06707a5e73a43628fff31613efa066f06",
      "tree": "505224e9d56ac6944b0223126f0a92f4b8680fe8",
      "parents": [
        "0b58e44080d917f21033099f5196bf40cc7dbf0a"
      ],
      "author": {
        "name": "Adam Snaider",
        "email": "asnaider@google.com",
        "time": "Wed Oct 28 09:00:37 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 09:00:37 2026 -0700"
      },
      "message": "pw_bluetooth_sapphire: Snapshot GATT containers before callbacks\n\nGATT::Impl::UpdateConnectedPeers range-iterated |connections_| while\ncalling Server::SendUpdate, which synchronously invokes the indication\ncallback when a peer has not configured the characteristic. A caller\nthat removed connections from that callback freed the map node under\nthe live iterator, causing a use-after-free when the loop advanced.\n\nIterate over a snapshot of the connected peer IDs instead and look up\neach peer again, skipping peers removed by an earlier callback.\n\nThe same pattern existed for the peer MTU listeners and the remote\nservice watchers, where a listener or watcher unregistering itself\nfreed the node being iterated. Apply the same snapshot-and-lookup fix\nthere.\n\nBug: b/523286163\nTest: bazelisk test --config googletest --config asan //pw_bluetooth_sapphire/host/gatt:gatt_test --test_arg\u003d--gtest_filter\u003d\u0027*UpdateConnectedPeersCallbackCanRemoveAllConnections:*CanUnregisterThemselvesWhenNotified\u0027\nTAG\u003dagy\nCONV\u003df8c894db-1655-4f80-ad77-faa570d60da3\n\nChange-Id: I0fcbb79ebfcacde91237780be560f1676a6a6964\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/511991\n"
    },
    {
      "commit": "0b58e44080d917f21033099f5196bf40cc7dbf0a",
      "tree": "edfe713fd8735cbe0a0e0145c9876a0d0dfb5b4e",
      "parents": [
        "c969ec73ad2a6cf5098760fdfae085dbbe786395"
      ],
      "author": {
        "name": "Adam Snaider",
        "email": "asnaider@google.com",
        "time": "Wed Oct 28 08:58:57 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 08:58:57 2026 -0700"
      },
      "message": "pw_bluetooth_sapphire: Refuse duplicate LE links during interrogation\n\nLowEnergyConnectionManager allowed two internal::LowEnergyConnection\nobjects to exist for the same peer when an inbound and an outbound link\noverlapped: RegisterRemoteInitiatedLink() did not check whether the\nin-flight outbound connector (current_request_) already held a link,\nand an outbound link completing while an inbound link was interrogating\nwas not checked either. GATT registration is keyed by PeerId, so the\nsecond connection\u0027s AddConnection() was a no-op, and when the duplicate\nwas later rejected its destructor called RemoveConnection(peer_id),\ntearing down the GATT client/server of the surviving link.\n\nEnforce at most one LowEnergyConnection per peer:\n- RegisterRemoteInitiatedLink() refuses a remote-initiated link if the\n  current local-initiated connector for the peer already has a link.\n- LowEnergyConnector refuses to create a LowEnergyConnection (and\n  reports failure through its result callback) if the manager already\n  has a connection, or a connector holding a link, for the peer. This\n  covers a local-initiated link completing while a remote-initiated\n  link is interrogating, or after it is established.\n\nIn both cases the duplicate link is disconnected before any GATT or\nL2CAP state is created for it, and its request is completed exactly\nonce with an error, while the surviving link is unaffected.\n\nBug: b/525199651\nTest: bazelisk test --config googletest //pw_bluetooth_sapphire/host/gap:gap_test --test_arg\u003d--gtest_filter\u003d\u0027*InitiatedLinkRefusedWhile*\u0027\nTAG\u003dagy\nCONV\u003df8c894db-1655-4f80-ad77-faa570d60da3\n\nChange-Id: I2bae5215d3b1219327c963f2e1f738666a6a6964\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/511990\n"
    },
    {
      "commit": "c969ec73ad2a6cf5098760fdfae085dbbe786395",
      "tree": "f9e3c57da069900043fe8ec1ea0a09d2cfb8583a",
      "parents": [
        "4cafc2efb80f9cf5e3b2e295a1d5265cb65a9ed0"
      ],
      "author": {
        "name": "Adam Snaider",
        "email": "asnaider@google.com",
        "time": "Wed Oct 28 08:57:22 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 08:57:22 2026 -0700"
      },
      "message": "pw_bluetooth_sapphire: Fix sibling handle release in CloseRefs\n\nWhen an LE connection is torn down (e.g. on a remote disconnect),\n~LowEnergyConnection calls CloseRefs(), which iterates over all active\nLowEnergyConnectionHandles and runs their closed callbacks. If one\nhandle\u0027s closed callback released or destroyed a sibling handle that\nhad not yet been visited, the sibling stayed in |refs_|. Originally its\nrelease callback re-entered LowEnergyConnectionManager::ReleaseReference\nand hit a PW_CHECK because the connection had already been removed from\nthe manager. Since the weak pointer is now invalidated at the top of the\ndestructor, the release callback became a no-op instead, and CloseRefs()\nwent on to call MarkClosed() on the freed handle (heap-use-after-free),\nor notify a handle that had already been released.\n\nFix this by giving connection handles a second weak pointer to the\nconnection that stays valid until CloseRefs() returns. When the main\nweak pointer has been invalidated, the release callback uses it to drop\nthe handle from |refs_| locally. CloseRefs() also removes each handle\nfrom |refs_| before notifying it, so the iteration tolerates closed\ncallbacks that mutate the set.\n\nBug: b/525209445\nTest: bazelisk test --config googletest --config asan //pw_bluetooth_sapphire/host/gap:gap_test --test_arg\u003d--gtest_filter\u003d\u0027LowEnergyConnectionManagerTest.DisconnectEvent*\u0027\nTAG\u003dagy\nCONV\u003df8c894db-1655-4f80-ad77-faa570d60da3\n\nChange-Id: I02a2087f627984ec08da0b6a2819e97d6a6a6964\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/511989\n"
    },
    {
      "commit": "4cafc2efb80f9cf5e3b2e295a1d5265cb65a9ed0",
      "tree": "850c8b6c0ec8808072e0d2c5441f0211093f0072",
      "parents": [
        "064a8410384d4d6f2eb148332f1b06ff692cf5c8"
      ],
      "author": {
        "name": "Adam Snaider",
        "email": "asnaider@google.com",
        "time": "Wed Oct 28 08:56:04 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 08:56:04 2026 -0700"
      },
      "message": "pw_bluetooth_sapphire: Cap results of remote GATT ReadByType\n\nRemoteService::ReadByType() reads all attributes of a given type in a\nservice by issuing ATT Read By Type requests until the end of the\nservice range, accumulating every returned value (each in its own heap\nbuffer) and every per-handle error into a single vector. The service\nrange is peer-controlled and may span the whole handle space, so a\nmalicious peer could make the host accumulate up to 65,535 results\n(about 16 MB of heap with maximum-length values) in a single procedure,\nexhausting the heap on embedded targets.\n\nLimit a procedure to RemoteService::kMaxReadByTypeResults (512)\nresults, counting both values and per-handle errors. If a peer returns\nmore, stop issuing requests and complete the callback with the new\nHostError::kTooManyResults and no results, rather than returning a\nsilently truncated list as a success. The check is done before a\nresponse\u0027s values are copied, so no buffers are allocated for the\nresponse that exceeds the limit. A dedicated error, rather than\nkOutOfMemory, keeps a peer exceeding the limit distinguishable from a\ngenuine allocation failure.\n\nThe fuchsia.bluetooth.gatt and fuchsia.bluetooth.gatt2 RemoteService\nservers report a ReadByType kTooManyResults status as\nTOO_MANY_RESULTS, the error they already return when the results do\nnot fit in a FIDL response, instead of a generic FAILURE or\nUNLIKELY_ERROR.\n\nBug: b/525207411\nTest: bazelisk test --config googletest //pw_bluetooth_sapphire/host/gatt:gatt_test --test_arg\u003d--gtest_filter\u003d\u0027*MaxReadByTypeResults*\u0027\nTest: bazelisk test --config\u003dfuchsia --test_timeout\u003d1400 //pw_bluetooth_sapphire/fuchsia:tests_qemu\nTAG\u003dagy\nCONV\u003df8c894db-1655-4f80-ad77-faa570d60da3\n\nChange-Id: Ieda5593b64df4bedb3bc8e60af6341736a6a6964\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/511988\n"
    },
    {
      "commit": "064a8410384d4d6f2eb148332f1b06ff692cf5c8",
      "tree": "8381d73d594303bd65ef889a0e6a6454bd6469d1",
      "parents": [
        "af30ec7db4791a2a340b4d99b7f1fe336ebb3629"
      ],
      "author": {
        "name": "Adam Snaider",
        "email": "asnaider@google.com",
        "time": "Wed Oct 28 08:55:02 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 08:55:02 2026 -0700"
      },
      "message": "pw_bluetooth_sapphire: Cap remote GATT services per peer\n\nDuring automatic GATT client initialization, RemoteServiceManager\nallocated a RemoteService for every service the peer returned, with no\nupper bound. A malicious peer could declare one-handle services across\nthe whole handle space and make the host allocate up to 65,535\nRemoteService objects (many MB of heap) before pairing, exhausting the\nheap on embedded targets. Service Changed handling had the same\nproblem: a peer could indicate a change covering the whole handle space\nand have every rediscovered service buffered and allocated.\n\nLimit the number of services tracked per peer to\nRemoteServiceManager::kMaxRemoteServices (256, a worst case of roughly\n31 KiB on 32-bit targets) and treat a peer that exceeds it as\nmisbehaving:\n\n- gatt::Client\u0027s ServiceCallback now returns a result. If it returns an\n  error, discovery stops immediately (no further ATT requests are sent)\n  and that error is reported through the status callback.\n- During initial discovery, RemoteServiceManager stops discovery once\n  the limit would be exceeded and fails Initialize() with\n  HostError::kOutOfMemory. gatt::Connection already reports the error\n  and shuts down the ATT bearer, which signals a link error and\n  disconnects the peer.\n- If a Service Changed indication would push the total past the limit,\n  discovery for it stops and none of the changes are applied. During\n  initialization this fails Initialize(). After initialization it is\n  reported through a new RemoteServiceManager fatal error callback,\n  which gatt::Connection uses to shut down the connection.\n\nAlso complete pending RemoteService::DiscoverCharacteristics() requests\nwith HostError::kFailed when the service is destroyed, instead of\ndropping them without ever invoking the callbacks. The callbacks run\nafter the service\u0027s removed handlers and after its WeakPtrs are\ninvalidated, so they can\u0027t queue new requests on the dying service.\nWhen a Service Changed indication modifies a service, the replacement\nis now put in the service map before the old service is destroyed.\n\nBug: b/525209028\nTest: bazelisk test --config googletest //pw_bluetooth_sapphire/host/gatt:gatt_test --test_arg\u003d--gtest_filter\u003d\u0027*MaxRemoteServices*:*BeyondMax*:*StopsWhenServiceCallbackFails*:*CompletesWithErrorWhenServiceDestroyed*:*CompletesOnDestruction*:*CompletesPendingDiscoveryAfterReplacing*:*DeferredExtPropReadAfterServiceDestroyed*\u0027\nTAG\u003dagy\nCONV\u003df8c894db-1655-4f80-ad77-faa570d60da3\n\nChange-Id: I82799b5405b7c7e47b7d58f097fddddb6a6a6964\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/511987\n"
    },
    {
      "commit": "af30ec7db4791a2a340b4d99b7f1fe336ebb3629",
      "tree": "d164d3ed2515e6fb44bd2d10ed77282dcc307fb8",
      "parents": [
        "5770d8268496a7f8d590eccfa9beb9eb7442cf39"
      ],
      "author": {
        "name": "Adam Snaider",
        "email": "asnaider@google.com",
        "time": "Wed Oct 28 08:53:29 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 08:53:29 2026 -0700"
      },
      "message": "pw_bluetooth_sapphire: Discover GATT descriptors one at a time\n\nRemoteService::StartDescriptorDiscovery() issued a descriptor discovery\nrequest for every characteristic of a service in a single synchronous\nloop. A remote peer could declare ~21k characteristics, each followed\nby a one-handle gap, in a service spanning the whole handle space,\nwhich made the host queue ~21k ATT transactions (PDUs plus closure\nchains) in the bearer at once, a multi-MB heap spike during automatic\nGATT client initialization.\n\nDiscover descriptors serially instead: the request for the next\ncharacteristic is only issued once the previous one completes, so at\nmost one descriptor discovery request is outstanding per service.\nSince the ATT bearer only allows one outstanding request anyway, this\ndoes not add latency. Requests that complete synchronously continue in\na loop rather than recursing, to bound stack usage. Discovery now stops\nat the first failing characteristic instead of issuing the remaining\nrequests.\n\nBug: b/525217209\nTest: bazelisk test --config googletest //pw_bluetooth_sapphire/host/gatt:gatt_test --test_arg\u003d--gtest_filter\u003d\u0027RemoteServiceManagerTest.DiscoverDescriptors*\u0027\nTAG\u003dagy\nCONV\u003df8c894db-1655-4f80-ad77-faa570d60da3\n\nChange-Id: I232e3830fcc495eca7e84016b2ec21836a6a6964\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/511986\n"
    },
    {
      "commit": "5770d8268496a7f8d590eccfa9beb9eb7442cf39",
      "tree": "340b61d1505b0b9261f2d2208b0b9e8e1f8bc4e5",
      "parents": [
        "90bced1784f2575a8f353aa720d88dd5deabf0a8"
      ],
      "author": {
        "name": "Josh Conner",
        "email": "joshconner@google.com",
        "time": "Wed Oct 28 07:10:03 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 07:10:03 2026 -0700"
      },
      "message": "pw_bluetooth_sapphire: Extract shared VirtualController\n\nMove the VirtualController FIDL server out of the driver into\nvirtual_controller.{h,cc}, so that a plain component can host it too.\n\nBug: b/430578502\nTest: (fuchsia) fx test --parallel 1 bt-access-integration-tests\n      bt-le-integration-tests bt-host-integration-tests\nTest: bazelisk test --config\u003dfuchsia\n      //pw_bluetooth_sapphire/fuchsia/bt_hci_virtual:test_pkg\nChange-Id: Iebc2b9c431c79bfe68b61428467f6309e517e1e9\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/507068\n"
    },
    {
      "commit": "90bced1784f2575a8f353aa720d88dd5deabf0a8",
      "tree": "1cb5b1dedb96cbabb5e04ad5b89bd01bd7eafaa3",
      "parents": [
        "029e19a955e236610f50bb88ecfebf7e3d31bf7e"
      ],
      "author": {
        "name": "Josh Conner",
        "email": "joshconner@google.com",
        "time": "Wed Oct 28 07:05:39 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 07:05:39 2026 -0700"
      },
      "message": "pw_bluetooth_sapphire: Publish EmulatorService per emulator\n\nGive clients a way to reach an emulator that does not depend on devfs:\neach EmulatorDevice publishes the\nfuchsia.hardware.bluetooth.EmulatorService instance `\u003cname\u003e` to the\noutgoing directory while it lives, alongside the vendor Service\ninstance it publishes on `Publish`.\n\nBug: b/430578502\nTest: (fuchsia) fx test --parallel 1 bt-access-integration-tests\n      bt-le-integration-tests bt-host-integration-tests\nTest: bazelisk test --config\u003dfuchsia\n      //pw_bluetooth_sapphire/fuchsia/bt_hci_virtual:test_pkg\nChange-Id: I92e41eb22a7bf1ba849bbee01799cf171145cf70\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/507067\n"
    },
    {
      "commit": "029e19a955e236610f50bb88ecfebf7e3d31bf7e",
      "tree": "f88191adb40da08aa33acfb766696458e4a13b14",
      "parents": [
        "cbc0d8e6ef380dbbad7775b5ed2fe097be4f72ed"
      ],
      "author": {
        "name": "Josh Conner",
        "email": "joshconner@google.com",
        "time": "Wed Oct 28 07:01:25 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 07:01:25 2026 -0700"
      },
      "message": "pw_bluetooth_sapphire: Constexpr mode comparisons\n\nDefine the AnyChannelMode equality operators inline in types.h as\nconstexpr, and make ChannelManagerImpl\u0027s IsModeSupported() constexpr\nnow that the comparisons it uses can be constant-evaluated.\n\nTest: bazelisk test --config\u003dgoogletest \\\n        //pw_bluetooth_sapphire/host/l2cap:l2cap_test \\\n        //pw_bluetooth_sapphire/host/gap:gap_test \\\n        //pw_bluetooth_sapphire/host/sdp:sdp_test \\\n        //pw_bluetooth_sapphire/host/testing:all\nChange-Id: I115f6f9165ce559bb5d50ba20faec18fcb152c32\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/514765\n"
    },
    {
      "commit": "cbc0d8e6ef380dbbad7775b5ed2fe097be4f72ed",
      "tree": "75a8fc61f00bd8c47784b468aafd3f8410ed994f",
      "parents": [
        "909513ecf3ab9cbb01160ef38d1649cde88dfb91"
      ],
      "author": {
        "name": "Josh Conner",
        "email": "joshconner@google.com",
        "time": "Wed Oct 28 07:01:12 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 07:01:12 2026 -0700"
      },
      "message": "pw_bluetooth_sapphire: Reject cross-transport PSMs\n\nL2CAP services shared one PSM namespace across BR/EDR and LE, and\ninbound lookups ignored the link type. An unauthenticated LE peer\ncould request SPSM 0x0001 and get the SDP server\u0027s Basic-mode\nparameters, hitting the PW_CHECK in LeDynamicChannel\u0027s ConvertMode\nand aborting the host.\n\nMake the transport explicit: ChannelManager::RegisterService and\nUnregisterService take a link type, services are keyed by link type\nand PSM, and inbound requests only match services for the link\u0027s\ntype.\n\nFixed: b/510065625\nFixed: b/42181829\nTest: bazelisk test --config\u003dgoogletest \\\n        //pw_bluetooth_sapphire/host/l2cap:l2cap_test \\\n        //pw_bluetooth_sapphire/host/gap:gap_test \\\n        //pw_bluetooth_sapphire/host/sdp:sdp_test \\\n        //pw_bluetooth_sapphire/host/testing:all\nChange-Id: I75447967e776a53f8e2051ab270627dc3a657bb2\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/508245\n"
    },
    {
      "commit": "909513ecf3ab9cbb01160ef38d1649cde88dfb91",
      "tree": "c20903a133fa74d1d0d37021c3414a78a4b26dba",
      "parents": [
        "255529e88b53c5b4923741e8eccefbd3c8fdb5a5"
      ],
      "author": {
        "name": "Benny Wen",
        "email": "shenghanw@google.com",
        "time": "Wed Oct 28 02:44:36 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 02:44:36 2026 -0700"
      },
      "message": "pw_ghish: Start --nightly now when already off-peak\n\n--nightly picks a slot in the 21:00 to 03:00 Pacific window from the\nchange number. Run inside the window after that slot had passed, it\nwaited for the next night, e.g. about 24 hours at 21:45 with a 21:30\nslot. Schedule the next minute instead, since the change is already\noff-peak. A slot still ahead in the window is kept, so changes stay\nspread out by change number.\n\nBug: b/576920195\nChange-Id: I097ca8810e5a85cf9dbed0f84dd108ae80d1f7f9\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/511566\n"
    },
    {
      "commit": "255529e88b53c5b4923741e8eccefbd3c8fdb5a5",
      "tree": "6361cb7b0887372dcb5acdbae3c579ba154d9665",
      "parents": [
        "0a5061f9bd1bac7539a3ace60a905febee4cbbea"
      ],
      "author": {
        "name": "Eric Rahm",
        "email": "erahm@google.com",
        "time": "Wed Oct 28 00:31:16 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 00:31:16 2026 -0700"
      },
      "message": "pw_ghish: Update MockGerritServer route matching and test helpers\n\nRegister exact change endpoints in `OnDefaultChange` instead of a\n`/changes/\u003cid\u003e*` prefix wildcard, and match routes in LIFO order with\nexact paths preferred over wildcards (tie-broken by literal prefix\nlength) so tests can override default routes regardless of registration\norder.\n\nAlso add declarative `MockGerritServer` helpers (`OnComments`,\n`OnDrafts`, `OnReview`, `OnAccountSelf`, `OnSearchBuildsSequence`,\n`OnSearchBuildsByPatchset`, `WithCommitMessage`, and `WithPatchsetKind`)\nand remove unused mock helpers from `test_utils_test.go`.\n\nBug: b/575891963\nChange-Id: I5ac8e93dc0c4effaedb43e56b3ab8aad31b57d42\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/514156\n"
    },
    {
      "commit": "0a5061f9bd1bac7539a3ace60a905febee4cbbea",
      "tree": "9140062c3e9b1538b3908a3a5ab83a1bb34ad9c6",
      "parents": [
        "eed63e368eae2bff2ffcb53b7d8e16d5eb176f16"
      ],
      "author": {
        "name": "Eric Rahm",
        "email": "erahm@google.com",
        "time": "Wed Oct 28 00:29:32 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 00:29:32 2026 -0700"
      },
      "message": "pw_ghish: Add native Gerrit REST client and models\n\nIntroduce the native `GerritClient` and Gerrit REST data models in\n`pw_ghish/gerrit.go` to prepare for removing the third-party\n`github.com/andygrunwald/go-gerrit` dependency. `GerritClient` handles\nGerrit\u0027s `\")]}\u0027\"` XSSI prefix, bounded response reads, OAuth2 token\nrefresh on 401/403, and anonymous GET fallback on public hosts.\n\nBug: b/575891963, b/575892646\nChange-Id: Ie334850e30e3c4308a7ef7300d492123104b00d0\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/514155\n"
    },
    {
      "commit": "eed63e368eae2bff2ffcb53b7d8e16d5eb176f16",
      "tree": "41239666839444e7de4535ed8cb0198ba0cb677b",
      "parents": [
        "6f5dc3b96df56ae6b4cdfb7f86ed4dd6bdc2a576"
      ],
      "author": {
        "name": "Eric Rahm",
        "email": "erahm@google.com",
        "time": "Wed Oct 28 00:28:11 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 00:28:11 2026 -0700"
      },
      "message": "pw_ghish: Enforce fail-closed hermetic auth and network in unit tests\n\nIsolate unit tests from ambient workstation credentials and non-loopback\nHTTP via `TestMain` and `WithHermeticAuth`, and consolidate loopback\nhost checks onto an exact-match `isLoopbackHost`.\n\nBug: b/575891963, b/575892726\nChange-Id: Ib43b1cc61de93750d11c3330c3176307cc92ae09\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/514148\n"
    },
    {
      "commit": "6f5dc3b96df56ae6b4cdfb7f86ed4dd6bdc2a576",
      "tree": "0fcbbc42e747554a3b323c4c8cb9f926b1a6206c",
      "parents": [
        "8824f56c1993d185bdc6dd063458fd994f7f4170"
      ],
      "author": {
        "name": "Eric Rahm",
        "email": "erahm@google.com",
        "time": "Wed Oct 28 00:12:13 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 00:12:13 2026 -0700"
      },
      "message": "pw_ghish: Auto-configure sso-cred-helper for luci-auth on Corp Linux\n\nAutomatically set `LUCI_AUTH_CREDENTIAL_HELPER\u003d/usr/bin/sso-cred-helper`\nwhen invoking `luci-auth` on Corp Linux if unset in the environment, so\nnon-login shells can mint OAuth2 tokens from valid `gcert` sessions.\n\nBug: b/575891963, b/575892726\nChange-Id: I7e8a9c4d5b6f1e2a3c4d5e6f7a8b9c0d1e2f3a4b\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/514926\n"
    },
    {
      "commit": "8824f56c1993d185bdc6dd063458fd994f7f4170",
      "tree": "65f040dd5a8bdf70d0efaeb72dd8c42d509e75ae",
      "parents": [
        "3fd051c63d4c1a88943c97ed202e47292ceb9c9d"
      ],
      "author": {
        "name": "Eric Rahm",
        "email": "erahm@google.com",
        "time": "Wed Oct 28 00:11:04 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Wed Oct 28 00:11:04 2026 -0700"
      },
      "message": "pw_ghish: Share CI build partitioning and remove dead stdlib flags\n\nShare `selectVisibleBuilds` across `gh pr checks`, `gh run list`, and\n`gh run view` so all three commands partition non-passing builds first\nand collapse passing builds past `maxExpandedPassingChecks`.\n\nAlso remove unused standard-library `flag.*` registrations from\n`root.go` `init()`, as global flags are parsed through Cobra\u0027s\n`PersistentFlags()`.\n\nBug: b/575891963\nChange-Id: I3a44617d57dc936977cab222ab5764f5fd9ff717\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/514147\n"
    },
    {
      "commit": "3fd051c63d4c1a88943c97ed202e47292ceb9c9d",
      "tree": "c9f12c579610180179c106b9e7cf5a6a4fd8810f",
      "parents": [
        "c3fb327cbe985923191e7e977e59c75fd210174f"
      ],
      "author": {
        "name": "Keir Mierle",
        "email": "keir@google.com",
        "time": "Tue Oct 27 21:58:43 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Tue Oct 27 21:58:43 2026 -0700"
      },
      "message": "pw_cobs: Add Python implementation\n\nAdd a pure-Python (standard library only) pw_cobs package providing\nraw COBS encode/decode, incremental Streamer and Chunk encoding,\nstreaming frame Decoder, and size helpers (max_encoded_size,\nmax_decoded_size) matching the C++ API in pw::cobs.\n\nInclude unit tests mirroring the C++ test suite, plus a\npw_build.generated_tests suite (cobs_generated_test.py) that executes\ndata-driven encode, decode, and streaming Decoder test vectors in\nPython and generates matching C++ unit tests\n(//pw_cobs/cpp:cobs_generated_test) at build time.\n\nChange-Id: I57254ad78463f46e951c6abe84e7855ad067f369\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/503227\n"
    },
    {
      "commit": "c3fb327cbe985923191e7e977e59c75fd210174f",
      "tree": "1cb28537c63f3d0fdfe54de4488782f30a26d838",
      "parents": [
        "5946d068d3e1f505022dcdf80d6f0fe3e9f8e0a1"
      ],
      "author": {
        "name": "Lloyd Pique",
        "email": "lpique@google.com",
        "time": "Tue Oct 27 21:23:01 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Tue Oct 27 21:23:01 2026 -0700"
      },
      "message": "bazel: Prepare BUILD, Starlark, and Bzlmod files for Bazel 10\n\nUpdate Pigweed BUILD, Starlark, and Bzlmod files for Bazel 10\ncompatibility while remaining compatible with Bazel 8 and 9:\n- Add explicit visibility \u003d [\"//visibility:public\"] to exports_files()\n  calls referenced across packages (preparing for Bazel 10\u0027s\n  --incompatible_no_implicit_file_export default).\n- Replace removed @bazel_tools//src/conditions:host_windows with\n  @bazel_skylib//rules/private:is_windows in pw_build/copy_to_bin.bzl.\n- Replace removed new_git_repository with git_repository in\n  targets/pw_rp2350/zephyr/MODULE.bazel.\n- Align rules_python (1.9.1) and platforms (1.1.0) across sub-workspace\n  MODULE.bazel files.\n\nBug: 572017117\nTest: Presubmit\nChange-Id: I4bd24ce43120ad7648eb0b4d7389d40ec40f2d46\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/507609\n"
    },
    {
      "commit": "5946d068d3e1f505022dcdf80d6f0fe3e9f8e0a1",
      "tree": "b0b34793da28935b58154c861a8fe5c383b63219",
      "parents": [
        "d2f05a4dead21dfc083dc1d59401cba6fb5eb4d0"
      ],
      "author": {
        "name": "Keir Mierle",
        "email": "keir@google.com",
        "time": "Tue Oct 27 20:08:25 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Tue Oct 27 20:08:25 2026 -0700"
      },
      "message": "pw_build: Add Bazel TypeScript test rules\n\nIntroduce pw_ts_library and pw_ts_test in //pw_build:pw_ts.bzl backed by\nTypeScript compiler typechecking, esbuild bundling, and a lightweight\nNode.js Jest shim in //pw_build/ts:jest_shim.\n\nExpose //pw_web:tsc_bin and //pw_web:protos_lib, export js_protos for\npw_rpc2 test and echo protos, fix bitrotted types in\npw_rpc/ts/docs_example.ts, and wire up Bazel TypeScript libraries and\ntests across pw_status, pw_base64, pw_hdlc, pw_tokenizer,\npw_protobuf_compiler, pw_rpc, and pw_transfer.\n\nChange-Id: I88886dac82623dbbdbba7975df720d3e53c615b2\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/514163\n"
    },
    {
      "commit": "d2f05a4dead21dfc083dc1d59401cba6fb5eb4d0",
      "tree": "4398dcfdbaba534a0373746c603cb9c3534d804a",
      "parents": [
        "5c2a2113573ee1004a91f2dd5d3e0bc110a1b64a"
      ],
      "author": {
        "name": "Eric Rahm",
        "email": "erahm@google.com",
        "time": "Tue Oct 27 19:49:20 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Tue Oct 27 19:49:20 2026 -0700"
      },
      "message": "pw_ghish: Use pure-Go InjectChangeID instead of downloading hook\n\nAlways use `InjectChangeID` and `CommitAmendMessage` when inserting a\nmissing `Change-Id` during `gh pr create` and `gh pr push`, rather than\nfetching `\u003cgerrit\u003e/tools/hooks/commit-msg` over HTTP and writing to\n`.git/hooks`. Installing Git hooks is an explicit opt-in via\n`gh hook install --git`; uploading a CL should not silently download and\ninstall a hook script into the repository as a side effect.\n\nUpdate `InjectChangeID` to insert `Change-Id` into the final trailer\nparagraph via `ParseCommitMessage` (preserving `Bug:` and `Fixed:`\nfooters, `#` lines in committed messages, and `Signed-off-by:` ordering)\nand skip `fixup!`, `squash!`, and `amend!` commits.\n\nBug: b/575891963\nChange-Id: I9c4d1b8e2f0a5c7d3e6b8a1f4c9d2e5a7b0c3f68\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/514146\n"
    },
    {
      "commit": "5c2a2113573ee1004a91f2dd5d3e0bc110a1b64a",
      "tree": "0cbcb70aeec01f0c59ffafcd25a8bc28781b9deb",
      "parents": [
        "d89f4a8d6e4a5b9046aeb4e127d9d4e248335427"
      ],
      "author": {
        "name": "Wyatt Hepler",
        "email": "hepler@google.com",
        "time": "Tue Oct 27 15:51:36 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Tue Oct 27 15:51:36 2026 -0700"
      },
      "message": "pw_transport: Rename DatagramSocket to Socket\n\nImplement the following renames:\n\n- DatagramSocket → Socket\n- ReliableDatagramSocket → ReliableSocket\n- DatagramSocketImpl → SocketImpl\n- ReliableDatagramSocketImpl → ReliableSocketImpl\n- ReliableDatagramListener → ReliableListener\n- ReliableDatagramConnector → ReliableConnector\n\nKeep deprecated aliases for the old names. A future byte-oriented socket\nwill be ByteSocket.\n\nChange-Id: I7c813ad6952785fc5bbfee921aa7d4bd165ea32a\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/510649\n"
    },
    {
      "commit": "d89f4a8d6e4a5b9046aeb4e127d9d4e248335427",
      "tree": "62aa4e7af31de63656ecbb6d307da249678bbf30",
      "parents": [
        "247aaeada026803e8ca5629bb88dc261a35f0ab4"
      ],
      "author": {
        "name": "Eric Rahm",
        "email": "erahm@google.com",
        "time": "Tue Oct 27 15:44:41 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Tue Oct 27 15:44:41 2026 -0700"
      },
      "message": "pw_ghish: Add UI, JSON, and perf contract test suites and docs\n\nAdd automated contract tests, golden fixtures, and architectural\ndocumentation to lock in CLI consistency, prevent silent performance\nregressions, and enforce deterministic output for agents and scripts:\n\n- Add `command_kind_test.go`, `kind_contract_test.go`, and\n  `kind_fixture_test.go` to verify every runnable Cobra command declares\n  a valid `ghish:kind` annotation and adheres to its upper-bound\n  subprocess, RPC, byte, receipt, and verdict budgets in a hermetic\n  mock environment.\n- Add `export_test.go` to expose internal test helpers to external\n  tests without cyclic dependencies.\n- Add `design_contract_test.go`, `golden_test.go`, and 14 golden\n  snapshots in `testdata/golden/` to verify terminal rendering rules,\n  receipt formats, and answer-first layout.\n- Update `invariants_ast_test.go` with AST checks ensuring no raw ANSI\n  escapes exist outside `ui.go` and all process invocations route\n  through the counting `ExecCommand` helpers in `procexec.go`.\n- Add `json_contract_test.go` to enforce single-document JSON output,\n  non-null empty collections, and bare ASCII enum values.\n- Add `perfbudget_test.go` to pin exact subprocess and HTTP request\n  counts on the 9 hot commands.\n- Update `BUILD.bazel` to include the new test targets and fixtures.\n- Update `AGENTS.md`, `developing.rst`, `subcommands.rst`,\n  `agent_eval.rst`, `agent_workflows.rst`, and the `ghish` skill to\n  document invariants 15-16, broken pipe handling, and JSON contracts.\n\nTest: bazelisk test //pw_ghish/...\nChange-Id: Icbcd02745f650ad1d7c4b4ff43daee6a1cbc1933\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/511938\n"
    },
    {
      "commit": "247aaeada026803e8ca5629bb88dc261a35f0ab4",
      "tree": "f6a99a673617546775820f23b734c3f81cf4ebfa",
      "parents": [
        "a6164815b015e415ef40a21225e8d576a35fe2a5"
      ],
      "author": {
        "name": "Keir Mierle",
        "email": "keir@google.com",
        "time": "Tue Oct 27 12:46:15 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Tue Oct 27 12:46:15 2026 -0700"
      },
      "message": "pw_cobs: Process words at a time and add lookahead\n\n- Process one word at a time instead of byte-by-byte in Streamer::Write\n  and Decoder::ProcessChunk using single-pass word copies and\n  SIMD-Within-A-Register (SWAR) zero-byte detection (HasZeroByte /\n  FindFirstZero / CopyNonZero).\n- Expose Decoder::remaining_in_run() and Decoder::ProcessChunk() so\n  streaming UART/DMA drivers can coalesce reads using the remaining\n  non-zero bytes in the active COBS block and decode one frame per poll.\n- Add //pw_cobs/cpp:cobs_perf_test benchmark suite.\n\nCortex-M3 cycle counts (bazelisk run --config\u003dlm3s6965evb\n//pw_cobs/cpp:cobs_perf_test):\n\n  Benchmark                       Before    After   Speedup\n  ---------------------------------------------------------\n  CobsEncode_254NonZero            2,589    1,028     2.52x\n  CobsEncode_1024NonZero          10,428    2,846     3.66x\n  CobsEncode_1024Mixed            10,646    3,136     3.39x\n  CobsEncodeInPlace_254NonZero     1,587      685     2.32x\n  CobsDecode_254NonZero            2,362      690     3.42x\n  CobsDecode_1024Mixed             9,506    2,780     3.42x\n  CobsStreamingDecoder_1024Mixed   9,480    2,755     3.44x\n\nChange-Id: Icadd7979125ba38486b1b187ce54ce3708c1672b\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/510546\n"
    },
    {
      "commit": "a6164815b015e415ef40a21225e8d576a35fe2a5",
      "tree": "11ccc3538f3b25cd9f08d3eba52f64be4e7fb62d",
      "parents": [
        "611d9f58a1e6739563f6089a49fb4e18f9d75d25"
      ],
      "author": {
        "name": "Alexei Frolov",
        "email": "frolv@google.com",
        "time": "Tue Oct 27 12:21:35 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Tue Oct 27 12:21:35 2026 -0700"
      },
      "message": "pw_async2: Transfer TimeFuture wakers on move\n\nMoving a TimeFuture moved its place in its provider\u0027s timer list, but\nleft its waker in the moved-from future. Moving a TimeFuture after it\nwas pended therefore left its task stalled when the timer expired.\nThe moved-from future also remained pendable, and completed immediately\nif pended. This violates async2 semantics, which require a moved-from\nfuture to be empty.\n\nUpdate TimeFuture to correctly transfer the waker into the target when\nmoved. Self-move assignment also no longer unlists the timer.\n\nAdditionally, document that moving a future transfers its operation and\nleaves the moved-from future empty, and update the composite future\nexample\u0027s move operations to follow this contract.\n\nChange-Id: I0680d480165eb547145fbfe07e80cc05993630e5\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/513806\n"
    },
    {
      "commit": "611d9f58a1e6739563f6089a49fb4e18f9d75d25",
      "tree": "3422bd273ba2b5a537743b7e33f4ccaa451154d2",
      "parents": [
        "085145f2451fb51b9138c687dae26dc020ca20f1"
      ],
      "author": {
        "name": "Keir Mierle",
        "email": "keir@google.com",
        "time": "Tue Oct 27 12:20:21 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Tue Oct 27 12:20:21 2026 -0700"
      },
      "message": "pw_transfer: Require resource_id on V2 start chunks\n\nValidate that non-legacy initial chunks include resource_id in addition\nto desired_session_id before dereferencing the std::optional in\nTransferService::HandleChunk, returning DATA_LOSS on malformed chunks.\n\nFixed: b/525190611\n\nChange-Id: Iedf9837c20c2376738214bd39bbbda538ce676df\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/499814\n"
    },
    {
      "commit": "085145f2451fb51b9138c687dae26dc020ca20f1",
      "tree": "160c918e90848c495130585c681a66e4b3607dd7",
      "parents": [
        "df2bf3d1cb7ef797a30a82fb1b99e06da5c21cd6"
      ],
      "author": {
        "name": "Liam Bucci",
        "email": "liambucci@google.com",
        "time": "Tue Oct 27 11:57:35 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Tue Oct 27 11:57:35 2026 -0700"
      },
      "message": "pw_transfer: Fix concurrency and timeout races in Java client\n\nFix several concurrency bugs and timeout race conditions in the Java\npw_transfer client that caused TransferClientTest to deadlock or time\nout on fast multi-core machines:\n\n- Fire transfer timeouts in Transfer.handleTimeoutIfDeadlineExceeded()\n  when the deadline is reached (!Instant.now().isBefore(deadline))\n  rather than strictly after, so 0-delay write chunk timeouts fire even\n  within the same clock tick.\n- Ensure waitUntilEventsAreProcessedForTest() processes due timeouts and\n  waits until both the event queue is empty and no immediate timeouts\n  remain before releasing the semaphore, preventing an AB-BA monitor\n  deadlock between Endpoint and TestClient.\n- Use a do-while loop in runForTestsThatMustTimeOut() so it blocks on\n  events.poll() until the next timeout instead of busy-spinning at 100%\n  CPU when the event queue is empty.\n- Move VersionedChunk.fromMessage() inside the queued event in\n  ChunkHandler.onNext() so legacyIdToSessionId is only accessed on the\n  transfer event handler thread.\n- Copy sessionIdToTransfer values before iterating in stop() to avoid\n  ConcurrentModificationException when transfers unregister on\n  termination.\n\nChange-Id: Ib6ae53efcfd67b1fee3c6117485c191024b084fc\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/497354\n"
    },
    {
      "commit": "df2bf3d1cb7ef797a30a82fb1b99e06da5c21cd6",
      "tree": "5aa89c7065361c423c707c2d6164d6a4cf2d8f0a",
      "parents": [
        "34b3dd897d61a3bc3555bed7a4f13302366696a3"
      ],
      "author": {
        "name": "Rob Mohr",
        "email": "mohrr@google.com",
        "time": "Tue Oct 27 11:40:38 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Tue Oct 27 11:40:38 2026 -0700"
      },
      "message": "pw_env_setup: Retry pip on network errors\n\npip only retries connection setup and response headers. A read timeout\nwhile streaming a response body (a wheel or its metadata) is fatal in\npip versions before 25.1, which do not resume downloads. With pip\u0027s\ndefault 15 second socket timeout, a single stalled read from PyPI fails\nthe whole environment setup, and rerunning it typically succeeds.\n\nThis affects every pip invocation during setup: the initial pip\nupgrade (which runs with the venv\u0027s bundled pip), the requirements\ninstall, and the pip installs run by the GN Python build.\n\nMake these more robust:\n- Default PIP_DEFAULT_TIMEOUT to 60 seconds unless already set.\n- Retry the pip install commands and the GN Python ninja build up to\n  3 times when the output indicates a transient network error. Ninja\n  only reruns the failed steps.\n- Stop dumping the full environment into the command log when an\n  explicit env is passed.\n\nFixed: b/552052827\nWant-Review: all\nChange-Id: I97d1d7082d683219864be47840fc956669de7e26\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/514162\n"
    },
    {
      "commit": "34b3dd897d61a3bc3555bed7a4f13302366696a3",
      "tree": "6ba774b61287de5c3951b41ead2cb3142e68a699",
      "parents": [
        "5de2117c95bb4fadc96d531e510b8d0f9af91c3d"
      ],
      "author": {
        "name": "Dave Roth",
        "email": "davidroth@google.com",
        "time": "Tue Oct 27 11:21:41 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Tue Oct 27 11:21:41 2026 -0700"
      },
      "message": "pw_hal/uart: Drop gtest dep from sync_uart_test\n\nTests defined with pw_cc_test should not directly depend on\n@com_google_googletest//:gtest; the test framework backend\nis injected via pw_unit_test. In sync_uart_test.cc, include\npw_unit_test/framework.h rather than gtest headers.\n\nThis also prevents build failures when downstream build systems\nimport Pigweed, where @com_google_googletest does not exist.\n\nChange-Id: Id6621f2fedc27dee2cdc0830339064996b078d3c\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/514161\n"
    },
    {
      "commit": "5de2117c95bb4fadc96d531e510b8d0f9af91c3d",
      "tree": "7166f4447145f88342649126e07b9e2183d9a7a5",
      "parents": [
        "19a7c55021c697000f3413dd480a2ef6c226d332"
      ],
      "author": {
        "name": "Dave Roth",
        "email": "davidroth@google.com",
        "time": "Tue Oct 27 11:01:22 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Tue Oct 27 11:01:22 2026 -0700"
      },
      "message": "pw_kernel: Set pw_assert_backend_pw_log for device targets\n\nCommit 6140196d8 switched the default //pw_assert/rust:pw_assert_backend\nlabel flag to :pw_assert_backend_std, which requires std and marks\nno_std kernel device targets incompatible unless overridden.\n\nExplicitly set @pigweed//pw_assert/rust:pw_assert_backend to\n@pigweed//pw_assert/rust:pw_assert_backend_pw_log in\nKERNEL_DEVICE_COMMON_FLAGS.\n\nBug: 563018764\nChange-Id: I7b3b0a735ce48ce45717f6a1454e46e06c122231\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/514826\n"
    },
    {
      "commit": "19a7c55021c697000f3413dd480a2ef6c226d332",
      "tree": "c128481736ba02f1ef40dc6cce5d48b49628f6e6",
      "parents": [
        "b4a92ac6a733b1dac0b87c8e32404580077cc618"
      ],
      "author": {
        "name": "Wyatt Hepler",
        "email": "hepler@google.com",
        "time": "Tue Oct 27 10:57:07 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Tue Oct 27 10:57:07 2026 -0700"
      },
      "message": "pw_enum: Length-prefix fields in enum version hashes\n\nThe version hash concatenated each enumerator\u0027s value and display name\nwithout delimiters, so different enums could hash identical bytes (e.g.\nvalue 1 named \"0X\" and value 10 named \"X\" both hash \"10X\") and share a\ntoken domain. Length-prefix every hashed field so that distinct enums\nalways hash distinct bytes.\n\nThis changes the token domain of every pw_enum enum.\n\nChange-Id: I518101f1bdc638d211557d511b30428e924c3830\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/512267\n"
    },
    {
      "commit": "b4a92ac6a733b1dac0b87c8e32404580077cc618",
      "tree": "846df89952037549a57484d4b61df8fe01766950",
      "parents": [
        "fb98df09f865898a77e1cf573d36e737072ef691"
      ],
      "author": {
        "name": "Josh Conner",
        "email": "joshconner@google.com",
        "time": "Tue Oct 27 10:50:41 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Tue Oct 27 10:50:41 2026 -0700"
      },
      "message": "pw_bluetooth: Update hci_events.emb definitions\n\nUpdate hci_events.emb to match the Bluetooth Core v6.2 specification:\n- Add [maximum_bits: 8] to EncryptionStatus.\n- Add v6.0/v6.2 flags to LEFeatureSet (bits 42, 45-48, 63).\n- Add missing command flags and spec-aligned flag aliases (marking old\n  names deprecated) to SupportedCommands.\n- Add lmp_features_bits view to\n  ReadLocalSupportedFeaturesCommandCompleteEvent.\n- Allow 0x00 in ReadBufferSizeCommandCompleteEvent\n  synchronous_data_packet_length and PAST v2 subevent parameters.\n- Fix LEAdvertisingReportSubevent.num_reports max (0x19), reorder\n  7.7.65.24 and 7.7.65.34 subevents into numeric order, and remove\n  obsolete TODO comments.\n\nTest: bazelisk test //pw_bluetooth:emboss_test\nChange-Id: I72af790539b1abd9cfa8999f8c76f8a622857cf3\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/509848\n"
    },
    {
      "commit": "fb98df09f865898a77e1cf573d36e737072ef691",
      "tree": "c658ea495eeaa1279ed0c3da1a008bf222648cb6",
      "parents": [
        "ca486480ecbb0b95dfba1253ffe7e3c101fe9fc1"
      ],
      "author": {
        "name": "Rob Mohr",
        "email": "mohrr@google.com",
        "time": "Tue Oct 27 10:15:04 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Tue Oct 27 10:15:04 2026 -0700"
      },
      "message": "pw_ghish: Fix ./gh outside a Pigweed checkout\n\nThe warm fast path reads four lines from a single `git rev-parse` call.\nOutside a Pigweed checkout (a copy of the script in another repository,\nor no repository at all) that call fails and prints fewer lines, so a\n`read` fails and `set -e` silently ends the script with status 1 before\nit can fall back to the CIPD prebuilt.\n\nTolerate missing lines and discard values that are not object IDs, so\nthe script continues to the CIPD fallback as it did before the fast\npath was added.\n\nChange-Id: I57c7bf412562dec0217ffed64334c460daa97e73\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/514745\n"
    },
    {
      "commit": "ca486480ecbb0b95dfba1253ffe7e3c101fe9fc1",
      "tree": "1e93fefcee053dfa07d5f10e3479573a0b1cf4ab",
      "parents": [
        "90f817d8454eb7b2935f59929e83cb45ac58b3ad"
      ],
      "author": {
        "name": "Keir Mierle",
        "email": "keir@google.com",
        "time": "Tue Oct 27 09:56:10 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Tue Oct 27 09:56:10 2026 -0700"
      },
      "message": "pw_perf_test: Add baremetal Cortex-M SysTick timer\n\nARMv6-M (Cortex-M0/M0+), ARMv8-M Baseline (Cortex-M23), and QEMU\u0027s\nCortex-M emulation do not implement the DWT CYCCNT register\n(0xE0001004), causing arm_cortex_timer to read 0 on every timestamp.\n\n- Add //pw_perf_test:arm_cortex_systick_timer, a standalone baremetal\n  timer backend using the architectural 24-bit SysTick counter\n  (0xE000E010..0xE000E018) configured for free-running wraparound at\n  processor clock rate without RTOS tick interrupts.\n- Fix the kDwtCyccnt identifier spelling and verify DEMCR/DWT_CTRL bits\n  in arm_cortex_timer::TimerPrepare().\n- Wire //pw_perf_test:arm_cortex_systick_timer as the test_timer_backend\n  for the baremetal lm3s6965evb_qemu target (leaving\n  lm3s6965evb_freertos on its FreeRTOS-aware freertos_systick_timer) and\n  drop unused chrono/thread deps from //pw_perf_test:timer_test.\n\nChange-Id: Iedbcb26fe8d84fb97ee9d5cb79d3985af23bf173\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/512089\n"
    },
    {
      "commit": "90f817d8454eb7b2935f59929e83cb45ac58b3ad",
      "tree": "16ec204a545f099149b1a903042b2bffe0f8b44a",
      "parents": [
        "7e77b2b617de21e9dc0104b83e27b19d489e76d6"
      ],
      "author": {
        "name": "Devan Yu",
        "email": "devanyu@google.com",
        "time": "Tue Oct 27 03:55:19 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Tue Oct 27 03:55:19 2026 -0700"
      },
      "message": "pw_bluetooth_sapphire: Keep connected dual-mode peers non-temporary\n\nPreviously, an unbonded dual-mode peer would become temporary when one\nof its transports disconnected while the other stayed connected. Make a\npeer temporary only when it\u0027s disconnected over all transports.\n\nTest: bazelisk test --config\u003dgoogletest\n      pw_bluetooth_sapphire/host/gap:gap_test\nChange-Id: I6b7481e10b7e4a7d88fe41b00727994a2994d209\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/505265\n"
    },
    {
      "commit": "7e77b2b617de21e9dc0104b83e27b19d489e76d6",
      "tree": "3bc2658aae3bfa0024b17e32bef7e96445e94565",
      "parents": [
        "3a979342cd07275ea298bd521f36834902a6f414"
      ],
      "author": {
        "name": "Devan Yu",
        "email": "devanyu@google.com",
        "time": "Tue Oct 27 03:55:12 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Tue Oct 27 03:55:12 2026 -0700"
      },
      "message": "pw_bluetooth_sapphire: Expire unbonded peers after they disconnect\n\nUnbonded public LE peers stayed non-temporary after disconnecting, so\nthey were never removed from the peer cache. Check bonded() instead of\nidentity_known() in Peer::TryMakeTemporary so that only connected and\nbonded peers remain non-temporary.\n\nUnbonded BR/EDR peers did become temporary on disconnect but updated\ntheir expiry before the state change, so they were never removed.\nUpdate the expiry after the temporary state change instead.\n\nThis also bounds how much a remote device can grow the peer cache by\nconnecting with spoofed public addresses, since such peers now expire.\n\nFixed: 525193229\nTest: bazelisk test --config\u003dgoogletest\n      pw_bluetooth_sapphire/host/gap:gap_test\nChange-Id: I78fcb58cf893006a9aa53e3183a39ad4eea866e1\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/503625\n"
    },
    {
      "commit": "3a979342cd07275ea298bd521f36834902a6f414",
      "tree": "69d50c3a1c0e40731e6290553782ad7b77443cda",
      "parents": [
        "5774a4c2ca9e4096ea1b1acaf81e0f1b01c58be0"
      ],
      "author": {
        "name": "Benny Wen",
        "email": "shenghanw@google.com",
        "time": "Tue Oct 27 03:02:17 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Tue Oct 27 03:02:17 2026 -0700"
      },
      "message": "pw_ghish: Space out --stack --nightly schedules\n\nWith --stack --nightly, each change took the nightly slot of its own\nchange number, so a stack of consecutive changes was scheduled about a\nminute apart, in no particular order. Give the bottom change its nightly\nslot and each change above it 30 minutes later, as --submit-at already\ndoes. Times past the end of the nightly window are kept.\n\nAlso keep a stack in order when \"now\" falls between its times. Each\nchange picked \"today\" or \"tomorrow\" from its own HH:MM, so at 21:45 with\nthe bottom change at 21:30, the bottom went to tomorrow 21:30 and the\nnext change to today 22:00. Count every change from the bottom change\u0027s\nactual date and time instead, naming a change two days out by its\nweekday. Gerrit Flows reads a weekday as its next occurrence after today\n(weekdayWaitExpression in Bugjuggler\u0027s libjuggler waitparser.go).\n\nBug: b/576920195\nChange-Id: I632927666ea0448e45eabe48fdb5675b8e28b5f3\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/511565\n"
    },
    {
      "commit": "5774a4c2ca9e4096ea1b1acaf81e0f1b01c58be0",
      "tree": "b0771bf9739682f406083aba313f17639d59c2be",
      "parents": [
        "ada4aaba23dc9f646e733e1a017fa93bbbfc5a14"
      ],
      "author": {
        "name": "Keir Mierle",
        "email": "keir@google.com",
        "time": "Mon Oct 26 20:58:25 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Mon Oct 26 20:58:25 2026 -0700"
      },
      "message": "docs: Disallow nested code in bold or italic\n\nreStructuredText does not support nested inline markup, so placing\ndouble-backtick inline code (``...``) inside bold (**...**) or italic\n(*...*) spans leaves literal backticks in the rendered HTML output.\n\nAdd a Sphinx doctree-read check in docs/common/__init__.py that emits a\nwarning when a strong or emphasis AST node contains literal double\nbackticks, and fix existing occurrences across module documentation.\n\nChange-Id: I87e4ed08ddeb8b4a0f48a646d82e2be933fb3b5f\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/513205\n"
    },
    {
      "commit": "ada4aaba23dc9f646e733e1a017fa93bbbfc5a14",
      "tree": "f890d15ea0c6c3eefba568bd38244d1ac52f5ead",
      "parents": [
        "2890b7204911136a6baf9a73889b85b6882a4349"
      ],
      "author": {
        "name": "Alexei Frolov",
        "email": "frolv@google.com",
        "time": "Mon Oct 26 15:03:48 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Mon Oct 26 15:03:48 2026 -0700"
      },
      "message": "pw_ghish: Don\u0027t export PW_ variables from the gh wrapper\n\nThe gh wrapper exported PW_GH_SCRIPT_DIR for the binary, which passes\nits environment to every subprocess, including the pre-push hook that\n`./gh pr create` triggers. Pigweed\u0027s environment parser rejects\nunrecognized PW_ variables, so presubmit checks that parse the\nenvironment, such as source_is_in_cmake_build_warn_only, failed and\nblocked the push.\n\nRename the variable to _PW_GH_SCRIPT_DIR, following the underscore\nconvention the wrapper already uses for _PW_GH_OUT_DIR, and test that\nthe wrapper exports no PW_ variables.\n\nChange-Id: Id5f9299d41439892a4cdd9fa61b9816b97248c2e\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/513885\n"
    },
    {
      "commit": "2890b7204911136a6baf9a73889b85b6882a4349",
      "tree": "60b418d3941dea839e96a58bc8c237ffb6aa8a83",
      "parents": [
        "29bf82a850122fb7c15f574972b9afc7938b28fe"
      ],
      "author": {
        "name": "Wyatt Hepler",
        "email": "hepler@google.com",
        "time": "Mon Oct 26 14:55:34 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Mon Oct 26 14:55:34 2026 -0700"
      },
      "message": "pw_transport: Add ForwardingDatagramSocketPair\n\nImplement ForwardingDatagramSocketPair and\nForwardingDatagramSocketOptions in pw_transport as a public,\nreference-counted, zero-copy in-memory pair of ReliableDatagramSocket\nendpoints with configurable queue depth and write backpressure.\n\nReplace PairedConnection in pw_rpc2 tests with\nForwardingDatagramSocketPair.\n\nChange-Id: I1f2ed303161ea1c07a295d64a856913379c7402e\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/505886\n"
    },
    {
      "commit": "29bf82a850122fb7c15f574972b9afc7938b28fe",
      "tree": "fb3ece7b34e17147279a61292172e419abeec3e2",
      "parents": [
        "ae27720a6036d1963faa6d8d348aa9b80d4b9db2"
      ],
      "author": {
        "name": "Liam Bucci",
        "email": "liambucci@google.com",
        "time": "Mon Oct 26 14:00:19 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Mon Oct 26 14:00:19 2026 -0700"
      },
      "message": "pw_hal/uart: Add initial BufferedUartDriver API\n\n- Adds BufferedUartDriver HAL API - This is the low level abstract\n  interface which must be implemented for each device family.\n- Adds SyncBufferedUart interface layer - This is the \"high level\"\n  interface which supports synchronous reads/writes to the underlying\n  abstract Uart device. This is hardware agnostic and can be reused on\n  all hardware which implements a BufferedUartDriver.\n- Adds GmockBufferedUartDriver for use with gmock testing.\n- Adds unit tests for SyncBufferedUart using the gmock mock.\n\nChange-Id: I418c18716c940391f609833283423fcb45284cf0\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/488749\n"
    },
    {
      "commit": "ae27720a6036d1963faa6d8d348aa9b80d4b9db2",
      "tree": "6b764de33c8fcdccc987edfe65a4b19545d7be1f",
      "parents": [
        "54535fe24ef2075edd36130217b8313732f7bc71"
      ],
      "author": {
        "name": "Lloyd Pique",
        "email": "lpique@google.com",
        "time": "Mon Oct 26 13:58:52 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Mon Oct 26 13:58:52 2026 -0700"
      },
      "message": "pw_env_setup, bazel: Roll back certifi to 2026.10.19 and pip to 26.2.1\n\nRoll back certifi from 2026.10.23 to 2026.10.19 across virtualenv\nconstraints, lockfiles, and the rules_python patch. Version 2026.10.23\nis not yet available in downstream package mirrors/caches, breaking\ndownstream consumers. Version 2026.10.19 still removes the distrusted\neMudhra root certificate (GHSA-6q48-6c7w-9gw2).\n\nAdditionally, roll back rules_python\u0027s internal pip wheel from 26.2.2\nto 26.2.1 in the patch, as 26.2.2 is likewise unavailable in the same\ndownstream caches. Although 26.2.1 is affected by GHSA-f8vq-jw3w-q789,\ninternal pip is only used by rules_python for sdist fallback, which is\nalready protected against unverified network requests via --no-index\nand --no-build-isolation in extra_pip_args, and as it was a\nsingle_version_override, the impact is only to Pigweed should any of the\nother mitigations fail.\n\nBug: b/577168466\nChange-Id: I836ef37107e945961386f6fb0c4b90589984c573\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/513905\n"
    },
    {
      "commit": "54535fe24ef2075edd36130217b8313732f7bc71",
      "tree": "c5f0ee1b6093a183a95efa24981b60803152ff53",
      "parents": [
        "fae2a526fc9fcd9eecf8ebc71167f7b46d47115a"
      ],
      "author": {
        "name": "Alexei Frolov",
        "email": "frolv@google.com",
        "time": "Mon Oct 26 13:36:27 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Mon Oct 26 13:36:27 2026 -0700"
      },
      "message": "pw_bluetooth_proxy: Wake sniff timeout task when its timer is reset\n\nTimeoutTask::WaitFor() replaces the timer that the task is pending from\noutside of the task. The new timer has no waker, so the task was only\nwoken because moving a TimeFuture left the previous timer\u0027s waker in\nplace. This is a bug in TimeFuture, which should not be relied on.\n\nUpdates the task to store a waker for the task whenever it waits, and\nwake it when WaitFor() resets the timer so that it pends the new timer.\n\nChange-Id: Ia64343687f5f56c2aa3b79bef34668422358b7c8\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/513805\n"
    },
    {
      "commit": "fae2a526fc9fcd9eecf8ebc71167f7b46d47115a",
      "tree": "3455134b9ff4f29958b121803006b354c013dab7",
      "parents": [
        "173fcc81ccb92871c65155fe65764ae3a7d75b58"
      ],
      "author": {
        "name": "Eric Rahm",
        "email": "erahm@google.com",
        "time": "Mon Oct 26 12:56:39 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Mon Oct 26 12:56:39 2026 -0700"
      },
      "message": "pw_ghish: Add issue receipts, verdicts, and comment folding\n\nInteractive and agentic Buganizer workflows require consistent command\nconfirmations, actionable next steps, and bounded context sizes. Raw\nbot commit notifications and unbounded comment threads flood terminal\nand agent context windows, while mutation commands lack receipts.\n\nStandardize issue mutations and optimize display formatting:\n- Standardize mutation commands (`create`, `edit`, `comment`, `close`,\n  `reopen`, `develop`) on `PrintReceipt` with `Next:` hints, and\n  annotate subcommands with `ghish:kind` metadata.\n- Add structured `Verdict:` and `Next:` lines to `issue view`, `issue\n  list`, and `issue status`.\n- Parallelize `issue view --comments` RPCs with issue metadata lookups,\n  cancelling in-flight comment queries if `GetIssue` fails.\n- Collapse bot-authored Gerrit commit dumps into single-line summaries\n  and fold human comment threads past 15 comments (expand with `--all`).\n- Fold `issue status` sections beyond 10 items (expand with `-v`), and\n  shorten user email displays by stripping `@google.com` domains.\n- Support `issue develop --json` for standard branch checkouts and route\n  git stdout to stderr under JSON mode to ensure clean machine output.\n- Update `issue.rst` documentation for worktree badges and comment\n  folding, and add unit test coverage in `cmd_issue_test.go`.\n\nTest: bazelisk test //pw_ghish:pw_ghish_test\nChange-Id: Ia4b8c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/511937\n"
    },
    {
      "commit": "173fcc81ccb92871c65155fe65764ae3a7d75b58",
      "tree": "db967a226740931daf495deca8c2552f9b362c04",
      "parents": [
        "d71fdd4174f8592cd333641468d7dcb5436e69c4"
      ],
      "author": {
        "name": "Eric Rahm",
        "email": "erahm@google.com",
        "time": "Mon Oct 26 12:33:35 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Mon Oct 26 12:33:35 2026 -0700"
      },
      "message": "pw_ghish: Optimize worktree plumbing, Gerrit batching, and UI\n\nFrequent worktree inspections (`wt list`, `sense`, and slot eviction)\nspawned redundant git subprocesses and serial Gerrit queries, adding\nlatency to interactive workflows. Furthermore, status outputs mingled\ndisplay glyphs into JSON fields, hindering programmatic parsing.\n\nParallelize slot inspection in `wt list` and candidate dirty checks in\nslot eviction using bounded concurrency semaphores. Collapse per-slot\nahead-count and `Change-Id` queries into a single `git log` execution\n(`InspectHeadAheadChangeID`).\n\nIn `git.go`, optimize `RunInDir` by scrubbing repo-local git environment\nvariables (`ScrubRepoLocalGitEnv`) and setting `GIT_CONFIG_NOSYSTEM\u003d1`\nand `GIT_OPTIONAL_LOCKS\u003d0` for read-only operations\n(`IsReadOnlyGitQuery`). Skip redundant `git rev-parse --show-toplevel`\ncalls when `PrimaryRepo` is already recorded.\n\nQuery batched Gerrit CL status chunks concurrently with bounded\nparallelism. Introduce `wt audit` as a dedicated read-only health\nchecker that returns a non-zero exit code when checklist errors are\nfound. Introduce `perfbudget_test.go` to enforce a strict subprocess\nbudget for `wt list` (0 base + 2 per slot).\n\nNormalize `StatusBadge` and `ChecklistStatus` values to bare ASCII\nenums in JSON payloads, isolating glyph formatting to display methods.\nStandardize `wt` mutation receipts, add structured `Verdict:` / `Next:`\nlines to `wt list`, `wt audit`, and `sense`, cache Gerrit self-account\nlookups, and clean HTML detail blocks from `sense` comment previews.\nUpdate documentation and test suites to match the standardized format.\n\nTest: bazelisk test //pw_ghish/...\nChange-Id: I1970afb92b9f5e16869b3e3dce44c0997288e467\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/511936\n"
    },
    {
      "commit": "d71fdd4174f8592cd333641468d7dcb5436e69c4",
      "tree": "a48178a88e1dae846ba22eeda53d7962ac0ad9fb",
      "parents": [
        "b1d1d1528486c3f2133ad32214e6c654c1c54dc1"
      ],
      "author": {
        "name": "Eric Rahm",
        "email": "erahm@google.com",
        "time": "Mon Oct 26 12:30:08 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Mon Oct 26 12:30:08 2026 -0700"
      },
      "message": "pw_ghish: Improve CI check/run verdicts and failure log excerpts\n\nWhen changes run across large CI builder matrices, long lists of\npassing checks overwhelm terminal output and obscure build failures.\nAdditionally, raw failure logs often span hundreds of lines where\nroot-cause diagnostics are buried above trailing shutdown noise, and\nidentical builder failures print repetitive log snippets.\n\nIn checks.go and run.go, partition builds to order failures before\npassing checks (PartitionAndOrderBuilds). Collapse passing checks when\nthey exceed 5 builders (maxExpandedPassingChecks) into a summary line,\nrestorable via --all. Add structured Verdict: and Next: footers across\npr checks, run list, and run view, and shorten redundant stderr errors\nin checks when verdict footers are displayed.\n\nExtract failure-detection heuristics into failure_detector.go (shared by\nluci.go and busytown.go) with unit tests in failure_detector_test.go.\nScore log lines using a 3-rank diagnostic priority (Rank 1 located\ncompiler/linker/test errors, Rank 2 failure headers, Rank 3 generic\nerror tokens) to extract a 25-line window with 5 lines of leading\ncontext around the top diagnostic. Cap summaries via\ncompactFailureSummary, record LogTotalLines, and deduplicate identical\nfailure signatures across builders in FormatFailureReports.\n\nIn run.go, add mutation receipts to run rerun. In checks.go, mark\nStatusSymbol with json:\"-\" to keep glyphs out of JSON output. In\nbusytown.go, invoke ExecCommandContext in BusytownExecCommandFn to\nsupport test execution mocking. Update run.rst documentation.\n\nTest: bazelisk test //pw_ghish:pw_ghish_test\nChange-Id: I1756a6aa313a3744c8ac66970baf666535a92c38\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/511935\n"
    },
    {
      "commit": "b1d1d1528486c3f2133ad32214e6c654c1c54dc1",
      "tree": "f505dc86757b1276d9b07a47c7b5736daaf71158",
      "parents": [
        "8d9a94ebabf7e32bed26197906c9437bfe51757e"
      ],
      "author": {
        "name": "Eric Rahm",
        "email": "erahm@google.com",
        "time": "Mon Oct 26 12:29:08 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Mon Oct 26 12:29:08 2026 -0700"
      },
      "message": "pw_ghish: Collapse PR RPC waterfalls and add view/status verdicts\n\nEliminate serial RPC waterfalls and redundant round-trips in PR\ncommands to accelerate interactive CLI responsiveness and provide\nanswer-first status summaries.\n\nIn pr status and pr list, use PeekSelfAccountCache to avoid blocking\non a serial /accounts/self network round-trip when cached, rewriting\n@me filter queries to numeric account IDs. In pr status, pipeline\nGerrit host resolution, comments, and drafts concurrently in Wave 1,\nand introduce Verdict and Next headers to summarize review blockers.\n\nIn pr view, prefetch comments and drafts concurrently with GetChange in\nWave 1, cancelling in-flight requests immediately if change lookup\nfails. Gate the Wave 2 ListFiles RPC on explicit --json files or .files\ntemplate usage. Add computeChangeVerdict to derive actionable next\nsteps (e.g. CI logs or unresolved comment viewing).\n\nIn comment_tree, add FormatCommentForestWithOptions and\nCountUnresolvedThreads to suppress resolved comment threads by default\nand fold excess unresolved threads, with a new --all flag on pr view to\nexpand all threads. In comments_summary, ensure unresolved comment\nslices serialize as empty lists instead of null in JSON output.\n\nTest: bazelisk test //pw_ghish:pw_ghish_test\nChange-Id: I6e5b8c9d0a1f2e3b4c5d6e7f8a9b0c1d2e3f4a5b\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/511934\n"
    },
    {
      "commit": "8d9a94ebabf7e32bed26197906c9437bfe51757e",
      "tree": "ce9863ac9e68836130015aab34d199f02294ef6b",
      "parents": [
        "ff6b38fa6f5e0e47a1b940525e7661f54cb6469c"
      ],
      "author": {
        "name": "Eric Rahm",
        "email": "erahm@google.com",
        "time": "Mon Oct 26 12:19:31 2026 -0700"
      },
      "committer": {
        "name": "CQ Bot Account",
        "email": "pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com",
        "time": "Mon Oct 26 12:19:31 2026 -0700"
      },
      "message": "pw_ghish: Cache Gerrit self-account and memoize auth tokens\n\nRepeated CLI invocations and multi-RPC commands incur redundant network\nand subprocess overhead from re-querying Gerrit /accounts/self,\nre-evaluating auth modes on each HTTP round trip, repeatedly probing\nunset Buganizer quota projects, and prematurely expiring OAuth tokens.\n\nOptimize auth and account lookup performance across the CLI:\n- account.go: Cache resolved /accounts/self metadata per host in\n  ~/.cache/pw_ghish/accounts.json (24-hour TTL, 0700 dir, 0600 file\n  mode with atomic tempfile replacement) and provide\n  PeekSelfAccountCache for non-blocking cache lookups.\n- auth.go: Parse token expiry from `luci-auth token -json-output -`\n  (up to 45-minute TTL) to memoize tokens until true expiration across\n  Gerrit, LUCI, Android Build, and Buganizer. Memoize ResolveAuthMode\n  results across requests in LUCIAuthTransport and reuse Config\u0027s\n  GitClient prefetch. Check candidate paths in findLuciAuthBinary before\n  spawning `git rev-parse`.\n- issuetracker.go: Memoize checked Buganizer quota projects (including\n  empty lookups) per runner, skip redundant keys when ProjectConfig is\n  loaded, and route quota-unset writes through the shared Git client to\n  invalidate config caches.\n- auth_cmd.go: Annotate auth and status commands as KindView, adopt\n  shared UI glyphs (GlyphPass, GlyphFail, GlyphWarn), add Verdict and\n  Next guidance, and use structured UnknownJSONFieldsError.\n- root.go \u0026 root_test.go: Remove obsolete Execute helper in favor of\n  runMain / runMainHelpForTest, and remove superseded request budget\n  tests.\n\nTest: bazelisk test //pw_ghish:pw_ghish_test\nChange-Id: I7d3ad0550635eff228bf7405db84afb52f311dce\nReviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/511933\n"
    }
  ],
  "next": "ff6b38fa6f5e0e47a1b940525e7661f54cb6469c"
}
