# Agent Navigator 0.6b

Base: stable `main` / annotated `v0.6.0` at `38da0adf8c009498a28e779f20749e5a839b8ff8`.
Version: `0.6.1`. Complete software gates and targeted physical acceptance confirmed on 2026-10-05; ready for fast-forward promotion as the DAILY-USABLE BASELINE.

Settings → Agent exposes Session, Model, native Effort, native Permissions, local Voice Send, frozen Speech, and Back according to negotiated capabilities. `openAgentSessionPicker()` is the only Session entry. Double B, Touch, workspace discovery/path management, and timezone configuration remain deferred.

## Device preferences and Voice

The explicit NVS codec is v4, with dual slots, generation and CRC. v1/v2/v3 migration defaults to Confirm; unknown future versions remain read-only. Voice Send is local to the device and persists independently of the selected Agent. Confirm requires A SEND (A START for a first prompt); Direct invokes the same existing one-shot `voice_decision(send)` only after a valid transcript. Identity, connection, target generation, approval preemption and native request validity remain enforced.

Duration starts after capture startup tone, DMA drains and successful START queueing, immediately before reading PCM. 999 ms and 1000 ms cancel capture, send `voice_cancel`, discard uploaded PCM and transcript, and never call STT or Agent input. 1001 ms follows normal transcription. Too-short feedback lasts 1500 ms and returns automatically; native input / first-message flow returns to its prior Navigator page. Secret/password/token/credential input never enters cloud STT.

## Catalog and target selection

Only canonical paths already registered in ProjectRegistry are eligible; paths are never offered in picker frames. Session identities are `(project_id, agent, session_id)`, with names for presentation only. Pi and Codex sessions are merged by `updated_at DESC`. Catalog and creation-model pages contain at most four items, remain below 4096 bytes, use connection-owned snapshots with a 60-second TTL, and have validated cursors. Adapter failure is Partial/Adapter unavailable, distinct from Empty. Device catalog/choices use fixed arrays; no unbounded session list is retained on ESP32.

TargetStore migrates legacy values to durable target/project/generation records. It validates expected generation, increments even for A→B→A, writes/fsyncs/replaces/fsyncs the directory before acknowledgement, and fails closed on corruption. A successful switch delivers `target_selected` and an authoritative full Agent snapshot under one send lock. Stale responses cannot switch the device optimistically. Lost acknowledgement is recovered by reading the persisted target.

Capabilities: `catalog`, `target-select`, `permissions`, `native-interaction`, `session-create`. Old firmware retains baseline protocols. New firmware hides unsupported controls when connected to an old Gateway. Legacy binary Reject maps to native cancel only when decline is absent and cancel was actually offered.

## Native settings and interaction

Installed versions verified on Lighthouse: Codex 0.154.0 generated experimental JSON schema; official Pi SDK 0.85.1. Codex reviewer modes map exactly to native `user` and `auto_review`. Permissions use `thread/resume` without overrides for authoritative read and `thread/settings/update` changing only `approvalsReviewer`, followed by readback. Existing approval policy, sandbox and active permission profile are preserved. Busy sessions reject changes. Pi has no equivalent permission control; it remains Native/read-only.

Codex approvals bridge native requestApproval and its exact `availableDecisions`. Once/session approval, decline and cancel remain distinct. Pi production pager no longer registers a `tool_call` interceptor; its legacy synthetic approval socket is not started. SDK loading excludes old global Device Lab pagers so their removed hook cannot silently return. No tool/command heuristic creates approvals.

Approval and UserInput are separate protocols. Two native choices use A/B; three or more use A NEXT/B SELECT. Codex requestUserInput preserves question IDs, exact choice indices, Other and non-secret free text. Pi official ExtensionUIContext confirm/select/input/editor binds to the same native input controller. Choice display is UTF-8 bounded while the native answer uses the original full option. Abort, timeout, turn completion, session end, resolution elsewhere and connection changes invalidate prior responses. Arbitrary custom Pi UI remains unsupported and requires desktop handling. Existing desktop Pi runtimes must reload their pager after deployment; they are never killed or duplicated to gain control.

## Creation and recovery

Project → Agent → Model → native Effort → native Permissions → first Voice message. No long-lived empty draft is created. Pi calls official SessionManager/createAgentSession SDK APIs; Codex calls native thread/start then turn/start. Model/effort/native permissions and canonical cwd are validated. The operation journal is SQLite with synchronous FULL, keyed by device and operation ID plus an immutable payload digest. UNKNOWN is written before native creation, CREATED with the real native ID before first-input submission, and DONE after accepted submission. Reused IDs with different input fail. UNKNOWN/CREATED after disconnect are queried and inspected, never blindly retried. A native Codex acknowledged identity can bridge its brief asynchronous rollout-file window; it never invents IDs or replays creation.

## Validation and acceptance

Software gates: diff check, wearable host, network resilience, server including TLS WebSocket/Voice smoke, and complete firmware build. Coverage includes real raw-button ownership, NVS migration/reboots, 999/1000/1001 boundaries, Direct once-only send, hundreds of merged sessions, Unicode/duplicate names, snapshots/TTL, removed sessions, Admin race/ABA, persisted target ACK loss, native choice/lifecycle/secret protection, native permissions and first-Voice creation recovery.

Live native evidence: real Codex create + first turn, reviewer user→auto_review→user readback, native requestApproval with offered accept/cancel, and native requestUserInput. Real Pi create + first prompt/model/effort readback and one actual Agent tool invoking confirm/select/input/editor, with four answers and successful native completion. Probe projects are isolated and do not change the production project registry.

The original 0.6b physical checklist covered existing Session switch/full snapshot, native permissions/interaction, Voice modes and short recordings, preference reboot persistence, and first-Voice creation. Earlier scoped observations remain recorded below. The final 0.6.1 gate deliberately uses targeted regression rather than repeating every earlier hardware exercise; acceptance and evidence limits are recorded in the closeout section. Preserve the spike branch while its independent research material has not all been archived or absorbed.

Speech Output: **FROZEN / NOT ACCEPTED**. Firmware does not advertise playback and does not execute inbound speech commands. No TTS, Read Screen, AUTO_REPLY/AUTO_SUMMARY or playback work is part of this candidate.

## Physical feedback: generation-zero snapshot

The first candidate 54e987a failed physical testing: Navigator repeatedly closed into Agent showing Waiting for agent activity. The unreceived-ACK sentinel was zero, equal to the legitimate generation of a migrated legacy target. Each periodic generation-zero snapshot therefore looked like an acknowledged target selection. The fix tracks ACK presence explicitly, validates its request identity/generation, and consumes it exactly once after the matching authoritative snapshot. Regression invokes the actual production JSON handler across Project, Session, Model, Permissions, native-input and Voice owners at generation zero, then tests real ACK consumption and later equal-generation snapshots. The initial FAIL remains recorded; the corrected candidate requires physical retest before merge.

Existing Pi target snapshots also restore recent/final assistant text from official SessionManager.buildSessionContext messages after a Gateway restart, rather than relying exclusively on transient pager overlays. Thinking, prior commentary and tool results are excluded; credentials are redacted before the bounded device presentation. An actually empty session continues to show waiting activity rather than fabricated output.

## Physical log review, 2026-10-05

On 8aca8b8 firmware, the user reported that the corrected navigation appeared to work. Read-only USB serial capture confirmed that repeated same-target snapshots retained Settings, and explicit Session selections delivered existing Pi replies (260 and 1774 bytes). The Gateway's durable journal contains one Pi and one Codex creation in registered chat project `123`, both DONE. The Pi native session is DONE with saved assistant text; Codex native thread/read confirms that its first turn and a subsequent turn completed, each containing one user message. These are scoped physical observations, not acceptance of every remaining gate.

The user also reported that the attempt immediately before successful Codex creation did not work, showed no observed error, and succeeded on immediate retry. That attempt has no UNKNOWN/CREATED journal entry. Historical voice INFO diagnostics were suppressed by Uvicorn's default root WARNING level, so its recording/transcription outcome cannot be determined retrospectively. Voice diagnostics now inherit the production Uvicorn logger and record bounded identities, capture counts, duration, provider HTTP status, safe outcome categories, and input submission phases. Creation exceptions distinguish native creation from target snapshot delivery while preserving the durable journal and no-retry behavior. Logs never include PCM, transcript, credentials, provider response bodies or exception text. Keep testing until the isolated failure and remaining physical gates are resolved.

## Existing-session Last Reply, 0.6.1 candidate

The requested base `8aca8b8` is retained. The actual starting feature HEAD was `8b62fb1`, including the existing Voice diagnostics above. Last Reply changes do not implement a History Browser or add device protocol fields.

Lighthouse's installed `codex-cli 0.154.0` experimental JSON schemas were freshly generated on 2026-10-05. `thread/read` explicitly reads metadata with `includeTurns=false`; selected inactive sessions are enriched through `thread/turns/list` with `sortDirection=desc`, `itemsView=full`, `limit=8`. At most four pages (32 recent turns), within a five-second total timeout, are read. A reply older than that scan budget can remain empty. The most recent completed turn with displayable assistant text wins; within it, the last `agentMessage` with `phase=final_answer` wins, otherwise the last non-commentary `agentMessage` (including absent/null phase). Interrupted, failed, user-only and commentary-only turns do not erase an earlier valid completed reply. Reasoning, tool/command output, file changes and user prompts are never recovered.

The existing `final_text` carries the result; state remains DORMANT/IDLE. RUNNING and native interactions suppress persisted final text. Current DONE/FAILED output wins, including events arriving during the history await. Catalog enumeration does not read history. An LRU cache holds at most 128 session IDs, each with native `updatedAt` and one redacted, UTF-8-safe reply of at most 2048 bytes (`device_final_text`). Matching revision reuses it; changed revision or live turn start/completion invalidates it. Empty and failed reads are cached for that revision, with one bounded category-only warning for failure. Optional history errors preserve selectable metadata. New adapters recover from native persistence without `self.live` or a second history database.

Both firmware render paths now use nonempty `final_text` for DORMANT/IDLE while preserving the state header; the wearable body label is LAST REPLY. Empty sessions retain the existing waiting view.

Targeted automation covers final/fallback/empty/commentary-only, latest invalid turns, bounded pagination, UTF-8/redaction, cache call counts and LRU eviction, native revision refresh, independent adapter restart, authoritative A→B→A snapshots, RUNNING/waiting/terminal precedence, events during recovery, timeout and unsupported response failure. These and existing Navigator/Agent/control tests passed (61 tests). The final 0.6.1 candidate also passed the full wearable, network resilience (88 Python tests), server (189 Python tests, plus Node, firmware harnesses, HTTP/WSS/Voice smoke) and build gates.

Read-only native probes recovered CODEX project `123`, session `01a10bf5-79f7-7733-a01e-40ac1595bd6e`, DORMANT, final reply `已删除天气文件。` (24 UTF-8 bytes). PI project `123`, session `01a10bf2-1216-71c4-8dea-5455c15a3311`, DORMANT, final reply `深圳今天多云，21到27度，挺舒服，出门带件薄外套就行。` (76 bytes). No turn was started or existing session modified by these probes. These are native software observations, not physical acceptance.

## Targeted physical closeout, 2026-10-05

The user accepted the final checklist: Boot, Watch, Agent, existing Pi/Codex replies, Pi↔Codex and A→B→A switching, Voice Confirm, Voice Direct, and Hold A Settings Back. USB logs independently confirm stable `0.6.1` boot and hello, retained NVS generation 7, online reconnect, existing Codex reply (902 bytes) and Pi reply (260 bytes), Settings retained across repeated same-target snapshots, authoritative selection returning to Agent, and a real Direct input progressing to RUNNING with empty final text then DONE with its new reply. Visual content and checklist items outside the capture rely on the user's acceptance; the serial capture alone is not claimed as a complete pixel/UI test.

One Voice attempt failed in the connection path. At 21:24:08 CST STT started and completed successfully at 21:24:10 (1953.3 ms). The device then reported no WebSocket PONG for 20 seconds, cancelled its Voice wait on disconnect, and reconnected; no Agent send was recorded for that attempt. The next attempt completed STT (1832.7 ms), performed one successful input send and received DONE. The user reported the single transient as tolerable network instability and accepted the smoke. This establishes a PONG-timeout transport failure, not an STT provider error; the specific network hop is not established. The failed attempt is retained rather than relabelled PASS, and no unrelated Voice work is added.

The first release artifact at `a5af497` had correct VERSION/ESP app metadata but an overlooked hardcoded `DEVICE_LAB_FIRMWARE_VERSION=0.6.1-dev`. `dafaffd` corrected the macro; all exact-candidate gates were rerun, both binary hashes reverified on Mac, and the app-only flash repeated with NVS preserved. Device boot and Gateway hello now agree on `0.6.1`. Firmware: 3,253,520 bytes, SHA256 `dd161d6932b0f6a8b3f344d2889b2a1548b05b1c70ec0bcfd3ffb28616382dd7`; merged: 3,319,056 bytes, SHA256 `38c530b81ccfb4746df66bd3eefbb1a9ffcc44a5d095c4ed4c6424bcca5aa378`.

The test deployment restarted only device-gateway.service. Existing Codex daemon and Pi runtimes were not restarted. Both agents' replies were recovered through the actual restarted Gateway API and the existing selected target was restored. Main promotion must preserve repo-external credentials/environment, Project Registry, Target Store, Operations DB and speech preferences; production must then reconnect and pass an additional old-Codex selection from main. Speech Output remains FROZEN / NOT INCLUDED. Remaining major features: Double-B, Touch, Speech Output; no further 0.6b features.
