From 0e8b1977569c5949bf5e75e1a42e7fb3bcc10fe0 Mon Sep 17 00:00:00 2001 From: Simon Qi Date: Wed, 26 Aug 2026 18:34:20 +1200 Subject: [PATCH] Say what the Session model is now, in the three comments that still describe the old one (#97) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Comments only; no behaviour, and the diff is three doc blocks. `core/clock.py` and `core/bridge.py` both justified `wall_clock` with a Session's `registered_at` being written to disk and read back by the next engine. #74 renamed the field to `first_seen` and deleted the Session half of `core/state.py`, so the sentence was false twice over — and it was the only example either comment offered for why two clocks exist at all. The fact that still holds is not durability. Nothing durable carries a timestamp any more: `PersistedState` is switch state and nothing else (`core/persistence.py:57-76`), and the roster is deliberately not persisted (`core/state.py:9-12`). What `first_seen` does is *leave the process* — it travels to every surface in the `sessions` payload (`control_plane/payloads.py:151`), where a monotonic reading is an offset from an origin only the engine knows and names no moment at all. So the rule is restated as "nothing read outside this process", which is broader than the durability rule it replaces and covers it. `ControlPanel.swift` said every action it offers "is one of the nine". #72 made it seven and #76 makes it eight. #97 offered pointing at `tests/test_app_bundle.py::TestTheThingsThatMustAgree` instead, but that class does not hold the two action sets together yet — that guard arrives with #76 — so the sentence is written to need no count and no pointer. The claim it was always making is "no private protocol", and that survives the count changing. Left alone on purpose: `docs/control-plane.md:121,129` carries the same stale `registered_at`, including as the payload's key name. #76 already rewrites both lines in its branch, so fixing it here would only be a merge conflict. Legacy: comments only, no runtime behaviour, so there is nothing to cite. Gates: ruff check, ruff format --check, pytest (1267 passed), swift build, swift test --disable-xctest (123 tests), swift format lint --strict. Co-Authored-By: Claude Opus 5 (1M context) --- shell/Sources/ShellCore/ControlPanel.swift | 5 +++-- src/gpt_voicecoding/core/bridge.py | 7 ++++--- src/gpt_voicecoding/core/clock.py | 18 ++++++++++-------- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/shell/Sources/ShellCore/ControlPanel.swift b/shell/Sources/ShellCore/ControlPanel.swift index 2d4430d..64009d5 100644 --- a/shell/Sources/ShellCore/ControlPanel.swift +++ b/shell/Sources/ShellCore/ControlPanel.swift @@ -80,8 +80,9 @@ public struct LiveReading: Equatable, Sendable { /// /// It holds no policy and no state of its own. Every value it shows is read from /// Bridge Core over the same JSON-over-UDS control plane every other surface -/// speaks, and every action it offers is one of the nine — there is no private -/// protocol here, and no second path to anything. +/// speaks, and every action it offers is one the control plane already +/// publishes — there is no private protocol here, and no second path to +/// anything. /// /// It reads on demand: when the dropdown opens, while it stays open, and after /// every action. No background timer — a poll nobody is reading is a permanent diff --git a/src/gpt_voicecoding/core/bridge.py b/src/gpt_voicecoding/core/bridge.py index 0ae18a6..e1fd210 100644 --- a/src/gpt_voicecoding/core/bridge.py +++ b/src/gpt_voicecoding/core/bridge.py @@ -223,9 +223,10 @@ def __init__( #: Empty when this hub generated none, and the interlock refuses to open #: a call on an empty one rather than this being checked at each caller. self._voice_instructions = self._instructions.voice.text if self._instructions else "" - #: Durations are measured with `clock`; anything written to disk is - #: stamped with `stamp`. A Session's `registered_at` is read back by the - #: next engine, and a monotonic reading would come back as the future. + #: Durations are measured with `clock`; anything read outside this + #: process is stamped with `stamp`. A Session's `first_seen` travels to + #: every surface in the `sessions` payload, and a monotonic reading + #: would name no moment on the far side. self._stamp = stamp self.interlock = CallInterlock(call) diff --git a/src/gpt_voicecoding/core/clock.py b/src/gpt_voicecoding/core/clock.py index f38b067..90ad04d 100644 --- a/src/gpt_voicecoding/core/clock.py +++ b/src/gpt_voicecoding/core/clock.py @@ -10,16 +10,18 @@ because the system clock stepped, and a laptop that sleeps and wakes must not report a queued Relay as ten minutes stale when it was thirty seconds. -**Nothing durable may be stamped from this clock.** A monotonic reading means -nothing after a restart, and the durable subset — switch state and the Session -registry — outlives the process. Those timestamps come from the surface that -records them; this clock measures durations inside one engine run. +**Nothing that will be read outside this process may be stamped from this +clock.** A monotonic reading is an offset from an origin only this process +knows, so it survives neither a restart nor the trip across the control plane, +and on the far side it names no moment at all. This clock measures durations +inside one engine run and answers no question asked from outside it. So there are two, and they are never interchangeable: `default_clock` measures -elapsed time inside one run, and `wall_clock` stamps a record that outlives the -run. A Session's `registered_at` is written to disk and read back by the next -engine, so it is stamped from the second — a monotonic reading there would come -back after a restart as a moment in the future. +elapsed time inside one run, and `wall_clock` stamps a fact read outside it. +A Session's `first_seen` is stamped from the second: the roster is not +written to disk (#74), but every row of it travels to every surface in the +`sessions` payload, and `first_seen` is the one field on that row this engine +authored rather than observed. """ from __future__ import annotations