)]}'
{"/COMMIT_MSG":[{"robot_id":"droid-review","robot_run_id":"droid-review-20260525-001","author":{"_account_id":1003869,"name":"Couchbase Robot","email":"build-team@couchbase.com","username":"cb-robot","avatars":[{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"e3e5d98ac439085c39db0c7c9469b6b0b1d6f487","patch_set":7,"id":"c9245320_c0524d7f","updated":"2026-05-25 10:46:44.000000000","message":"The commit message clearly describes what changed, why (magma vbucket sizing, non-UTF8 key handling, timeout log noise), and the expected impact, so no revision is needed.","commit_id":"289440866f2f4cfae9a3f52ccea3525bd0357bd1"}],"lib/dcp_bin_client.py":[{"robot_id":"droid-review","robot_run_id":"droid-review-20260525-001","author":{"_account_id":1003869,"name":"Couchbase Robot","email":"build-team@couchbase.com","username":"cb-robot","avatars":[{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"9e530b9def4f691299c8641e22ce74df82274267","patch_set":6,"id":"c72a2a33_3ca3414b","line":16,"updated":"2026-05-25 10:19:59.000000000","message":"Missing unit coverage for `DcpClient` core behaviors (connection lifecycle + error handling). This makes regressions in the client hard to detect. Add a focused unit test that mocks `_recvMsg` and verifies the `\u0027died\u0027` path returns status 0xff.\n\n```python\nimport unittest\nfrom unittest import mock\n\nclass TestDcpClient(unittest.TestCase):\n    def test_recv_op_died_returns_error_status(self):\n        client \u003d DcpClient(\"localhost\", 11210, timeout\u003d1, do_auth\u003dFalse)\n        op \u003d Operation(CMD_NOOP)\n        with mock.patch.object(client, \"_recvMsg\", side_effect\u003dRuntimeError(\"died\")):\n            resp \u003d client.recv_op(op)\n        self.assertEqual(resp[\"status\"], 0xff)\n```\n","commit_id":"4e91def922816266f4018c4691df302a01fde924"},{"robot_id":"droid-review","robot_run_id":"droid-review-20260525-001","author":{"_account_id":1003869,"name":"Couchbase Robot","email":"build-team@couchbase.com","username":"cb-robot","avatars":[{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"9e530b9def4f691299c8641e22ce74df82274267","patch_set":6,"id":"fbdace22_8fcff9de","line":255,"updated":"2026-05-25 10:19:59.000000000","message":"Timeout handling in `recv_op` is now a soft-return path; add a test to ensure timeouts return `None` without poisoning the stream state. This locks down the intended behavior for slow streams.\n\n```python\nimport unittest\nfrom unittest import mock\n\nclass TestRecvOpTimeout(unittest.TestCase):\n    def test_recv_op_timeout_returns_none(self):\n        client \u003d DcpClient(\"localhost\", 11210, timeout\u003d1, do_auth\u003dFalse)\n        op \u003d Operation(CMD_NOOP)\n        with mock.patch.object(client, \"_recvMsg\", side_effect\u003dTimeoutError(\"timed out\")):\n            self.assertIsNone(client.recv_op(op))\n```\n","commit_id":"4e91def922816266f4018c4691df302a01fde924"},{"robot_id":"droid-review","robot_run_id":"droid-review-20260525-001","author":{"_account_id":1003869,"name":"Couchbase Robot","email":"build-team@couchbase.com","username":"cb-robot","avatars":[{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"e3e5d98ac439085c39db0c7c9469b6b0b1d6f487","patch_set":7,"id":"8799e8b4_34a90358","line":16,"updated":"2026-05-25 10:46:44.000000000","message":"Missing unit coverage for DcpClient core error-handling (e.g., the \"died\" path) makes regressions hard to detect. Add a focused test that stubs `_recvMsg` and asserts status `0xff` is returned.\n\n```python\nimport unittest\nfrom unittest import mock\n\nfrom lib.dcp_bin_client import DcpClient\n\nclass TestDcpClientDied(unittest.TestCase):\n    @mock.patch(\"lib.dcp_bin_client.MemcachedClient.__init__\", return_value\u003dNone)\n    def test_recv_op_died_returns_status_ff(self, _init):\n        client \u003d DcpClient(\"127.0.0.1\", 11210, do_auth\u003dFalse)\n        op \u003d mock.Mock(opcode\u003d0x00, opaque\u003d1)\n        with mock.patch.object(client, \"_recvMsg\", side_effect\u003dException(\"connection died\")):\n            response \u003d client.recv_op(op)\n        self.assertEqual(response[\"status\"], 0xff)\n```","commit_id":"289440866f2f4cfae9a3f52ccea3525bd0357bd1"},{"robot_id":"droid-review","robot_run_id":"droid-review-20260525-001","author":{"_account_id":1003869,"name":"Couchbase Robot","email":"build-team@couchbase.com","username":"cb-robot","avatars":[{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"e3e5d98ac439085c39db0c7c9469b6b0b1d6f487","patch_set":7,"id":"df4ffe1a_0254889a","line":125,"updated":"2026-05-25 10:46:44.000000000","message":"The stream_req generator path is still untested; regressions could miss CMD_STREAM_END and leave streams open. Add a unit test that exercises the queue-empty path and confirms the generator stops on stream end.\n\n```python\nimport unittest\nfrom unittest import mock\n\nfrom lib.dcp_bin_client import DcpClient, CMD_STREAM_END\n\nclass TestStreamReqGenerator(unittest.TestCase):\n    @mock.patch(\"lib.dcp_bin_client.MemcachedClient.__init__\", return_value\u003dNone)\n    def test_stream_req_stops_on_stream_end(self, _init):\n        client \u003d DcpClient(\"127.0.0.1\", 11210, do_auth\u003dFalse)\n        op_response \u003d {\"opcode\": 0x00, \"status\": 0}\n        stream_end \u003d {\"opcode\": CMD_STREAM_END}\n        with mock.patch.object(client, \"_handle_op\", return_value\u003dop_response):\n            with mock.patch.object(client, \"recv_op\", side_effect\u003d[stream_end]):\n                stream \u003d client.stream_req(0, 0, 0, 0, 0)\n                stream.next_response()\n                self.assertFalse(stream.has_response())\n```","commit_id":"289440866f2f4cfae9a3f52ccea3525bd0357bd1"},{"robot_id":"droid-review","robot_run_id":"droid-review-20260525-001","author":{"_account_id":1003869,"name":"Couchbase Robot","email":"build-team@couchbase.com","username":"cb-robot","avatars":[{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"e3e5d98ac439085c39db0c7c9469b6b0b1d6f487","patch_set":7,"id":"7a1ae194_27d252af","line":154,"updated":"2026-05-25 10:46:44.000000000","message":"With timeouts now returning None without setting `_stream_timeout`, the generator can spin in tight loops when callers poll rapidly, wasting CPU on slow streams. Consider adding a small backoff when `response is None`.\n\n```python\ndef __generator(response):\n    yield response\n    last_by_seqno \u003d 0\n\n    while True:\n        if not op.queue.empty():\n            response \u003d op.queue.get()\n        else:\n            response \u003d self.recv_op(op)\n        if response is None:\n            time.sleep(0.1)\n            continue\n        yield response\n        if response[\u0027opcode\u0027] \u003d\u003d CMD_STREAM_END:\n            break\n```","commit_id":"289440866f2f4cfae9a3f52ccea3525bd0357bd1"},{"robot_id":"droid-review","robot_run_id":"droid-review-20260525-001","author":{"_account_id":1003869,"name":"Couchbase Robot","email":"build-team@couchbase.com","username":"cb-robot","avatars":[{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"e3e5d98ac439085c39db0c7c9469b6b0b1d6f487","patch_set":7,"id":"c41bf233_9f6fc92d","line":206,"updated":"2026-05-25 10:46:44.000000000","message":"Timeout handling in recv_op is now a soft-return path; add a unit test to ensure timeouts return None without poisoning the stream state.\n\n```python\nimport unittest\nfrom unittest import mock\n\nfrom lib.dcp_bin_client import DcpClient\n\nclass TestRecvOpTimeout(unittest.TestCase):\n    @mock.patch(\"lib.dcp_bin_client.MemcachedClient.__init__\", return_value\u003dNone)\n    def test_recv_op_timeout_returns_none(self, _init):\n        client \u003d DcpClient(\"127.0.0.1\", 11210, do_auth\u003dFalse)\n        op \u003d mock.Mock(opcode\u003d0x00, opaque\u003d1)\n        with mock.patch.object(client, \"_recvMsg\", side_effect\u003dException(\"timed out\")):\n            response \u003d client.recv_op(op)\n        self.assertIsNone(response)\n        self.assertFalse(client._stream_timeout)\n```","commit_id":"289440866f2f4cfae9a3f52ccea3525bd0357bd1"}],"pytests/dcp_new/dcp_base.py":[{"robot_id":"droid-review","robot_run_id":"droid-review-20260525-0001","author":{"_account_id":1003869,"name":"Couchbase Robot","email":"build-team@couchbase.com","username":"cb-robot","avatars":[{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"1798b2f33d4bd6e3185fb7815758c50dffc8bba7","patch_set":4,"id":"3915582e_4d41b2a5","line":62,"updated":"2026-05-25 09:49:07.000000000","message":"Class-level test gap: `DCPBase` has no direct coverage for its stream setup and event-handling helpers, so behavioral changes here can regress silently. Add integration/unit coverage for the base class (e.g., via a small derived test class that drives the helpers).","commit_id":"755fe0267ca8aca93a5a97aa650736e7b0ee109b"},{"robot_id":"droid-review","robot_run_id":"droid-review-20260525-0001","author":{"_account_id":1003869,"name":"Couchbase Robot","email":"build-team@couchbase.com","username":"cb-robot","avatars":[{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"1798b2f33d4bd6e3185fb7815758c50dffc8bba7","patch_set":4,"id":"7f5b121c_a7186c5e","line":62,"updated":"2026-05-25 09:49:07.000000000","message":"Missing test coverage for `initialise_cluster_connections`: there is no test asserting `self.vbuckets` length matches the cluster `vBucketMap` and that `LogData` is initialized for each vbucket. Add a test that exercises this path to prevent regressions.","commit_id":"755fe0267ca8aca93a5a97aa650736e7b0ee109b"},{"robot_id":"droid-review","robot_run_id":"droid-review-20260525-0001","author":{"_account_id":1003869,"name":"Couchbase Robot","email":"build-team@couchbase.com","username":"cb-robot","avatars":[{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"1798b2f33d4bd6e3185fb7815758c50dffc8bba7","patch_set":4,"id":"07603287_0fcde0ae","line":94,"updated":"2026-05-25 09:49:07.000000000","message":"Missing test coverage for `initiate_connection`, especially around SASL auth failure and feature negotiation; currently failures only log and the connection continues. Add a test to lock down the intended behavior on auth failure.","commit_id":"755fe0267ca8aca93a5a97aa650736e7b0ee109b"},{"robot_id":"droid-review","robot_run_id":"droid-review-20260525-0001","author":{"_account_id":1003869,"name":"Couchbase Robot","email":"build-team@couchbase.com","username":"cb-robot","avatars":[{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"1798b2f33d4bd6e3185fb7815758c50dffc8bba7","patch_set":4,"id":"57afd5be_858858ce","line":188,"updated":"2026-05-25 09:49:07.000000000","message":"Decoding arbitrary DCP keys with strict UTF-8 can raise `UnicodeDecodeError` for binary keys, aborting system-event handling. Use a tolerant decode (or keep bytes and decode only for logging) and add a test covering non-UTF8 keys. Example fix:\n```python\nif isinstance(response.get(\"key\"), bytes):\n    response[\"key\"] \u003d response[\"key\"].decode(\"utf-8\", errors\u003d\"surrogateescape\")\n```","commit_id":"755fe0267ca8aca93a5a97aa650736e7b0ee109b"},{"robot_id":"droid-review","robot_run_id":"droid-review-20260525-001","author":{"_account_id":1003869,"name":"Couchbase Robot","email":"build-team@couchbase.com","username":"cb-robot","avatars":[{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"9e530b9def4f691299c8641e22ce74df82274267","patch_set":6,"id":"2748ee6e_7066b9de","line":19,"updated":"2026-05-25 10:19:59.000000000","message":"DCPBase helpers still lack direct coverage for stream setup and event-handling helpers, so behavior changes can regress silently. Add a small derived test class that drives these helper paths.\n\n```python\nclass TestDcpBaseHelpers(DCPBase):\n    def test_handle_marker_round_trips(self):\n        response \u003d {\n            \"vbucket\": 0,\n            \"streamId\": 0,\n            \"snap_start_seqno\": 1,\n            \"snap_end_seqno\": 2,\n            \"flag\": \"memory\",\n        }\n        start, end \u003d self.handleMarker(response)\n        self.assertEqual((start, end), (1, 2))\n```\n","commit_id":"4e91def922816266f4018c4691df302a01fde924"},{"robot_id":"droid-review","robot_run_id":"droid-review-20260525-001","author":{"_account_id":1003869,"name":"Couchbase Robot","email":"build-team@couchbase.com","username":"cb-robot","avatars":[{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"9e530b9def4f691299c8641e22ce74df82274267","patch_set":6,"id":"f4fe04cc_288ae787","line":62,"updated":"2026-05-25 10:19:59.000000000","message":"Missing test coverage for `initialise_cluster_connections` verifying `self.vbuckets` matches the `vBucketMap` length and that `LogData` is initialized with that range. Add a test that stubs `DcpClient.get_config` and asserts the derived range.\n\n```python\nimport json\nfrom unittest import mock\n\ndef test_initialise_cluster_connections_sets_vbucket_range(self):\n    config \u003d {\n        \"vBucketServerMap\": {\"vBucketMap\": [[0], [1]], \"serverList\": []},\n        \"nodesExt\": [],\n    }\n    with mock.patch.object(DcpClient, \"get_config\", return_value\u003d(None, None, json.dumps(config))):\n        with mock.patch(\"pytests.dcp_new.dcp_base.LogData\") as log_data_cls:\n            dcp_base \u003d DCPBase()\n            dcp_base.log_path \u003d None\n            dcp_base.keep_logs \u003d False\n            dcp_base.initialise_cluster_connections()\n            self.assertEqual(list(dcp_base.vbuckets), [0, 1])\n            log_data_cls.assert_called_once()\n```\n","commit_id":"4e91def922816266f4018c4691df302a01fde924"},{"robot_id":"droid-review","robot_run_id":"droid-review-20260525-001","author":{"_account_id":1003869,"name":"Couchbase Robot","email":"build-team@couchbase.com","username":"cb-robot","avatars":[{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"9e530b9def4f691299c8641e22ce74df82274267","patch_set":6,"id":"6c5aecfa_860b5002","line":88,"updated":"2026-05-25 10:19:59.000000000","message":"Missing test coverage for `initiate_connection` around SASL auth failure and feature negotiation; today a `MemcachedError` is logged and execution continues. Add a test to lock down the intended behavior (fail fast or explicit status) so this path can\u0027t regress.\n\n```python\nfrom unittest import mock\n\ndef test_initiate_connection_auth_failure(self):\n    dcp_base \u003d DCPBase()\n    with mock.patch.object(DcpClient, \"sasl_auth_plain\", side_effect\u003dMemcachedError(\"auth failed\")):\n        with self.assertRaises(MemcachedError):\n            dcp_base.initiate_connection()\n```\n","commit_id":"4e91def922816266f4018c4691df302a01fde924"},{"robot_id":"droid-review","robot_run_id":"droid-review-20260525-001","author":{"_account_id":1003869,"name":"Couchbase Robot","email":"build-team@couchbase.com","username":"cb-robot","avatars":[{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"9e530b9def4f691299c8641e22ce74df82274267","patch_set":6,"id":"4d832e23_1b9ffde4","line":188,"updated":"2026-05-25 10:19:59.000000000","message":"Add coverage for non-UTF8 system-event keys to ensure the new surrogateescape decode path doesn\u0027t raise and still updates the manifest correctly.\n\n```python\nimport struct\n\ndef test_handle_system_event_non_utf8_key(self):\n    response \u003d {\n        \"event\": EVENT_CREATE_COLLECTION,\n        \"version\": 0,\n        \"value\": struct.pack(\"\u003eQII\", 1, 2, 3),\n        \"key\": b\"\\\\xff\",\n        \"vbucket\": 0,\n        \"streamId\": 0,\n        \"by_seqno\": 1,\n    }\n    manifest \u003d {\"uid\": \"0\", \"scopes\": [{\"uid\": \"2\", \"collections\": []}]}\n    updated \u003d self.handleSystemEvent(response, manifest)\n    self.assertEqual(updated[\"uid\"], \"1\")\n```\n","commit_id":"4e91def922816266f4018c4691df302a01fde924"},{"robot_id":"droid-review","robot_run_id":"droid-review-20260525-001","author":{"_account_id":1003869,"name":"Couchbase Robot","email":"build-team@couchbase.com","username":"cb-robot","avatars":[{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"e3e5d98ac439085c39db0c7c9469b6b0b1d6f487","patch_set":7,"id":"3da0c8df_de586a45","line":19,"updated":"2026-05-25 10:46:44.000000000","message":"DCPBase helper paths are still untested, so regressions in marker/event helpers can slip through. Add a small unit test that invokes the helpers with stubbed state.\n\n```python\nimport unittest\nfrom unittest import mock\n\nfrom pytests.dcp_new.dcp_base import DCPBase\n\nclass TestDcpBaseHelpers(unittest.TestCase):\n    def test_handle_marker_round_trips(self):\n        base \u003d DCPBase.__new__(DCPBase)\n        base.log \u003d mock.Mock()\n        response \u003d {\n            \"vbucket\": 0,\n            \"streamId\": 1,\n            \"snap_start_seqno\": 10,\n            \"snap_end_seqno\": 20,\n            \"flag\": \"memory\"\n        }\n        start, end \u003d DCPBase.handleMarker(base, response)\n        self.assertEqual((start, end), (10, 20))\n```","commit_id":"289440866f2f4cfae9a3f52ccea3525bd0357bd1"},{"robot_id":"droid-review","robot_run_id":"droid-review-20260525-001","author":{"_account_id":1003869,"name":"Couchbase Robot","email":"build-team@couchbase.com","username":"cb-robot","avatars":[{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"e3e5d98ac439085c39db0c7c9469b6b0b1d6f487","patch_set":7,"id":"c1674083_9e15ebf6","line":57,"updated":"2026-05-25 10:46:44.000000000","message":"initialise_cluster_connections still lacks direct coverage that the vbuckets range matches the vb_map length and that LogData is initialized with that range. Add a test that stubs get_config and asserts the derived vbuckets.\n\n```python\nimport json\nimport unittest\nfrom unittest import mock\n\nfrom pytests.dcp_new.dcp_base import DCPBase\n\nclass TestInitialiseClusterConnections(unittest.TestCase):\n    def test_vbuckets_match_vb_map_length(self):\n        base \u003d DCPBase.__new__(DCPBase)\n        base.initiate_connection \u003d mock.Mock(return_value\u003dmock.Mock())\n        base.check_valid_host \u003d mock.Mock(side_effect\u003dlambda host, _: host)\n        base.log_path \u003d None\n        base.keep_logs \u003d False\n        config \u003d {\n            \"vBucketServerMap\": {\n                \"vBucketMap\": [[0], [1]],\n                \"serverList\": [\"n1:11210\", \"n2:11210\"]\n            },\n            \"nodesExt\": [\n                {\"services\": {\"kv\": 11210}, \"thisNode\": True},\n                {\"services\": {\"kv\": 11210}}\n            ]\n        }\n        with mock.patch(\n            \"pytests.dcp_new.dcp_base.DcpClient.get_config\",\n            return_value\u003d(None, None, json.dumps(config)),\n        ):\n            base.initialise_cluster_connections()\n        self.assertEqual(list(base.vbuckets), [0, 1])\n```","commit_id":"289440866f2f4cfae9a3f52ccea3525bd0357bd1"},{"robot_id":"droid-review","robot_run_id":"droid-review-20260525-001","author":{"_account_id":1003869,"name":"Couchbase Robot","email":"build-team@couchbase.com","username":"cb-robot","avatars":[{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"e3e5d98ac439085c39db0c7c9469b6b0b1d6f487","patch_set":7,"id":"b5dd347a_97e51678","line":88,"updated":"2026-05-25 10:46:44.000000000","message":"initiate_connection has no test coverage for SASL auth failure and feature negotiation, so behavior can regress silently. Add a test that triggers MemcachedError and asserts the intended handling.\n\n```python\nimport unittest\nfrom unittest import mock\n\nfrom mc_bin_client import MemcachedError\nfrom pytests.dcp_new.dcp_base import DCPBase\n\nclass TestInitiateConnection(unittest.TestCase):\n    def test_sasl_auth_failure_is_handled(self):\n        base \u003d DCPBase.__new__(DCPBase)\n        base.cluster \u003d mock.Mock(master\u003dmock.Mock(ip\u003d\"127.0.0.1\",\n                                                  rest_username\u003d\"u\",\n                                                  rest_password\u003d\"p\"))\n        base.bucket \u003d mock.Mock(name\u003d\"default\")\n        base.log \u003d mock.Mock()\n        base.timeout \u003d 1\n        base.xattrs \u003d False\n        base.collections \u003d False\n        base.delete_times \u003d False\n        base.compression \u003d 0\n        base.enable_expiry \u003d False\n        base.enable_stream_id \u003d False\n        base.check_for_features \u003d mock.Mock()\n        client \u003d mock.Mock()\n        client.sasl_auth_plain.side_effect \u003d MemcachedError()\n        with mock.patch(\"pytests.dcp_new.dcp_base.DcpClient\", return_value\u003dclient):\n            base.initiate_connection()\n        base.check_for_features.assert_called_once_with(client)\n        base.log.info.assert_any_call(\"DCP connection failure\")\n```","commit_id":"289440866f2f4cfae9a3f52ccea3525bd0357bd1"},{"robot_id":"droid-review","robot_run_id":"droid-review-20260525-001","author":{"_account_id":1003869,"name":"Couchbase Robot","email":"build-team@couchbase.com","username":"cb-robot","avatars":[{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/d465bd97bd9f40f1453c5b112ef4a021.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"e3e5d98ac439085c39db0c7c9469b6b0b1d6f487","patch_set":7,"id":"1393250e_a767f37a","line":185,"updated":"2026-05-25 10:46:44.000000000","message":"Add coverage for non-UTF8 system-event keys so the surrogateescape decode path is exercised and manifest updates are validated.\n\n```python\nimport struct\nimport unittest\nfrom unittest import mock\n\nfrom pytests.dcp_new.dcp_base import DCPBase, EVENT_CREATE_COLLECTION\n\nclass TestHandleSystemEvent(unittest.TestCase):\n    def test_non_utf8_key_surrogateescape(self):\n        base \u003d DCPBase.__new__(DCPBase)\n        base.output_string \u003d []\n        base.log \u003d mock.Mock()\n        key \u003d b\"\\xff\"\n        value \u003d struct.pack(\"\u003eQII\", 1, 2, 3)\n        response \u003d {\n            \"event\": EVENT_CREATE_COLLECTION,\n            \"version\": 0,\n            \"value\": value,\n            \"key\": key,\n            \"vbucket\": 0,\n            \"streamId\": 1,\n            \"by_seqno\": 1\n        }\n        manifest \u003d {\n            \"uid\": \"0\",\n            \"scopes\": [{\"uid\": format(2, \"x\"), \"collections\": []}]\n        }\n        updated \u003d DCPBase.handleSystemEvent(base, response, manifest)\n        expected \u003d key.decode(\"utf-8\", errors\u003d\"surrogateescape\")\n        self.assertEqual(updated[\"scopes\"][0][\"collections\"][0][\"name\"], expected)\n```","commit_id":"289440866f2f4cfae9a3f52ccea3525bd0357bd1"}]}
