ccx-native 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +241 -2
  3. package/bin/ccx +56 -0
  4. package/ccx/__init__.py +163 -0
  5. package/ccx/__main__.py +28 -0
  6. package/ccx/claude/__init__.py +0 -0
  7. package/ccx/claude/analytics.py +466 -0
  8. package/ccx/claude/attach.py +762 -0
  9. package/ccx/claude/context.py +465 -0
  10. package/ccx/claude/delivery.py +806 -0
  11. package/ccx/claude/external.py +253 -0
  12. package/ccx/claude/host/__init__.py +0 -0
  13. package/ccx/claude/host/events.py +297 -0
  14. package/ccx/claude/host/hooks.py +438 -0
  15. package/ccx/claude/host/pty.py +250 -0
  16. package/ccx/claude/host/session.py +5184 -0
  17. package/ccx/claude/host/subagents.py +169 -0
  18. package/ccx/claude/host/successor.py +267 -0
  19. package/ccx/claude/managed_turns.py +240 -0
  20. package/ccx/claude/oauth.py +176 -0
  21. package/ccx/claude/settings.py +339 -0
  22. package/ccx/claude/spawn.py +557 -0
  23. package/ccx/claude/tasks.py +72 -0
  24. package/ccx/claude/telemetry.py +282 -0
  25. package/ccx/claude/transcript.py +2281 -0
  26. package/ccx/claude/usage.py +837 -0
  27. package/ccx/claude/usage_control.py +152 -0
  28. package/ccx/cli/__init__.py +0 -0
  29. package/ccx/cli/codex.py +1009 -0
  30. package/ccx/cli/commands/__init__.py +0 -0
  31. package/ccx/cli/commands/_common.py +407 -0
  32. package/ccx/cli/commands/control.py +161 -0
  33. package/ccx/cli/commands/create.py +669 -0
  34. package/ccx/cli/commands/read.py +1020 -0
  35. package/ccx/cli/commands/turns.py +1081 -0
  36. package/ccx/cli/controller.py +757 -0
  37. package/ccx/cli/main.py +301 -0
  38. package/ccx/cli/parser.py +1324 -0
  39. package/ccx/cli/skills.py +215 -0
  40. package/ccx/cli/statusline.py +160 -0
  41. package/ccx/client.py +1900 -0
  42. package/ccx/codex/__init__.py +0 -0
  43. package/ccx/codex/attach_tty.py +267 -0
  44. package/ccx/codex/client.py +732 -0
  45. package/ccx/codex/completion.py +121 -0
  46. package/ccx/codex/control.py +288 -0
  47. package/ccx/codex/daemon/__init__.py +0 -0
  48. package/ccx/codex/daemon/__main__.py +4 -0
  49. package/ccx/codex/daemon/daemon.py +1556 -0
  50. package/ccx/codex/daemon/models.py +140 -0
  51. package/ccx/codex/daemon/native.py +1590 -0
  52. package/ccx/codex/daemon/release.py +367 -0
  53. package/ccx/codex/daemon/worker.py +2396 -0
  54. package/ccx/codex/delivery.py +758 -0
  55. package/ccx/codex/delivery_recovery.py +232 -0
  56. package/ccx/codex/evidence.py +827 -0
  57. package/ccx/codex/history.py +158 -0
  58. package/ccx/codex/notify_history.py +140 -0
  59. package/ccx/codex/ops.py +666 -0
  60. package/ccx/codex/paths.py +70 -0
  61. package/ccx/codex/protocol.py +805 -0
  62. package/ccx/codex/provenance.py +105 -0
  63. package/ccx/codex/read.py +29 -0
  64. package/ccx/codex/records.py +51 -0
  65. package/ccx/codex/reports.py +177 -0
  66. package/ccx/codex/runtime.py +1412 -0
  67. package/ccx/codex/settle.py +363 -0
  68. package/ccx/codex/telemetry.py +792 -0
  69. package/ccx/codex/types.py +659 -0
  70. package/ccx/codex/worker_environment.py +25 -0
  71. package/ccx/constants.py +288 -0
  72. package/ccx/controllers/__init__.py +0 -0
  73. package/ccx/controllers/controller.py +1449 -0
  74. package/ccx/controllers/live_vars.py +1706 -0
  75. package/ccx/controllers/live_vars_runner.py +216 -0
  76. package/ccx/controllers/notify.py +213 -0
  77. package/ccx/controllers/orchestrator.py +193 -0
  78. package/ccx/controllers/policy.py +57 -0
  79. package/ccx/controllers/store.py +681 -0
  80. package/ccx/errors.py +634 -0
  81. package/ccx/notify/__init__.py +0 -0
  82. package/ccx/notify/__main__.py +5 -0
  83. package/ccx/notify/client.py +116 -0
  84. package/ccx/notify/daemon.py +480 -0
  85. package/ccx/notify/deliver.py +304 -0
  86. package/ccx/notify/paths.py +51 -0
  87. package/ccx/notify/registry.py +649 -0
  88. package/ccx/notify/select.py +750 -0
  89. package/ccx/notify/settle.py +684 -0
  90. package/ccx/ops/__init__.py +0 -0
  91. package/ccx/ops/background.py +115 -0
  92. package/ccx/ops/cancel.py +289 -0
  93. package/ccx/ops/codex_import.py +96 -0
  94. package/ccx/ops/common.py +397 -0
  95. package/ccx/ops/compact.py +337 -0
  96. package/ccx/ops/compact_ops.py +550 -0
  97. package/ccx/ops/context_events.py +48 -0
  98. package/ccx/ops/conversation.py +1540 -0
  99. package/ccx/ops/conversation_paging.py +1338 -0
  100. package/ccx/ops/create.py +56 -0
  101. package/ccx/ops/creation.py +952 -0
  102. package/ccx/ops/creation_steps.py +579 -0
  103. package/ccx/ops/event_feed.py +710 -0
  104. package/ccx/ops/forking.py +711 -0
  105. package/ccx/ops/input.py +556 -0
  106. package/ccx/ops/maintenance.py +295 -0
  107. package/ccx/ops/report.py +770 -0
  108. package/ccx/ops/semantics.py +490 -0
  109. package/ccx/ops/send.py +961 -0
  110. package/ccx/ops/steer_ops.py +867 -0
  111. package/ccx/ops/terminate.py +383 -0
  112. package/ccx/ops/turn_reports.py +306 -0
  113. package/ccx/ops/wait.py +762 -0
  114. package/ccx/ops/worker_events.py +636 -0
  115. package/ccx/rpc/__init__.py +0 -0
  116. package/ccx/rpc/local_rpc.py +1602 -0
  117. package/ccx/rpc/rpc.py +559 -0
  118. package/ccx/rpc/serve.py +374 -0
  119. package/ccx/rpc/transport.py +409 -0
  120. package/ccx/rpc/view.py +125 -0
  121. package/ccx/store/__init__.py +0 -0
  122. package/ccx/store/discovery.py +170 -0
  123. package/ccx/store/identity.py +105 -0
  124. package/ccx/store/journal_io.py +79 -0
  125. package/ccx/store/liveness.py +194 -0
  126. package/ccx/store/paths.py +254 -0
  127. package/ccx/store/record_cache.py +40 -0
  128. package/ccx/store/records.py +309 -0
  129. package/ccx/store/root.py +804 -0
  130. package/ccx/store/runtime_presence.py +137 -0
  131. package/ccx/store/store.py +2332 -0
  132. package/ccx/store/worker_state.py +86 -0
  133. package/ccx/system/__init__.py +0 -0
  134. package/ccx/system/bounded.py +296 -0
  135. package/ccx/system/cwd_paths.py +25 -0
  136. package/ccx/system/engine_binary.py +59 -0
  137. package/ccx/system/executable.py +50 -0
  138. package/ccx/system/oslayer.py +667 -0
  139. package/ccx/system/pipes.py +46 -0
  140. package/ccx/system/sanitize.py +43 -0
  141. package/ccx/types.py +705 -0
  142. package/ccx/version.py +29 -0
  143. package/ccx/workers.py +2081 -0
  144. package/ccx.py +9 -0
  145. package/package.json +40 -4
  146. package/pyproject.toml +87 -0
  147. package/skills/ccx/SKILL.md +155 -0
  148. package/skills/ccx/references/controllers.md +244 -0
  149. package/skills/ccx/references/troubleshooting.md +94 -0
  150. package/skills/ccx/references/variables.md +62 -0
@@ -0,0 +1,750 @@
1
+ from __future__ import annotations
2
+ import hashlib
3
+ import time
4
+ import uuid
5
+ from typing import Any
6
+ from ccx.errors import InvalidRequest, SessionUnavailable
7
+ from ccx.ops.turn_reports import codex_native_turn_evidence as _codex_native_turn_evidence
8
+
9
+
10
+ def _controller_notification_shape(
11
+ value: dict[str, Any], worker: dict[str, Any], operation: dict[str, Any],
12
+ ) -> None:
13
+ """Static v3 controller subject, independent of any later run state."""
14
+ from ccx.store.identity import IdentityError, canonical_worker_id
15
+
16
+ try:
17
+ canonical_worker_id(worker.get("workerId"))
18
+ canonical_worker_id(operation.get("attemptToken"))
19
+ event = uuid.UUID(value.get("eventId"))
20
+ except (IdentityError, TypeError, ValueError, AttributeError):
21
+ raise SessionUnavailable("controller notification identity invalid") from None
22
+ if (set(worker) != {"engine", "workerId", "generation", "name"}
23
+ or set(operation) != {"kind", "attempt", "attemptToken", "startupDeadlineMs"}
24
+ or operation.get("kind") != "controller-attempt"
25
+ or type(operation.get("attempt")) is not int or operation["attempt"] < 1
26
+ or type(operation.get("startupDeadlineMs")) is not int
27
+ or operation["startupDeadlineMs"] <= 0
28
+ or str(event) != value.get("eventId") or event.version != 4
29
+ or value.get("registrationKeySha256") is not None
30
+ or value.get("settlementMode") is not None):
31
+ raise SessionUnavailable("controller notification identity invalid")
32
+
33
+
34
+ def _controller_attempt_at_arm(run_id: str, operation: dict[str, Any], source: str) -> None:
35
+ """Check controller run/layout/slot once, before publishing an event."""
36
+ from ccx.controllers import store as controller_store
37
+ from ccx.errors import ControllerError
38
+
39
+ bootstrap = controller_store.bootstrap_root() / run_id
40
+ run_dir = (bootstrap if bootstrap.is_dir() else next(
41
+ (path for path in controller_store._all_run_dirs() if path.name == run_id), None
42
+ ))
43
+ if run_dir is None:
44
+ raise SessionUnavailable("controller run not found for notification")
45
+ try:
46
+ record = controller_store.read_json(controller_store.run_record_path(run_dir))
47
+ controller_store.require_operation_journal_layout(run_dir, record)
48
+ except (ControllerError, OSError) as exc:
49
+ raise SessionUnavailable(f"controller notification run unavailable: {exc}") from exc
50
+ if record.get("runId") != run_id:
51
+ raise SessionUnavailable("controller notification run identity changed")
52
+ number, token = operation["attempt"], operation["attemptToken"]
53
+ attempts = record.get("attempts") or []
54
+ selected = next((item for item in attempts
55
+ if isinstance(item, dict) and item.get("number") == number), None)
56
+ if selected is not None and selected.get("attemptToken") == token:
57
+ if source != "controller.run" or number == 1:
58
+ return
59
+ elif (selected is None and source == "controller.resume" and number == len(attempts) + 1
60
+ and attempts and isinstance(attempts[-1], dict)
61
+ and attempts[-1].get("number") == len(attempts)
62
+ and (record.get("lifecycle") or {}).get("state")
63
+ in controller_store.TERMINAL_LIFECYCLES):
64
+ # The caller holds resume.lock and publishes this exact token next.
65
+ return
66
+ raise InvalidRequest("controller notification attempt or token is not the selected start")
67
+
68
+
69
+ def _original_notification_parent(store, parent: dict[str, Any], worker_id: str | None):
70
+ """The existing exact Codex return address; never infer one from a child."""
71
+ if parent["kind"] == "codex-native-thread":
72
+ native_thread = parent.get("threadId")
73
+ if (set(parent) != {"kind", "threadId"}
74
+ or not isinstance(native_thread, str) or not native_thread
75
+ or native_thread != native_thread.strip() or "\x00" in native_thread
76
+ or len(native_thread.encode("utf-8")) > 1024):
77
+ raise SessionUnavailable("interactive parent return address malformed")
78
+ # Managed-native inventory exclusion is proven when the caller arms.
79
+ return dict(parent)
80
+ parent_id = parent.get("workerId")
81
+ parent_owner = store.resolve(f"codex:{parent_id}")
82
+ if (parent_owner.worker_id != parent_id or parent_id == worker_id
83
+ or parent.get("generation") != store.generation):
84
+ raise SessionUnavailable("Notification recipient is invalid; verify the parent worker")
85
+ store.authorize_native_action(parent_owner.worker, "send")
86
+ parent_native = (store.record(parent_owner.worker).get("native") or {})
87
+ if (parent.get("threadId") != parent_native.get("threadId")
88
+ or parent_native.get("threadSource") != store.codex_source(parent_owner.worker)):
89
+ raise SessionUnavailable("Notification recipient changed; create a new notification")
90
+ return parent_owner.worker
91
+
92
+
93
+ def _compact_effect_receipt(store, child: str, engine: str, worker_id: str,
94
+ operation: dict[str, Any]) -> dict[str, Any] | None:
95
+ """Bind a compact event to its original full-UUID native source and intent."""
96
+ from ccx.ops.compact_ops import compact_intent_digest as claude_digest
97
+ from ccx.codex.ops import compact_intent_digest as codex_digest
98
+
99
+ original = operation["nativeSourceId"]
100
+ operation_id = operation["operationId"]
101
+ record = store.record(child)
102
+ native = record.get("native") or {}
103
+ activation = store.native_activation(child)
104
+ name = "sessionId" if engine == "claude" else "threadId"
105
+ source = (f"claude-session:{original}" if engine == "claude"
106
+ else store.codex_source(child))
107
+ if (native.get(name) != original
108
+ or activation.get("state") != "confirmed"
109
+ or activation.get("source") != source
110
+ or (activation.get("nativeBinding") or {}).get(name) != original
111
+ or (engine == "codex" and native.get("threadSource") != source)):
112
+ raise SessionUnavailable("Compaction worker changed; inspect its operation")
113
+ family = "compact" if engine == "claude" else "codex-compact"
114
+ digest = (claude_digest(worker_id, generation=store.generation,
115
+ native_session_id=original, operation_id=operation_id)
116
+ if engine == "claude" else codex_digest(
117
+ worker_id, store.generation, original, source, operation_id))
118
+ receipt = store.read_receipt(child, family, operation_id)
119
+ if receipt is not None and (
120
+ receipt.get("workerId") != worker_id
121
+ or receipt.get("engine") != engine
122
+ or receipt.get("generation") != store.generation
123
+ or receipt.get("operationId") != operation_id
124
+ or receipt.get("family") != family
125
+ or receipt.get("action") != "compact"
126
+ or receipt.get("intentSha256") != digest):
127
+ raise SessionUnavailable("Compaction delivery does not match the worker; inspect the operation")
128
+ return receipt
129
+
130
+
131
+ def _original_notification_registration(value: dict[str, Any]) -> tuple[Any, str | dict[str, Any], str]:
132
+ """Verify the typed notification subject and original Codex parent.
133
+
134
+ The old short-keyed registration layout is not a routing fallback; an
135
+ interactive native return address is never a managed worker target.
136
+ """
137
+ from ccx import constants
138
+ from ccx.store.root import require_ccx_active
139
+
140
+ store = require_ccx_active(constants.CCX_ROOT)
141
+ parent = value.get("parent") if isinstance(value.get("parent"), dict) else {}
142
+ worker = value.get("worker") if isinstance(value.get("worker"), dict) else {}
143
+ operation = value.get("operation") if isinstance(value.get("operation"), dict) else {}
144
+ worker_id = worker.get("workerId")
145
+ engine = worker.get("engine")
146
+ source = value.get("source")
147
+ if (value.get("version") != 3 or value.get("generation") != store.generation
148
+ or parent.get("kind") not in {"ccx-codex", "codex-native-thread"}
149
+ or engine not in {"codex", "claude", "controller"}
150
+ or worker.get("generation") != store.generation
151
+ or source not in ({"controller.run", "controller.resume", "controller.notify"}
152
+ if engine == "controller" else {"send", "notify", "new", "input", "compact"})
153
+ or value.get("settlementMode") not in {None, "orchestration"}
154
+ or (value.get("settlementMode") == "orchestration" and engine != "codex")):
155
+ raise SessionUnavailable("Notification record is incompatible; create a new notification")
156
+ if engine == "controller":
157
+ _controller_notification_shape(value, worker, operation)
158
+ # The independently minted controller run UUID is not a worker owner.
159
+ return store, _original_notification_parent(store, parent, None), f"controller:{worker_id}"
160
+ if source == "send":
161
+ from ccx.claude.delivery import valid_delivery_id
162
+ if (operation.get("kind") != f"{engine}-turn"
163
+ or not valid_delivery_id(operation.get("deliveryId"))):
164
+ raise SessionUnavailable("original send notification has no owned delivery ID")
165
+ key = f"full-uuid-{engine}-send:{store.generation}:{worker_id}:{operation['deliveryId']}"
166
+ if (value.get("eventId") != str(uuid.uuid5(uuid.NAMESPACE_URL, "ccx-notify:" + key))
167
+ or value.get("registrationKeySha256") != hashlib.sha256(key.encode()).hexdigest()):
168
+ raise SessionUnavailable("notification event ID differs from original semantic key")
169
+ elif source == "compact":
170
+ operation_id = operation.get("operationId")
171
+ original = operation.get("nativeSourceId")
172
+ if (set(operation) != {"kind", "operationId", "nativeSourceId"}
173
+ or operation.get("kind") != f"{engine}-compact"
174
+ or not isinstance(operation_id, str) or not 0 < len(operation_id) <= 128
175
+ or "\x00" in operation_id
176
+ or not isinstance(original, str) or not original):
177
+ raise SessionUnavailable("original compact notification operation malformed")
178
+ key = f"full-uuid-{engine}-compact:{store.generation}:{worker_id}:{operation_id}"
179
+ if (value.get("eventId") != str(uuid.uuid5(
180
+ uuid.NAMESPACE_URL, "ccx-notify:" + key))
181
+ or value.get("registrationKeySha256") != hashlib.sha256(
182
+ key.encode()).hexdigest()):
183
+ raise SessionUnavailable("original compact notification event differs from operation")
184
+ elif source == "input":
185
+ from ccx.store.root import _HASH
186
+ key = f"full-uuid-{engine}-input:{store.generation}:{worker_id}:{operation.get('gateId')}"
187
+ hashed_input = (engine == "claude"
188
+ and operation.get("kind") in {"claude-input-answer", "claude-input-respond"})
189
+ fields = {"kind", "gateId", "responseId", "nativeSourceId",
190
+ "intentSha256", "selectedTurnRef"}
191
+ fields |= ({"payloadSha256"} if hashed_input
192
+ else {"decision", "reason" if engine == "claude" else "turnId"})
193
+ reason = operation.get("reason")
194
+ ref = operation.get("selectedTurnRef")
195
+ if (set(operation) != fields
196
+ or (not hashed_input and (
197
+ operation.get("kind") != f"{engine}-input-decision"
198
+ or operation.get("decision") not in {"approve", "reject"}))
199
+ or (hashed_input and (
200
+ not isinstance(operation.get("payloadSha256"), str)
201
+ or not _HASH.fullmatch(operation["payloadSha256"])))
202
+ or any(not isinstance(operation.get(field), str) or not operation[field]
203
+ for field in ("gateId", "responseId", "nativeSourceId",
204
+ "intentSha256"))
205
+ or (engine == "claude"
206
+ and (reason is not None and (not isinstance(reason, str) or not reason)
207
+ or not isinstance(ref, str)
208
+ or not ref.startswith("ccx-turn:claude:v1:")
209
+ or len(ref) <= len("ccx-turn:claude:v1:")))
210
+ or (engine == "codex"
211
+ and (not isinstance(operation.get("turnId"), str)
212
+ or not operation["turnId"]
213
+ or ref != f"ccx-turn:codex:v1:{operation['turnId']}"))
214
+ or value.get("eventId") != str(uuid.uuid5(
215
+ uuid.NAMESPACE_URL, "ccx-notify:" + key))
216
+ or value.get("registrationKeySha256") != hashlib.sha256(key.encode()).hexdigest()):
217
+ raise SessionUnavailable("original input notification identity invalid")
218
+ elif source == "new":
219
+ # One original positive native creation, no model send or latest-turn
220
+ # selection. The event is keyed to the child, not the parent/mode.
221
+ key = f"full-uuid-{engine}-new:{store.generation}:{worker_id}:promptless"
222
+ if (engine not in {"claude", "codex"} or type(operation.get("expectTurn")) is not bool
223
+ or operation != {"kind": f"{engine}-stable", "expectTurn": False,
224
+ "selectionMode": "status-only", "stableState": "idle"}
225
+ or value.get("eventId") != str(uuid.uuid5(
226
+ uuid.NAMESPACE_URL, "ccx-notify:" + key))
227
+ or value.get("registrationKeySha256") != hashlib.sha256(key.encode()).hexdigest()):
228
+ raise SessionUnavailable("original promptless creation identity invalid")
229
+ else:
230
+ # Independent observation arms use random event identity. They are not
231
+ # fresh send attempts and cannot rekey an earlier delivery's event.
232
+ try:
233
+ event = uuid.UUID(value.get("eventId"))
234
+ except (ValueError, TypeError, AttributeError):
235
+ raise SessionUnavailable("standalone notification event UUID malformed") from None
236
+ if (str(event) != value.get("eventId") or event.version != 4
237
+ or value.get("registrationKeySha256") is not None):
238
+ raise SessionUnavailable("standalone observation needs its own UUIDv4 event")
239
+ kind = operation.get("kind")
240
+ selection = operation.get("selectionMode")
241
+ if kind == f"{engine}-compact" and selection == "active-compact":
242
+ token = operation.get("operationId")
243
+ original = operation.get("nativeSourceId")
244
+ if (set(operation) != {"kind", "selectionMode", "operationId",
245
+ "nativeSourceId"}
246
+ or not isinstance(token, str) or not 0 < len(token) <= 128
247
+ or "\x00" in token or not isinstance(original, str) or not original):
248
+ raise SessionUnavailable("standalone compact observation identity invalid")
249
+ elif kind == f"{engine}-stable":
250
+ if (selection != "status-only"
251
+ or operation.get("stableState") not in {
252
+ "idle", "idle-killed", "dead", "crashed", "budget-stopped"
253
+ } or operation.get("selectedTurnRef") is not None
254
+ or operation.get("deliveryId") is not None):
255
+ raise SessionUnavailable("standalone stable observation identity invalid")
256
+ elif (kind == "claude-next-turn" and engine == "claude"
257
+ and selection == "future"):
258
+ from ccx.ops.event_feed import decode_cursor
259
+ cursor = operation.get("armCursor")
260
+ ref = operation.get("selectedTurnRef")
261
+ if (set(operation) != {"kind", "selectionMode", "nativeSourceId",
262
+ "armCursor", "selectedTurnRef"}
263
+ or not isinstance(cursor, str)
264
+ or (ref is not None and (not isinstance(ref, str)
265
+ or not ref.startswith("ccx-turn:claude:v1:")
266
+ or len(ref) <= len("ccx-turn:claude:v1:")))):
267
+ raise SessionUnavailable("future Claude notification identity invalid")
268
+ decode_cursor(cursor, engine="claude", short=worker_id)
269
+ elif (kind == f"{engine}-observed-turn"
270
+ and selection in {"active", "last-settled"}):
271
+ from ccx.claude.delivery import valid_delivery_id
272
+ ref = operation.get("selectedTurnRef")
273
+ if (not isinstance(ref, str)
274
+ or not ref.startswith(f"ccx-turn:{engine}:v1:")
275
+ or len(ref) <= len(f"ccx-turn:{engine}:v1:")):
276
+ raise SessionUnavailable("standalone selected original turn identity invalid")
277
+ if operation.get("nativeProof") == "original-native-turn":
278
+ fields = {"kind", "selectionMode", "selectedTurnRef",
279
+ "nativeProof", "nativeSourceId"}
280
+ if engine == "codex":
281
+ fields.add("turnId")
282
+ if (set(operation) != fields
283
+ or not isinstance(operation.get("nativeSourceId"), str)
284
+ or not operation["nativeSourceId"]
285
+ or (engine == "codex" and operation.get("turnId") !=
286
+ ref[len("ccx-turn:codex:v1:"):])):
287
+ raise SessionUnavailable("receiptless native turn identity invalid")
288
+ elif (operation.get("nativeProof") is not None
289
+ or not valid_delivery_id(operation.get("deliveryId"))):
290
+ raise SessionUnavailable("standalone selected original delivery invalid")
291
+ else:
292
+ raise SessionUnavailable("standalone observation operation unsupported")
293
+ # The child is always an exactly owned original UUID; only the caller's
294
+ # return-address kind varies. No native parent ID is a worker target.
295
+ worker_owner = store.resolve(f"{engine}:{worker_id}")
296
+ if worker_owner.worker_id != worker_id:
297
+ raise SessionUnavailable("Notification worker is invalid; verify its handle")
298
+ # This is a read-only original source/binding gate. It is lifecycle
299
+ # independent and permits stopped workers, but never terminalOnly or
300
+ # pending provider bindings; no model native action is performed.
301
+ store.authorize_native_action(worker_owner.worker, "send")
302
+ if source == "compact" or (source == "notify"
303
+ and operation.get("kind") == f"{engine}-compact"):
304
+ receipt = _compact_effect_receipt(
305
+ store, worker_owner.worker, engine, worker_id, operation)
306
+ if source == "notify" and (receipt is None or receipt.get("state") not in {
307
+ "submitted-unknown", "accepted"}):
308
+ raise SessionUnavailable("standalone compact has no authenticated original effect")
309
+ if source == "input":
310
+ # Lazy import avoids a module-load cycle, and one original input
311
+ # digest layout is shared by Claude, Codex and the public protocol.
312
+ from ccx.ops.input import _input_intent_digest
313
+ record = store.record(worker_owner.worker)
314
+ native = record.get("native") or {}
315
+ source_id = operation["nativeSourceId"]
316
+ expected_source = (f"claude-session:{source_id}" if engine == "claude"
317
+ else store.codex_source(worker_owner.worker))
318
+ hashed_input = (engine == "claude"
319
+ and operation["kind"] in {"claude-input-answer", "claude-input-respond"})
320
+ expected_sha = _input_intent_digest(
321
+ worker_id=worker_id, engine=engine, generation=store.generation,
322
+ native_id=source_id, native_source=expected_source,
323
+ kind=(operation["kind"].removeprefix("claude-input-") if hashed_input else "decide"),
324
+ request_id=operation["gateId"], response_id=operation["responseId"],
325
+ **({"payload_sha256": operation["payloadSha256"]} if hashed_input else
326
+ {"payload": {"decision": operation["decision"],
327
+ "reason": operation["reason"] if engine == "claude" else None}}),
328
+ )
329
+ intent = store.read_receipt(worker_owner.worker, "answer", operation["responseId"])
330
+ if (native.get("sessionId" if engine == "claude" else "threadId") != source_id
331
+ or (engine == "codex" and native.get("threadSource") != expected_source)
332
+ or not isinstance(intent, dict)
333
+ or intent.get("workerId") != worker_id
334
+ or intent.get("engine") != engine
335
+ or intent.get("generation") != store.generation
336
+ or intent.get("family") != "answer"
337
+ or intent.get("action") != "answer"
338
+ or intent.get("operationId") != operation["responseId"]
339
+ or operation["intentSha256"] != expected_sha
340
+ or intent.get("intentSha256") != expected_sha):
341
+ raise SessionUnavailable("original input receipt/source/decision proof invalid")
342
+ if engine == "claude":
343
+ from ccx.claude.managed_turns import report_window_for_turn_ref
344
+ window, available = report_window_for_turn_ref(
345
+ worker_id, operation["selectedTurnRef"])
346
+ offset = window.get("startOffset") if isinstance(window, dict) else None
347
+ if not available or type(offset) is not int or offset < 0:
348
+ raise SessionUnavailable("original Claude input R lacks native start/window proof")
349
+ if source == "notify" and operation["kind"] == "claude-next-turn":
350
+ native = store.record(worker_owner.worker).get("native") or {}
351
+ if (not isinstance(operation.get("nativeSourceId"), str)
352
+ or not operation["nativeSourceId"]
353
+ or operation["nativeSourceId"] != native.get("sessionId")):
354
+ raise SessionUnavailable("future Claude native source changed")
355
+ ref = operation.get("selectedTurnRef")
356
+ if ref is not None and not _future_first_ref_matches(
357
+ worker_id, operation["armCursor"], ref):
358
+ raise SessionUnavailable("future Claude selected R is not first post-arm start")
359
+ elif (source == "notify" and operation["kind"] == f"{engine}-observed-turn"
360
+ and operation.get("nativeProof") == "original-native-turn"):
361
+ record = store.record(worker_owner.worker)
362
+ native = record.get("native") or {}
363
+ original = operation["nativeSourceId"]
364
+ if engine == "claude":
365
+ from ccx.claude.managed_turns import report_window_for_turn_ref
366
+ window, available = report_window_for_turn_ref(
367
+ worker_id, operation["selectedTurnRef"])
368
+ start = window.get("startOffset") if isinstance(window, dict) else None
369
+ valid = (native.get("sessionId") == original and available
370
+ and type(start) is int and start >= 0)
371
+ else:
372
+ valid = (native.get("threadId") == original and
373
+ native.get("threadSource") == store.codex_source(worker_owner.worker))
374
+ if valid:
375
+ valid = _codex_native_turn_evidence(
376
+ worker_owner.worker, record, original, operation["turnId"]) is not None
377
+ if not valid:
378
+ raise SessionUnavailable("receiptless selected original native source or turn proof changed")
379
+ elif source == "notify" and operation["kind"] == f"{engine}-observed-turn":
380
+ token = operation["deliveryId"]
381
+ if engine == "codex":
382
+ from ccx.codex import delivery as codex_delivery
383
+ receipt = codex_delivery.read_receipt(worker_owner.worker, token)
384
+ valid = (isinstance(receipt, dict) and receipt.get("state") == "accepted"
385
+ and codex_delivery.route(receipt) == "new_turn"
386
+ and codex_delivery.placement(receipt) == "new_turn"
387
+ and receipt.get("turnId") == operation.get("turnId")
388
+ and operation["selectedTurnRef"] == codex_delivery.turn_ref_for(receipt["turnId"])
389
+ and all(receipt.get(field) == operation.get(field)
390
+ for field in ("requestedMode", "promptSha256",
391
+ "callerMetadata", "clientUserMessageId")))
392
+ else:
393
+ from ccx.claude import delivery as claude_delivery
394
+ receipt = claude_delivery.read_receipt(worker_owner.worker, token)
395
+ valid = (isinstance(receipt, dict) and receipt.get("state") == "accepted"
396
+ and receipt.get("route") == "new_turn"
397
+ and receipt.get("placement") == "new_turn"
398
+ and receipt.get("turnRef") == operation["selectedTurnRef"]
399
+ and all(receipt.get(field) == operation.get(field)
400
+ for field in ("requestedMode", "promptSha256",
401
+ "promptByteCount", "callerMetadata", "cap")))
402
+ if not valid or receipt.get("requestedMode") not in {"new_turn_only", "auto"}:
403
+ raise SessionUnavailable("selected turn differs from its original opener receipt")
404
+ if engine == "claude":
405
+ native = store.record(worker_owner.worker).get("native") or {}
406
+ if (not isinstance(native.get("sessionId"), str)
407
+ or not native["sessionId"]):
408
+ raise SessionUnavailable("original Claude notification child native session is unbound")
409
+ return store, _original_notification_parent(store, parent, worker_id), worker_owner.worker
410
+
411
+
412
+ def _active_compact_selection(store, owner, record: dict[str, Any]) -> dict[str, Any] | None:
413
+ """Observe only an already-active, original-effect-backed native compact."""
414
+ from ccx.errors import CcxError, OperationConflict
415
+ from ccx.store.root import GenerationError
416
+
417
+ engine, child, wid = owner.engine, owner.worker, owner.worker_id
418
+ if engine == "claude":
419
+ from ccx.ops.compact_ops import active_operation
420
+ try:
421
+ active = active_operation(wid)
422
+ except (OSError, ValueError, RuntimeError) as error:
423
+ raise SessionUnavailable(f"Claude compact journal unavailable: {error}") from error
424
+ if active is None:
425
+ return None
426
+ token = active.get("operation_id")
427
+ else:
428
+ active = record.get("activeCompact")
429
+ if active is None:
430
+ return None
431
+ token = active.get("operationId") if isinstance(active, dict) else None
432
+ native = record.get("native") or {}
433
+ native_id = native.get("sessionId" if engine == "claude" else "threadId")
434
+ if (not isinstance(token, str) or not 0 < len(token) <= 128 or "\x00" in token
435
+ or not isinstance(native_id, str) or not native_id):
436
+ raise OperationConflict("Compaction operation cannot be verified; inspect the worker")
437
+ operation = {"kind": f"{engine}-compact", "selectionMode": "active-compact",
438
+ "operationId": token, "nativeSourceId": native_id}
439
+ receipt = _compact_effect_receipt(store, child, engine, wid, operation)
440
+ if not isinstance(receipt, dict) or receipt.get("state") not in {
441
+ "submitted-unknown", "accepted"}:
442
+ raise OperationConflict("Compaction has no recorded submission; inspect its operation")
443
+ try:
444
+ if engine == "claude":
445
+ from ccx.ops.compact import compact_status
446
+ status = compact_status(child, operation_id=token, publish=False).get("operation_status")
447
+ valid = status in {"accepted", "pasted", "submitted"}
448
+ else:
449
+ from ccx.codex.ops import compact_observation
450
+ valid = compact_observation(child, token).get("status") == "submitted"
451
+ except (CcxError, GenerationError, OSError, ValueError):
452
+ valid = False
453
+ if not valid:
454
+ raise OperationConflict("Compaction outcome is unknown; inspect the operation")
455
+ # Freeze exactly the original ID, never a later compact or a model-turn R.
456
+ latest = store.record(child)
457
+ if engine == "claude":
458
+ from ccx.ops.compact_ops import active_operation
459
+ try:
460
+ current = active_operation(wid)
461
+ except (OSError, ValueError, RuntimeError) as error:
462
+ raise SessionUnavailable(f"Claude compact changed during selection: {error}") from error
463
+ same = isinstance(current, dict) and current.get("operation_id") == token
464
+ else:
465
+ current = latest.get("activeCompact")
466
+ same = isinstance(current, dict) and current.get("operationId") == token
467
+ if (not same or (latest.get("native") or {}).get(
468
+ "sessionId" if engine == "claude" else "threadId") != native_id):
469
+ raise OperationConflict("Compaction changed during selection; retry notification")
470
+ store.revalidate()
471
+ return operation
472
+
473
+
474
+ def _claude_prompt_opening(child: str) -> bool:
475
+ """A Claude send is still being pasted (owned, not yet accepted)."""
476
+ from ccx.claude import delivery as claude_delivery
477
+ try:
478
+ return any(row.get("state") == "owned"
479
+ for row in claude_delivery.iter_receipts(child))
480
+ except (claude_delivery.ClaudeDeliveryError, OSError):
481
+ return False
482
+
483
+
484
+ def select_current_turn(target: str) -> dict[str, Any]:
485
+ """Read one original managed turn or positively proven stable no-turn."""
486
+ from ccx.claude import delivery as claude_delivery
487
+ from ccx.codex import delivery as codex_delivery
488
+ from ccx import constants
489
+ from ccx.errors import OperationConflict
490
+ from ccx.ops.wait import wait_worker
491
+ from ccx.store.root import require_ccx_active
492
+
493
+ store = require_ccx_active(constants.CCX_ROOT)
494
+ owner = store.resolve(target)
495
+ child = owner.worker
496
+ store.authorize_native_action(child, "send") # original binding check only
497
+ record = store.record(child)
498
+ compact = _active_compact_selection(store, owner, record)
499
+ if compact is not None:
500
+ return {"worker": child, "worker_id": owner.worker_id,
501
+ "engine": owner.engine, "name": record.get("name"),
502
+ "state": "compacting", "operation": compact}
503
+ # One bounded read: a zero-second call gives the live daemon barely .01s
504
+ # and may falsely label a healthy just-settled worker inconclusive.
505
+ snapshot = wait_worker(child, timeout=.75, expected_generation=store.generation)
506
+ # Right after `new/send --no-wait` the worker is idle while the prompt is
507
+ # still being delivered; wait briefly for that turn to open instead of
508
+ # selecting the previous one.
509
+ settle_by = time.monotonic() + 15
510
+ while (snapshot.get("state") == "idle" and snapshot.get("active_turn_ref") is None
511
+ and (snapshot.get("status") == "timeout"
512
+ or owner.engine == "claude" and _claude_prompt_opening(child))
513
+ and time.monotonic() < settle_by):
514
+ time.sleep(.25)
515
+ snapshot = wait_worker(child, timeout=.75, expected_generation=store.generation)
516
+ if (owner.engine == "claude" and snapshot.get("active_turn_ref") is None
517
+ and _claude_prompt_opening(child)):
518
+ raise SessionUnavailable(
519
+ "the last message to this worker is still being delivered; "
520
+ "retry notify once its turn has started")
521
+ state = snapshot.get("state")
522
+ active = snapshot.get("active_turn_ref")
523
+ live_idle = (snapshot.get("status") == "idle"
524
+ and snapshot.get("reason") == "worker is idle")
525
+ if owner.engine == "claude" and (active is not None or live_idle):
526
+ # The host can be compacting even before the journal is visible.
527
+ from ccx.rpc.rpc import _rpc
528
+ try:
529
+ status = _rpc(child, {"op": "status"}, timeout=.5)
530
+ except (OSError, ValueError, TimeoutError) as error:
531
+ raise SessionUnavailable(f"Claude compact status read unavailable: {error}") from error
532
+ if (status.get("ok") is not True or status.get("compacting") is not False
533
+ or status.get("compactJournalError")):
534
+ raise OperationConflict("Claude compact state unavailable or active")
535
+ if status.get("activeTurnRef") != active:
536
+ raise SessionUnavailable("original Claude active turn changed while selecting")
537
+ if state in {"busy", "waiting"}:
538
+ if not isinstance(active, str) or not active:
539
+ raise SessionUnavailable("busy/waiting worker has no proven original active turn")
540
+ ref, selection = active, "active"
541
+ elif state in {"idle", "idle-killed", "dead", "crashed", "budget-stopped"}:
542
+ if state == "idle" and active is not None:
543
+ raise SessionUnavailable("idle worker retains an untrusted active turn")
544
+ if state != "idle" and (record.get("lifecycle") or {}).get("state") != state:
545
+ raise SessionUnavailable("terminal worker state differs from durable source")
546
+ settled = snapshot.get("last_settled_turn")
547
+ ref = settled.get("turn_ref") if isinstance(settled, dict) else None
548
+ selection = "last-settled"
549
+ else:
550
+ raise SessionUnavailable("worker state cannot select an original model turn")
551
+
552
+ receipt = None
553
+ if isinstance(ref, str) and ref.startswith(f"ccx-turn:{owner.engine}:v1:"):
554
+ if owner.engine == "codex":
555
+ turn_id = ref[len("ccx-turn:codex:v1:"):]
556
+ try:
557
+ receipt = codex_delivery.receipt_for_turn(child, turn_id)
558
+ except (codex_delivery.DeliveryReceiptError, OSError) as error:
559
+ raise SessionUnavailable(f"Codex original opener receipt untrusted: {error}") from error
560
+ if (not isinstance(receipt, dict) or receipt.get("state") != "accepted"
561
+ or codex_delivery.route(receipt) != "new_turn"
562
+ or codex_delivery.placement(receipt) != "new_turn"
563
+ or receipt.get("turnId") != turn_id):
564
+ receipt = None
565
+ else:
566
+ # Claude's existing receipt inventory is best effort. Match only
567
+ # unique eligible valid openers, then strictly reread that token.
568
+ try:
569
+ candidates = [row for row in claude_delivery.iter_receipts(child)
570
+ if row.get("state") == "accepted"
571
+ and row.get("route") == "new_turn"
572
+ and row.get("placement") == "new_turn"
573
+ and row.get("turnRef") == ref]
574
+ if len(candidates) == 1:
575
+ receipt = claude_delivery.read_receipt(child, candidates[0]["deliveryId"])
576
+ except (claude_delivery.ClaudeDeliveryError, OSError) as error:
577
+ raise SessionUnavailable(f"Claude original opener receipt untrusted: {error}") from error
578
+ if receipt is not None:
579
+ if (receipt.get("turnRef") != ref
580
+ or receipt.get("state") != "accepted"
581
+ or receipt.get("route") != "new_turn"
582
+ or receipt.get("placement") != "new_turn"):
583
+ receipt = None
584
+ if receipt is None:
585
+ native = record.get("native") or {}
586
+ original = native.get("sessionId" if owner.engine == "claude" else "threadId")
587
+ proven = False
588
+ if isinstance(ref, str) and isinstance(original, str) and original:
589
+ if owner.engine == "claude":
590
+ from ccx.claude.managed_turns import report_window_for_turn_ref
591
+ window, available = report_window_for_turn_ref(owner.worker_id, ref)
592
+ start = window.get("startOffset") if isinstance(window, dict) else None
593
+ proven = (available and type(start) is int and start >= 0)
594
+ elif native.get("threadSource") == store.codex_source(owner.worker):
595
+ proven = _codex_native_turn_evidence(child, record, original,
596
+ ref[len("ccx-turn:codex:v1:"):]) is not None
597
+ if proven and state in {"busy", "waiting"}:
598
+ from ccx.codex import runtime as codex_runtime
599
+ served = codex_runtime.observe_worker(owner.worker_id, timeout=.5)
600
+ reply = served.get("reply") or {}
601
+ proven = (served.get("daemon_served") is True and
602
+ reply.get("ok") is True and reply.get("loaded") is True
603
+ and reply.get("activeTurnId") == ref[len("ccx-turn:codex:v1:"):])
604
+ if proven:
605
+ operation = {"kind": f"{owner.engine}-observed-turn",
606
+ "selectionMode": selection, "selectedTurnRef": ref,
607
+ "nativeProof": "original-native-turn", "nativeSourceId": original}
608
+ if owner.engine == "codex":
609
+ operation["turnId"] = ref[len("ccx-turn:codex:v1:"):]
610
+ else:
611
+ if state in {"busy", "waiting"}:
612
+ raise SessionUnavailable("current original turn lacks an eligible opening receipt or native proof")
613
+ if state == "idle" and not live_idle:
614
+ raise SessionUnavailable(
615
+ "Cannot notify yet: the worker's idle state could not be confirmed. "
616
+ "Check its status and retry."
617
+ )
618
+ operation = {"kind": f"{owner.engine}-stable",
619
+ "selectionMode": "status-only", "selectedTurnRef": None,
620
+ "stableState": state}
621
+ else:
622
+ operation = {"kind": f"{owner.engine}-observed-turn",
623
+ "selectionMode": selection, "selectedTurnRef": ref,
624
+ "deliveryId": receipt["deliveryId"],
625
+ "requestedMode": receipt.get("requestedMode"),
626
+ "promptSha256": receipt.get("promptSha256"),
627
+ "callerMetadata": receipt.get("callerMetadata")}
628
+ if owner.engine == "codex":
629
+ operation.update(turnId=receipt["turnId"],
630
+ clientUserMessageId=receipt.get("clientUserMessageId"))
631
+ else:
632
+ operation.update(promptByteCount=receipt.get("promptByteCount"),
633
+ cap=receipt.get("cap"))
634
+ store.revalidate()
635
+ return {"worker": child, "worker_id": owner.worker_id,
636
+ "engine": owner.engine, "name": record.get("name"),
637
+ "state": state, "operation": operation}
638
+
639
+
640
+ def select_future_turn(target: str) -> dict[str, Any]:
641
+ """Arm one future Claude turn only from a positively served idle host."""
642
+ from ccx import constants
643
+ from ccx.ops.compact_ops import active_operation
644
+ from ccx.ops.event_feed import read_page, decode_cursor
645
+ from ccx.store.paths import events_ndjson_path
646
+ from ccx.ops.wait import wait_worker
647
+ from ccx.rpc.rpc import _rpc
648
+ from ccx.store.root import require_ccx_active
649
+
650
+ store = require_ccx_active(constants.CCX_ROOT)
651
+ owner = store.resolve(target)
652
+ if owner.engine != "claude":
653
+ raise SessionUnavailable("notify --next-turn requires managed Claude")
654
+ store.authorize_native_action(owner.worker, "send") # binding only
655
+ record = store.record(owner.worker)
656
+ native = record.get("native") or {}
657
+ sid = native.get("sessionId")
658
+ if (not isinstance(sid, str) or not sid
659
+ or (record.get("lifecycle") or {}).get("state") != "idle"):
660
+ raise SessionUnavailable("notify --next-turn requires a live idle managed worker")
661
+ if active_operation(owner.worker_id) is not None:
662
+ raise SessionUnavailable("notify --next-turn requires a live idle managed worker (compact active)")
663
+ if not events_ndjson_path(owner.worker_id).is_file():
664
+ raise SessionUnavailable("Cannot find an upcoming Claude turn; retry notification")
665
+ cursor = read_page("claude", owner.worker_id, tail=0)["next_cursor"]
666
+ if decode_cursor(cursor, engine="claude", short=owner.worker_id).get("i") is None:
667
+ raise SessionUnavailable("future Claude event baseline not retained")
668
+ snapshot = wait_worker(owner.worker, timeout=.75,
669
+ expected_generation=store.generation)
670
+ try:
671
+ live = _rpc(owner.worker, {"op": "status"}, timeout=.5)
672
+ except (OSError, ValueError, TimeoutError) as error:
673
+ raise SessionUnavailable(f"future Claude original host unavailable: {error}") from error
674
+ if (snapshot.get("worker") != owner.worker
675
+ or snapshot.get("state") != "idle"
676
+ or snapshot.get("status") != "idle"
677
+ or snapshot.get("reason") != "worker is idle"
678
+ or snapshot.get("active_turn_ref") is not None
679
+ or live.get("ok") is not True or live.get("state") != "idle"
680
+ or live.get("activeTurnRef") is not None
681
+ or live.get("waitingFor") is not None
682
+ or live.get("compacting") is not False or live.get("compactJournalError")
683
+ or active_operation(owner.worker_id) is not None
684
+ or (store.record(owner.worker).get("native") or {}).get("sessionId") != sid):
685
+ raise SessionUnavailable("notify --next-turn requires a live idle managed worker")
686
+ changed = read_page("claude", owner.worker_id, after=cursor, native=True)
687
+ if changed["gap"] or changed["has_more"] or changed["events"]:
688
+ raise SessionUnavailable("future Claude baseline changed during idle admission")
689
+ store.revalidate()
690
+ return {"worker": owner.worker, "worker_id": owner.worker_id,
691
+ "engine": "claude", "name": record.get("name"), "state": "idle",
692
+ "operation": {"kind": "claude-next-turn", "selectionMode": "future",
693
+ "nativeSourceId": sid, "armCursor": cursor,
694
+ "selectedTurnRef": None}}
695
+
696
+
697
+ def _future_events(worker_id: str, cursor: str | None) -> list[dict] | None:
698
+ """One existing physical-order event-feed walk, or None on a cursor gap."""
699
+ from ccx.ops.event_feed import read_page
700
+ rows = []
701
+ while True:
702
+ page = read_page("claude", worker_id, after=cursor, native=True,
703
+ limit=1000)
704
+ if page["gap"]:
705
+ return None
706
+ rows.extend(page["events"])
707
+ if not page["has_more"]:
708
+ return rows
709
+ cursor = page["next_cursor"]
710
+
711
+
712
+ def _future_ref_before(worker_id: str, cursor: str, ref: str) -> bool:
713
+ """Missing baseline or older evidence disqualifies a first future start."""
714
+ from ccx.ops.event_feed import decode_cursor, read_page
715
+ at = decode_cursor(cursor, engine="claude", short=worker_id)
716
+ if at["p"] is None and at["q"] == 0:
717
+ return False
718
+ next_cursor = None
719
+ while True:
720
+ page = read_page("claude", worker_id, after=next_cursor,
721
+ native=True, limit=1000)
722
+ if page["gap"]:
723
+ return True
724
+ for row in page["events"]:
725
+ if row.get("turn_ref") == ref:
726
+ return True
727
+ if row.get("epoch") == at["p"] and row.get("seq") == at["q"]:
728
+ return False
729
+ if not page["has_more"]:
730
+ return True # baseline rotated out, never adopt later old R
731
+ next_cursor = page["next_cursor"]
732
+
733
+
734
+ def _future_first_ref_matches(worker_id: str, cursor: str, ref: str) -> bool:
735
+ """Select the first eligible future turn, so later starts cannot replace it."""
736
+ events = _future_events(worker_id, cursor)
737
+ if events is None:
738
+ return False
739
+ seen: set[str] = set()
740
+ for row in events:
741
+ candidate = row.get("turn_ref")
742
+ if not isinstance(candidate, str) or not candidate.startswith("ccx-turn:claude:v1:"):
743
+ continue
744
+ if candidate in seen:
745
+ continue
746
+ seen.add(candidate)
747
+ if (row.get("type") in {"turn_start", "turn_identity_recovered"}
748
+ and not _future_ref_before(worker_id, cursor, candidate)):
749
+ return candidate == ref
750
+ return False