)]}'
{
  "commit": "f9dd287c3f6b3c94551bebf75f5efe404684d06a",
  "tree": "852b8ad9f307e49e65080d3f83c36e89930f1bfb",
  "parents": [
    "29242717a0ee3c8d46281111a964ae8ab114f181"
  ],
  "author": {
    "name": "simonhmorris1",
    "email": "112178216+simonhmorris1@users.noreply.github.com",
    "time": "Thu Aug 20 13:53:16 2026 +0200"
  },
  "committer": {
    "name": "GitHub",
    "email": "noreply@github.com",
    "time": "Thu Aug 20 11:53:16 2026 +0000"
  },
  "message": "Commissioning Proxy PR2: Add CP Cluster Server and Unit Tests  (#72625)\n\n* CommissioningProxy: add cluster definition and generated code\n\n* CommissioningProxy: add cluster server, delegate and unit tests\n\n* Remove PythonProxyCommissioner, CHI, add CachedResults\n\n* Adds missing CP auto-gen config\n\n* Cluster Delegate Code Review\n\n* [pre-commit.ci] auto fixes from pre-commit.com hooks\n\nfor more information, see https://pre-commit.ci\n\n* Updates after CP Gemini code review\n\n* [pre-commit.ci] auto fixes from pre-commit.com hooks\n\nfor more information, see https://pre-commit.ci\n\n* CommissioningProxy: register cluster XML in ZAP codegen config\n\nAdd the generated registration for commissioning-proxy-cluster.xml that\nwas missing from the codegen config:\n\n- zap_cluster_list.json: add COMMISSIONING_PROXY_CLUSTER (empty server\n  dir; server entry deferred to the cluster-impl PR)\n- tests.yaml: add the XML to the CI \"Validate that xml are parsable\" list\n- commissioning-proxy-cluster.xml: regenerate header with\n  attribute\u003din-progress; Git provenance now clean (no -dirty)\n\n* Rebuild autogen files\n\n* Removes CP active Python code\n\n* [commissioning-proxy] Address PR2 review feedback\n\n- Cluster owns ScanMaxTime/CacheTimeout storage + change reporting (delegate no longer forwards them).\n- Command handlers return std::optional to own their async/sync response.\n- Move endpoint id to the constructor; rename State_t -\u003e State; default mock ctor/dtor in header.\n- Remove dead CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONING_PROXY test define.\n- Rename backwards-compat suite -\u003e codegen-integration and run it via src/BUILD.gn.\n- Tests: drop 2 duplicate BgScan cases, add ScanMaxTime/CacheTimeout change-reporting tests.\n\n* [commissioning-proxy] Replace delegate with transport-driver interface + subsystems\n\nThe cluster now owns all transport-agnostic bookkeeping via three internal\nsubsystems (SessionManager, ScanCache, ScanAggregator). Physical transport\nwork is handled by CommissioningProxyTransport driver objects registered via\nRegisterTransport(); GetSupportedTransports() ORs all registered drivers.\n\nCommissioningProxyDelegate.h is removed; NotifyAttributeChanged for writable\nattributes (ScanMaxTime, CacheTimeout) is now always the cluster\u0027s responsibility.\n\nTests updated to use CommissioningProxyMockTransport (93 cases).\n\n* [pre-commit.ci] auto fixes from pre-commit.com hooks\n\nfor more information, see https://pre-commit.ci\n\n* [commissioning-proxy] Fix GN include-checker failure in CommissioningProxyScanCache\n\nCommissioningProxyScanCache.cpp included CommissioningProxyCluster.h, which\nis intentionally excluded from the commissioning-proxy-server source_set\n(compiled in the consumer\u0027s context via app_config_dependent_sources.gni).\nGN\u0027s include-checker rejected it, failing ESP32, Linux, and ARM cross-compile.\n\nIntroduce ScanCacheObserver (three pure-virtual callbacks) in\nCommissioningProxyScanCache.h. CommissioningProxyCluster inherits it;\nthe scan cache stores ScanCacheObserver\u0026 instead of CommissioningProxyCluster\u0026.\n\n* [pre-commit.ci] auto fixes from pre-commit.com hooks\n\nfor more information, see https://pre-commit.ci\n\n* [commissioning-proxy] Fix ASAN stack-use-after-scope in TestProxyMessageRequest_DuplicateRequest_Busy\n\nCommissioningProxyCluster did not override Shutdown(). The explicit\ncluster.Shutdown() call in tests only cleared mContext; subsystem teardown\nonly happened in the destructor. C++ destroys tester (which owns\nMockCommandHandler) before cluster, so the destructor\u0027s mSessions.Shutdown()\n→ delete pm → Handle::Release() reached a dead CommandHandler.\n\nOverride Shutdown() to clean up subsystems and transports. The destructor\ndelegates to it as an idempotent safety net (mTransportCount\u003d0 guards the loop).\n\n* [commissioning-proxy] Fix clang-tidy warnings in TestCommissioningProxyCluster\n\nbugprone-argument-comment: argument comment must match the parameter\nname exactly — /*maxSessions\u003d*/ → /*aMaxSessions\u003d*/.\n\nbugprone-unchecked-optional-access: clang-tidy\u0027s dataflow analysis does\nnot see through the ASSERT_TRUE macro, so response-\u003e after\nASSERT_TRUE(response.has_value()) is flagged. Replace with\nresponse.value().field which throws bad_optional_access instead of UB\nand is not flagged by the checker.\n\n* [commissioning-proxy] Fix bugprone-unchecked-optional-access in tests\n\nclang-tidy\u0027s dataflow analysis does not see through ASSERT_TRUE macros,\nso response.value() after ASSERT_TRUE(response.has_value()) is still\nflagged. Wrap each access in an explicit if (response.has_value()) block,\nwhich creates visible control flow the checker can follow.\n\n* [commissioning-proxy] Add braces to all bare if/for/while bodies\n\nGCC 14.2 on Tizen raises -Werror\u003ddangling-else when a brace-free\nif body is a GTest EXPECT_* macro that expands to if/else internally.\nAdd explicit braces to all single-statement if/else-if/for/while\nbodies across commissioning-proxy-server/ (46 sites in 7 files).\n\nAlso fix README: remove unverified spec section number, update\nargument-comment names to match Config constructor parameters.\n\n* [pre-commit.ci] auto fixes from pre-commit.com hooks\n\nfor more information, see https://pre-commit.ci\n\n* [commissioning-proxy] Add shared background-scan fabric registry\n\nExtract the transport-agnostic ProxyBackGroundScan bookkeeping (per-fabric\ntransport/band records, lifetime timers, Start/Stop overlap arithmetic,\npaused/deferred state) into CommissioningProxyBgScanRegistry so the BLE and\nPAF transports stop duplicating it; transports supply only hardware\nstart/stop/clear hooks via HardwareControl. Adds 15 unit tests.\n\n* [pre-commit.ci] auto fixes from pre-commit.com hooks\n\nfor more information, see https://pre-commit.ci\n\n* [commissioning-proxy] Document background-scan registry, fix build layout\n\nAdd CommissioningProxyBgScanRegistry to the README\u0027s subsystem and\narchitecture tables, fix the BgScanStart/BgScanStop signatures in the\ndriver example, and document its API and HardwareControl contract.\n\nThe cluster reads no transport build flags, so move\nCommissioningProxyCluster.{h,cpp} into the cluster source_set and out of\napp_config_dependent_sources.{gni,cmake}, matching chime-server, and\ndrop the stale comment naming the deleted CommissioningProxyDelegate.h.\n\n* [pre-commit.ci] auto fixes from pre-commit.com hooks\n\nfor more information, see https://pre-commit.ci\n\n* Use WritAttribute and remove redundant comment\n\n- WriteAttribute: use DefaultServerCluster::SetAttributeValue for\n  ScanMaxTime and CacheTimeout instead of hand-rolling the\n  compare/assign/NotifyAttributeChanged pattern. No behaviour change.\n- tests/BUILD.gn: drop the historical backwards-compatibility note from\n  the tests-codegen-integration comment\n\n* CodeRabbitAI first checnges fix\n\nAdd the smaller fixes identified.\n\n* Inject a TimerDelegate so cluster timer paths are testable\n\nThe session manager and scan aggregator called SystemLayer directly, so\ntests could not drive expiry or exercise a StartTimer failure.\n\nBoth now take a chip::TimerDelegate; the aggregator and each pending\nmessage are TimerContexts, and CodegenIntegration supplies the shared\nDefaultTimerDelegate, so the cluster ctor gains a third parameter.\nAdds CommissioningProxyMockTimer (multi-context with failure injection)\nand 3 tests for the rollback paths, each confirmed to fail without them.\n\n* Add new tests to use TimerDelegate\n\nAdds 7 timer unit tests tests for bgscan lifetime expiry and\ntimer-arm failure, independent per-fabric lifetimes, cache TTL expiry,\nrediscovery resetting the TTL, sweep re-arming, and the watchdog ending\na stalled aggregation. Each confirmed to fail against broken code.\n\n* Make a rejected background-scan start leave nothing behind\n\nBgScanRegistry::Start mutated the fabric table before the hardware start\nand lifetime timer could fail, so a failed refresh destroyed a working\nregistration and cancelled its timer. Both fallible steps now run first\nand the record is only replaced on success.\n\nProxyBackGroundScanStartRequest returned the first error while leaving\nalready-started transports scanning; those are now stopped on failure.\n\n* Make background-scan records per fabric\n\nSpec says \"keep per fabric records\", recording the sender\u0027s NodeID only to\nauthorise the matching Stop. Keying on the pair grew the table with fabrics\nx nodes. The NodeID now sits in the record, Stop rejects a non-owner, and a\nstart from another node on the same fabric takes ownership.\n\n* Tidy unsued #include and small tweaks\n\n* Trim comments.\n\n* Scan the union of each fabric\u0027s background-scan requests\n\nEach node keeps its own request (a Stop is identified by NodeID and FabricID);\nthe fabric scans their union under one timer at the latest deadline, recomputed\non Stop, capped at 4 requests. Clearing is band-scoped: ClearCachedResults(bands).\n\n* Give the CommissioningProxy cluster bounded, fabric-aware state\n\nAdded removed fabric\u0027s sessions, connect and background scans. MaxSessions and\nMaxCachedResults now come from CHIPConfig.h, sizing the heap-free storage that\nreplaces std::map and raw new.\n\n* Clear fabric request slot on re-arm failure\n\nAdd new tests and update REAME.md\n\n* Fix CommissioningProxy lifecycle and validation gaps from review\n\nRelease a background-scan fabric whose lifetime timer cannot be re-armed\nso a failed refresh cannot leave its requests scanning unbounded. Reject\nreserved Transport bits in ProxyConnectRequest with InvalidCommand, as\nthe scan commands already does. Cancel the scan cache\u0027s sweep timer\nfrom its destructor. Leave the mock transport\u0027s unanswered message\npending so the response timer is what resolves it.\n\n* Consolidate CommissioningProxy unit tests\n\nMerge or drop tests that re-asserted a covered path, table the read-only and\nmin-1 attribute checks, and give the registry tests a fixture. Add a\ncross-command reserved-Transport-bit test; note why MaxSessions stays above 1.\n\n* CP: Make MAX_SESSIONS default\u003d1\n\n* Add compile-time bounds on the three CP config macros\n\n* Address PR review feedback on the Commissioning Proxy cluster server\n\nDrop the unused CodegenIntegration Instance wrapper, its test target and the\nmock_ember carve-out it needed. Type the transport interface\u0027s seconds params\nas System::Clock::Seconds16, rename the session lookups, tidy the registry.\n\n* [pre-commit.ci] auto fixes from pre-commit.com hooks\n\nfor more information, see https://pre-commit.ci\n\n---------\n\nCo-authored-by: pre-commit-ci[bot] \u003c66853113+pre-commit-ci[bot]@users.noreply.github.com\u003e",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "87c4064b251ea09bb400f7dcb3415a4798702367",
      "old_mode": 33188,
      "old_path": "src/BUILD.gn",
      "new_id": "7bdad0d3f471471dd47dd03a674053965df8c9b1",
      "new_mode": 33188,
      "new_path": "src/BUILD.gn"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "63cc9e9077cca68d1db6b3ed90bd82aa5928998d",
      "new_mode": 33188,
      "new_path": "src/app/clusters/commissioning-proxy-server/BUILD.gn"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "a76b6d15db0bb018134904e7ee416f08dd71d999",
      "new_mode": 33188,
      "new_path": "src/app/clusters/commissioning-proxy-server/CodegenIntegration.cpp"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "d5ec379449be92b242f252e043f436adda6917e0",
      "new_mode": 33188,
      "new_path": "src/app/clusters/commissioning-proxy-server/CodegenIntegration.h"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "e5d0ba99b4cd1fb4702d351ddf83436add72f377",
      "new_mode": 33188,
      "new_path": "src/app/clusters/commissioning-proxy-server/CommissioningProxyBgScanRegistry.cpp"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "d2abc902981ef30a3f994dfa32585e919730cc5c",
      "new_mode": 33188,
      "new_path": "src/app/clusters/commissioning-proxy-server/CommissioningProxyBgScanRegistry.h"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "6854bdf5c482f1ce6a6a34435dd0c1237766df0c",
      "new_mode": 33188,
      "new_path": "src/app/clusters/commissioning-proxy-server/CommissioningProxyCluster.cpp"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "59c5c2a88d4a640db2e052fe31c275dd7316694e",
      "new_mode": 33188,
      "new_path": "src/app/clusters/commissioning-proxy-server/CommissioningProxyCluster.h"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "0fe60eb1b7bad90f4b472062431b6995a5267c0f",
      "new_mode": 33188,
      "new_path": "src/app/clusters/commissioning-proxy-server/CommissioningProxyScanAggregator.cpp"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "44a21834e9e5698ba15d1e80d68779f4024b6f75",
      "new_mode": 33188,
      "new_path": "src/app/clusters/commissioning-proxy-server/CommissioningProxyScanAggregator.h"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "fbdf5075f1a492257651ac59d48037130bdd47f5",
      "new_mode": 33188,
      "new_path": "src/app/clusters/commissioning-proxy-server/CommissioningProxyScanCache.cpp"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "1ceef98a7d30fc379dc0a588f073990a42169ef9",
      "new_mode": 33188,
      "new_path": "src/app/clusters/commissioning-proxy-server/CommissioningProxyScanCache.h"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "7a9d0388e6acb706dc012cc87f01c1c94038d5ab",
      "new_mode": 33188,
      "new_path": "src/app/clusters/commissioning-proxy-server/CommissioningProxySessionManager.cpp"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "05a1f58101615bf23ff8fd252b15ff8f783567f9",
      "new_mode": 33188,
      "new_path": "src/app/clusters/commissioning-proxy-server/CommissioningProxySessionManager.h"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "608b5443856301b7179dd5f7593e46cfcae3136d",
      "new_mode": 33188,
      "new_path": "src/app/clusters/commissioning-proxy-server/CommissioningProxyTestEventTriggerHandler.h"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "0ebce2964c3ff64ea2f6a8d4e9d9fae7bee8560f",
      "new_mode": 33188,
      "new_path": "src/app/clusters/commissioning-proxy-server/CommissioningProxyTransport.h"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "0c55da3965d89cef2830c13665e59578af14f337",
      "new_mode": 33188,
      "new_path": "src/app/clusters/commissioning-proxy-server/README.md"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "830dae4ebb17d7799ba99b98980f68506aa66a58",
      "new_mode": 33188,
      "new_path": "src/app/clusters/commissioning-proxy-server/app_config_dependent_sources.cmake"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "9e78d8b91ed82243e33f13c67dd25b29e6ffc3d0",
      "new_mode": 33188,
      "new_path": "src/app/clusters/commissioning-proxy-server/app_config_dependent_sources.gni"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "70932d3a8e1cc1582500a358194d737eab4f438f",
      "new_mode": 33188,
      "new_path": "src/app/clusters/commissioning-proxy-server/tests/BUILD.gn"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "b5fe5d0936472ff5fc90911b3606c4ae07781945",
      "new_mode": 33188,
      "new_path": "src/app/clusters/commissioning-proxy-server/tests/CommissioningProxyMockTimer.h"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "c58732ab4007b9468d858b07b2ca9a12c25916a8",
      "new_mode": 33188,
      "new_path": "src/app/clusters/commissioning-proxy-server/tests/CommissioningProxyMockTransport.cpp"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "7f56d3b415f37aa4f12ac161aa46bffd538ae822",
      "new_mode": 33188,
      "new_path": "src/app/clusters/commissioning-proxy-server/tests/CommissioningProxyMockTransport.h"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "3436a3ce089c7ccf77701d4132ea30bb5f164b65",
      "new_mode": 33188,
      "new_path": "src/app/clusters/commissioning-proxy-server/tests/TestCommissioningProxyBgScanRegistry.cpp"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "608cfd8b4b00a8cd5477ed9f672d2fcb40fdd9ac",
      "new_mode": 33188,
      "new_path": "src/app/clusters/commissioning-proxy-server/tests/TestCommissioningProxyCluster.cpp"
    },
    {
      "type": "modify",
      "old_id": "cd2101fb8f087f97d05ae60678534a32563e94c4",
      "old_mode": 33188,
      "old_path": "src/app/server-cluster/testing/ClusterTester.h",
      "new_id": "5b8b0d1f7ba76080b9d18722f04d9afc794f159a",
      "new_mode": 33188,
      "new_path": "src/app/server-cluster/testing/ClusterTester.h"
    },
    {
      "type": "modify",
      "old_id": "30671f363b9af9084783de72ea446e45a81cac1a",
      "old_mode": 33188,
      "old_path": "src/app/zap_cluster_list.json",
      "new_id": "fb39bbd7cc569bd0a41db828dc88dd508aaa8e9d",
      "new_mode": 33188,
      "new_path": "src/app/zap_cluster_list.json"
    },
    {
      "type": "modify",
      "old_id": "4c0c071df38d87036b9ff7c930c1c9520ff9f665",
      "old_mode": 33188,
      "old_path": "src/lib/core/CHIPConfig.h",
      "new_id": "3af0e604a21c3b9767de449e73714a9963b80a88",
      "new_mode": 33188,
      "new_path": "src/lib/core/CHIPConfig.h"
    }
  ]
}
