Version. 0.1
Date. 2026-06-09
Status. Implementation notes. A record-resident write-up of what Phase 60 shipped — the tune_setting capability, the first instance of the Companion-as-Operator-system-interface principle. Phase 60 closed mid-May (Operator-Layer tags phase-60-close-v0_1, phase-60-recovery-v0_1, 2026-05-16) without producing this artifact; the manifest flagged the absence as identified-but-not-actioned. This note closes that gap, matching the implementation-notes pattern Phases 61–64 already follow. Descriptive of built behaviour; the one interim shape is named as interim. Operator-facing summary at top; technical detail below. Markdown primary, HTML companion.
Author posture. Descriptive — records what shipped, grounded against engine a2d760b and Operator Layer f1d8fd1. Where the built shape is known to be interim (the non-conversation-intent gate), the interim status and the intended destination are recorded, not smoothed.
Relates to. The Companion-as-Operator-system-interface standing note v0.1 (the durable principle this is the first instance of); architecture specification §08 (where the principle is named); the Companion functional specification v0.1 (the optional-access-layer framing this respects).
Phase 60 shipped the first piece of a larger idea: that the Companion — the conversation — is how the Operator adjusts the system, not just how they do the work. Before Phase 60, changing a setting meant finding it in a settings screen. After Phase 60, the Operator can say "make the wait time shorter" or "show oldest messages first" and the Companion changes the setting, confirms the new value, and the surface updates in the same breath.
What actually shipped is tune_setting — a Companion intent that adjusts three settings by conversation: the voice-listening blur, the voice-listening wait time, and the conversation message order. It's deliberately small — three settings — because the point of Phase 60 was to prove the pattern, not to move every setting into conversation at once. Adding a fourth setting later is a small, well-defined change.
Two things in the build are worth knowing. First, a setting can be changed two ways — by asking the Companion, or by a direct control — and both are recorded the same way, so the history of "what changed and when" is complete regardless of how the change was made. Second, a "tune the setting" exchange is deliberately not saved as part of the conversation: it's an adjustment to how the surface behaves, not something said, so it doesn't clutter the conversation history. That second choice is an interim shape with a known better destination, recorded below.
Phase 60 is Companion-as-Operator-system-interface: the principle that the Companion is the primary surface for all Operator-system interaction — preferences, configuration, policy — not only the conversational work of an engagement. tune_setting is its first shipped instance. The durable principle has its own standing note (v0.1); these notes record the build that first instantiated it.
(A naming correction, recorded for the trail: an earlier label called this work "Upload pathway v1," which was wrong — it keyed off a since-deleted branch name. The manifest carries the correction. Phase 60 is Companion-as-interface; tune_setting is its first instance.)
tune_setting pipelineA tune request flows classify → route → execute → write → confirm:
setting_label (what to change) and a direction (how — more/less/reset, an enum value, or a verbatim number)._route_tune_setting calls execute_tune_setting, which resolves the label to a setting key via _LABEL_TO_KEY, reads the current value, and dispatches by the setting's shape:conversation.message_order (newest_first / oldest_first).preferences/person_settings.set_setting, which validates, clamps, and upserts into person_settings(person_id, setting_key, setting_value, updated_at), keyed by a dotted namespace. The DB boundary refuses bad writes: UnknownSettingError / InvalidSettingValueError return a structured refusal rather than a silent failure.operation_data["action"] — one of tuned, reset, no_change, unknown_setting, unknown_direction, error. The responder template renders it into a reply that names the new value. Naming the value is a deliberate trust discipline: "Done" alone is refused by the template — the Operator must be told what the setting now is, so they can trust the change landed as intended.event_kind="setting_change") records the previous→new transition. It is best-effort — a failure to audit is swallowed, and the setting write stays authoritative (the audit is a record of the change, not a gate on it).
The complete current set (KNOWN_SETTINGS in person_settings.py):
| key | type | default | bounds | conversation labels |
|---|---|---|---|---|
| voice.listening.blur_intensity | float | 0.6 | [0.0, 1.0] | "blur", "blur intensity", "voice blur", "listening blur" |
| voice.listening.silence_submit_seconds | float | 2.5 | [0.5, 10.0] | "wait time", "wait", "pause", "silence", "silence threshold", "silence submit" |
| conversation.message_order | enum | newest_first | {newest_first, oldest_first} | "message order", "conversation order", "order" |
This is the whole tunable surface. The manifest's shorthand ("backdrop blur and voice-listening thresholds") was two of the three; message_order is the third. The three-setting scope is intentional — Phase 60 proves the pattern, not exhaustive coverage.
The extension pattern. Adding a new tunable setting is a single, well-defined change in three places: a _LABEL_TO_KEY branch (the labels that name it in conversation), a KNOWN_SETTINGS entry (its type, default, bounds), and a frontend apply branch (how the surface reflects it). This is what makes the principle generalize cheaply — the cost of moving a setting into conversation is one branch, not a feature.
A setting can be changed two ways, and both are first-class:
tune_setting, by conversation.PUT /me/settings/{key}, a direct affordance (a control the Operator operates).
write_setting_change_event audits both — the FORAY trail records the "Companion-said path" and the "button-click path" alike. So the history of what changed and when is complete regardless of which path made the change. This matters for the Companion-as-interface principle: conversation is a path to system settings, not the only path — consistent with the optional-access-layer framing (the Companion makes the API pleasant; it does not become the sole door to it).
tune_setting is the sole member of NON_CONVERSATION_INTENTS. When a turn classifies as tune_setting, neither the Operator turn nor the Companion turn is recorded as conversation — record_turn is skipped, and the Companion turn stays null.
Why. A tune exchange produces metadata about how the surface renders, not conversation content. Persisting it would clutter the conversation history and replay the same "tune chatter" on every reload. So it is deliberately excluded from the recorded conversation.
Why this is interim, not finished. Skipping the turn has a real consequence the in-code note records: there is no companion_turn.id to anchor consumption recording against, so the token cost of a tune turn is "swallowed under the interim shape." The intended destination (named in the code as "option iii," not yet built) is a proper handling: an SSE bus carrying the surface change, the FORAY audit (already present) as the durable record, and a transient surface confirmation — rather than a skipped turn. The current skip is the interim gate that keeps tune chatter out of history until that fuller shape is built. These notes record it as interim so a later reader does not mistake the skip for the finished design.
The surface reflects the substrate write in the same render the Companion's reply lands:
setting_changes entry, _applySettingChange (CenterPane) switches on the setting key and updates local surface state immediately. This is robust against classifier false positives: only an actual handler write emits a setting_changes entry (the router populates it only on a real tuned/reset action), so a misclassified utterance carries an empty list and the surface stays put.classified_intent is in NON_CONVERSATION_INTENTS, the surface drops the optimistic Operator turn and skips appending a Companion turn — mirroring the substrate's record_turn skip. The Companion's confirmation is the surface change applied above, not a chat message. (Substrate skip and frontend drop are deliberately kept in mirror — if one changed without the other, a tune turn would either ghost in the transcript or fail to apply.)conversation.message_order is owned by CenterPane (it reorders the transcript there). The two voice.listening.* settings are owned by the engagement-navigation voice surface (the voice-listening panel and its hook) — the blur translucency and the silence-submit timing take effect there, not in CenterPane. So a tune turn's effect lands on whichever surface owns the setting, which is why the optimistic apply switches on the key.
Built and shipped (Phase 60, closed 2026-05-16, Operator-Layer tags phase-60-close-v0_1 / phase-60-recovery-v0_1): the tune_setting pipeline, the three-setting registry with enum/numeric dispatch, the dual write path with FORAY audit on both, the responder name-the-value discipline, the frontend optimistic-apply/turn-drop with the surface-ownership split.
Interim, with a known destination: the non-conversation-intent gate (§5) — a skip that keeps tune chatter out of history, with the consumption-recording consequence noted, pending the fuller "option iii" shape (SSE + FORAY + transient confirmation). This is the one part of Phase 60 that is provisional by design.
The principle this instantiates is carried forward in the Companion-as-Operator-system-interface standing note v0.1, which states what Phase 60 first proved and what it commits future work to.
DUNIN7 — Done In Seven LLC — Miami, Florida Loomworks — Phase 60 implementation notes — v0.1 — 2026-06-09