docs(telemetry): ACTIVITY D1+D2 — the route comments claimed a convergence the fix removed

dev50-guard HOLD on 612495510, comment-only. Behavior unchanged: zero
non-comment lines differ.

The sessions-route comment added by this atom said the shared observation meant
ACTIVITY and TERMINAL "can no longer disagree about whether a seat is producing
output". That was true of the first candidate and FALSE the moment read-time
aging landed: ACTIVITY re-ages the raw `lastActivityAt` against the request
clock while TERMINAL projects the `isActiveWithinWindow` computed at poll time.
When a tmux read has been failing, `pollSeat` leaves the last record in place,
so the cached boolean can stay `true` after the pane went quiet — TERMINAL keeps
reporting that stale `true` and ACTIVITY refuses it.

That divergence is the stale-cache protection working. Only one of the two
surfaces makes an affirmative liveness claim a reader acts on, and it is the one
that re-checks. The comment now says so, so the next reader does not "reconcile"
the gap and delete the protection.

The graph-route comment is corrected on the same pass rather than left for a
third round: sharing the observation does not collapse the slice-15
non-inference contract (which is between `terminalActive` and `hasAssignedWork`
— ACTIVITY still reads no queue state), and it points at the sessions route for
why the two surfaces may differ.

This is the third time in this atom that behavior moved and adjacent prose kept
asserting the old property. A stale comment claiming a guarantee that no longer
holds is worse than no comment: it is a false claim the next reader will rely on,
and here it invited exactly the change that would undo the fix.

Gate 15/15. tsc 0. seat-activity, structural-signal, healthz-wedge,
attach-terminal-activity, ps-projection, startup-wiring: 6 files, 113 passed.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
v-openrig-buildandClaude Opus 5 committed 2026-08-11 05:30:59 +00:00
1 parent 6124955107
commit 69d2a5e904
2 files changed
+16 -4

No files matched your search

+7 -2
View File
@@ -324,8 +324,13 @@ rigsRoutes.get("/:id/graph", async (c) => {
const graphFull = c.req.query("full") === "true";
const seatStructuralActivityService = c.get("seatStructuralActivityService" as never) as SeatStructuralActivityService | undefined;
// ACTIVITY D1+D2 — resolved BEFORE attachAgentActivity now, because the ACTIVITY ladder reads the
// same motion observation the TERMINAL column reads. Order matters only for this declaration; the
// two enrichments still read their own sources independently.
// same motion observation the TERMINAL column reads. Order matters only for this declaration.
//
// Sharing that observation does NOT collapse the slice-15 non-inference contract, which is between
// `terminalActive` and `hasAssignedWork` — ACTIVITY still reads no queue/assignment state. And the
// two surfaces can legitimately disagree: ACTIVITY re-ages the raw timestamp at read time while
// TERMINAL projects the poll-time boolean (see the sessions route for why that gap is the
// stale-cache protection rather than an inconsistency).
const seatActivityService = c.get("seatActivityService" as never) as SeatActivityService | undefined;
const inventoryWithActivityOnly = tmuxAdapter
? await attachAgentActivity(inventory, { tmuxAdapter, activityStore: agentActivityStore, structuralActivity: seatStructuralActivityService, seatActivity: seatActivityService, captureFallback: graphFull })
+9 -2
View File
@@ -123,8 +123,15 @@ nodesRoutes.get("/", async (c) => {
activityStore: deps.agentActivityStore,
structuralActivity: deps.seatStructuralActivityService,
// ACTIVITY D1+D2 — the SAME SeatActivityService instance `attachTerminalActivityAndWork` reads
// just below. One observation, now serving both the TERMINAL column and the ACTIVITY verdict,
// so the two columns can no longer disagree about whether a seat is producing output.
// just below. One observation now feeds both the TERMINAL column and the ACTIVITY verdict.
//
// They can still DISAGREE, deliberately: TERMINAL projects the cached `isActiveWithinWindow`
// computed at POLL time, while ACTIVITY re-ages the raw `lastActivityAt` against the REQUEST
// clock. When the tmux read has been failing, `pollSeat` leaves the last record in place, so the
// cached boolean can stay `true` long after the pane went quiet — TERMINAL keeps reporting that
// stale `true` and ACTIVITY refuses it. That divergence IS the stale-cache protection working,
// not a bug to reconcile: only one of these two surfaces makes an affirmative liveness claim
// that a reader will act on, and it is the one that re-checks.
seatActivity: deps.seatActivityService,
captureFallback: full,
});