Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions ALIVENESS_WORKPLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Aliveness Workplan

Status: living work ledger for the August 2026 aliveness audit
Baseline audited: `99ff6010` (main, 2026-08-13)
Working branch: `agent/aliveness-tier1-tier2`

This document tracks the defects and improvements identified by the 2026-08-13 full-repo
aliveness audit, their fix status, and their evidence status. It follows the repository
evidence discipline: **"Done in source" never implies physical qualification.** Any row that
changes firmware behavior remains physically unqualified until the exact flashed SHA-256
passes its own gates.

Status legend:

- `todo` — not started.
- `in-progress` — being edited on the working branch.
- `done-source` — implemented and passing native/host tests; not physically qualified.
- `qualified` — exact-image physical evidence recorded (owner-run; out of scope for this branch).
- `blocked` — cannot proceed; blocker named in Notes.

## Tier 1 — Firmware aliveness fixes (source-only, native-testable)

| ID | Task | Status | Notes |
| --- | --- | --- | --- |
| AL-01 | Fix dropped persona face channels: `FaceAnimator::samplePose` must compose `faceX`/`faceY`, mouth width/corner deltas, lid tilts, and eye corners from the incoming `RobotFrame` instead of discarding them (`src/face/FaceAnimator.cpp:251-263`, `src/face/ProceduralFace.cpp:45`). Unify on one `BreathRhythm` so face and body share one breath. Add a composed-path native test. | done-source | Restores IdleLife breath translation, yawn faceY, GazeTracker face shifts, and sound-orientation faceX to the rendered face. |
| AL-02 | Remove `ActuationEngine` idle sine sway (`src/motion/ActuationEngine.cpp:201-205`) which re-adds the metronomic motion `IntentEngine` explicitly removed; jitter the fixed 14.3 s `IdleLife` gaze-drift sine (`src/persona/IdleLife.cpp:51-56`). Also deletes the dead `src/motion/Blink.hpp`/`Saccade.hpp` duplicates and the now-unused `STACKCHAN_SERVO_IDLE_SCALE` flag. | done-source | HeadGaze look-and-hold remains the only idle head-motion source. |
| AL-03 | Seed `FaceAnimator::rng_` (fixed `0x51A7C0DE`) and the `IdleLife`/`BreathRhythm`/`HeadGaze` hash streams from hardware entropy at boot so each power-on plays a different idle sequence. Keep deterministic seeding available for native tests. | done-source | Entropy injected at construction/begin; native tests pass fixed seeds. |
| AL-04 | Persist `EmotionModel` long-timescale state (baseline temperament, habituation familiarity) to NVS with a bounded slow write cadence; restore on boot. Fix the unreachable natural-wake condition (`quietSeconds_` pins `sleepPressure()` at 1.0 while asleep, so `fatigue < 0.35` can never occur). | done-source | Temperament now survives power cycles; sleep can end naturally. |
| AL-05 | Make `applyCircadian`/`applyAmbient` dt-scaled and idempotent per phase change instead of unbounded impulses per received message (`src/persona/EmotionModel.cpp:250,280`); remove the double-application path in `main.cpp:9527-9532`. | done-source | Prerequisite for any real clock/ALS circadian source. |

## Tier 2 — Bridge character fixes (host-side)

| ID | Task | Status | Notes |
| --- | --- | --- | --- |
| AL-06 | Remove the `[0,1]` valence clamp on the firmware response-start frame (`bridge/lan_service.py:2932`) so face valence matches TTS valence (`[-1,1]`). Completes the open half of AFFECT-001. | done-source | Concerned voice no longer paired with neutral face. |
| AL-07 | Make `pip` and `bolt` real characters: distinct traits/prompt rules, remove the inherited "answer only: I am Stackchan Spark" line (`personas/pip/character.yaml:68`, `personas/bolt/character.yaml:68`). Harden `scaffold_persona_pack` to refuse emitting prompt rules that name the source persona. | done-source | Also verifies Glow retains the Spark safety rules it silently dropped. |
| AL-08 | Move the hardcoded Spark-only conversation style (`SPARK_CONVERSATION_STYLE`, `bridge/character_harness.py:820-821`) into per-pack YAML so every persona gets a style palette; stop loading `DEFAULT_PERSONA` at module import. | done-source | Personas other than Spark are no longer structurally blander. |
| AL-09 | Give failures a voice: model/TTS failure paths speak one short in-character line instead of returning silence (`bridge/lan_service.py:3543`, `3726-3731`, `3905-3906`). TTS-misconfigured no longer reports a fully successful silent turn. | done-source | Failure lines routed through the persona spoken-line table. |
| AL-10 | Persist bounded affect across sessions: mood baseline and rapport in a dedicated `affect_state.json` beside the memory file (`bridge/affect_state.py`), injected as one coarse host-derived prompt line. Deliberately **not** in `BridgeMemory`: `MEMORY_CONTRACT.md` gates new memory-schema work behind the AUDIT-03 repairs, and this state carries no user data. | done-source | Hard bands mirror the firmware temperament bands; corrupt files clamp to neutral; rapport relaxes over idle days. |
| AL-11 | Initiative fixes: pass the relationship card and recent-context lines into `run_initiative` (`bridge/lan_service.py:2759-2760`) and open a bounded reply window (`conversation.wake()`) after a proactive line so the user can answer without re-waking. | done-source | A robot that speaks first can now hear the answer. |
| AL-12 | Vary character beats: the `sha256 % 16` quip selection now mixes a per-process rotation salt (`STACKCHAN_BEAT_ROTATION_SALT` overrides for deterministic runs), so the same question after a bridge restart draws a different quip. | done-source | Within-session anti-repetition unchanged; cross-session repetition broken by the salt. |

## Tier 3 — Documentation truth sync

| ID | Task | Status | Notes |
| --- | --- | --- | --- |
| AL-13 | Update stale P0 rows for fixes already merged on main: demo-mode default (PR #230), capture lease 13.5 s (PR #226), dashboard stale readiness (PR #222) in `EXPERIENCE_SCORECARD.md`, `TASK_LEDGER.md`, `CURRENT_CAPABILITY_AUDIT.md`, `CONTINUITY_GAP_ANALYSIS.md`, `PROJECT_STATE.md`, `docs/BRIDGE_AI_HANDOFF.md`, `docs/CONVERSATION_V2_ROADMAP.md`. | done-source | Genuinely-open P0s (valence clamp, F3 vision, F1 error paths) now stand out. |
| AL-14 | Record this workplan's changes in the ledgers without claiming physical evidence. | done-source | This file is the tracking source of truth for the audit follow-up. |

## Explicitly out of scope for this branch

- Flashing any image, OTA, soak, or physical qualification (owner-run; see
`docs/ARRIVAL_DAY_RUNBOOK.md`). All firmware rows above stop at `done-source`.
- F3 vision bring-up (requires flashing `stackchan_release_forensics_vision`).
- F1 error-path physical qualification (`host-response-wire-clean` report).
- Conversation v2 promotion, PERCEPT/IDENT/MOTION preregistered tasks.
- The Continuity Core typed journal (Milestone 2) — design docs remain normative-only.

## Audit findings intentionally left open (tracked, not fixed here)

| Finding | Why deferred |
| --- | --- |
| `lan_service.py` god module / ~800-line `_run_utterance_end` | Structural refactor; high regression risk near unqualified Conversation v2 paths. |
| Pure-Python reply-PCM speech gate cost | Optimization; needs latency evidence before/after. |
| Per-turn persona pack reload from disk | Optimization; cache invalidation policy needs design. |
| Two parallel TTS paths in `lan_service.py` | Consolidation belongs with the F1 error-path work. |
| Frozen-dataclass mutation via `object.__setattr__` in `bridge_memory.py` | Belongs in the Memory v5 schema follow-up after AL-10 lands. |
| Servo 2 Hz release resampling and duty freeze | Power/actuator policy decision; owner call, needs hardware evidence. |
| Boredom/curiosity drive state | New behavior, requires preregistration per `TASK_LEDGER.md` discipline. |
24 changes: 20 additions & 4 deletions CONTINUITY_GAP_ANALYSIS.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ projections rather than one typed, source-monitored model.
| Concern | Current owner/mechanism | Useful property | Continuity limit |
| --- | --- | --- | --- |
| Body/face/actuator safety | Deterministic firmware coordinators | Bounded authority, 50 ms display gate, graceful local behavior | Host intent and observed completion are not one typed outcome chain |
| Affect/energy | Firmware `IntentEngine`, `EmotionModel`, `EmbodiedEnergy` | Stateful decay, habituation, hysteresis, multimodal influence | Demo events default on; state resets; host sees a lossy subset |
| Conversation phase | Host `ConversationSession` plus firmware wake/reply/audio paths | Bounded context, cancellation, authoritative successful playback | Error/timeout terminal states and time ceilings can diverge |
| Affect/energy | Firmware `IntentEngine`, `EmotionModel`, `EmbodiedEnergy` | Stateful decay, habituation, hysteresis, multimodal influence | Demo events default on (fixed in source at `45032a43`, PR #230); state resets; host sees a lossy subset |
| Conversation phase | Host `ConversationSession` plus firmware wake/reply/audio paths | Bounded context, cancellation, authoritative successful playback | Error/timeout terminal states and time ceilings can diverge (capture/endpoint ceilings aligned in source at `8e76b865`, PR #226; terminal-state divergence remains) |
| Durable facts/episodes/open loops | Memory v4 host store | Bounded atomic persistence, expiry, explicit routes | Model actions not solely authorized; incomplete provenance/contradiction/scope |
| Presence/gaze/room | Firmware camera adapter, vision/room host summaries | Raw-media restraint, typed/bounded summaries, gaze decay | Freshness/provenance disagree and false/stale presence reaches consumers |
| Initiative | Host curiosity threshold | Strong minimum interval and several restraint gates | Not an agenda; no why-now/value/silence evidence; in-flight revalidation gap |
| Product state | Dashboard cached debug/runtime health | Useful local visibility and guarded motion actions | Historical state can be presented as current connection/readiness |
| Product state | Dashboard cached debug/runtime health | Useful local visibility and guarded motion actions | Historical state can be presented as current connection/readiness (fixed in source at `7fd8e0a3`, PR #222) |

The central gap is not lack of more model intelligence. It is the absence of one typed causal chain
from event, through source/freshness/state/decision, to observed outcome and safe consolidation.
Expand Down Expand Up @@ -49,12 +49,21 @@ Required bridge: source-specific `observed_at`/`expires_at`, boot identity, curr
unknown semantics, contradiction preservation, and one freshness-aware social/connection
projection. Last-known data remains available but cannot satisfy a current claim.

Update 2026-08-13: the dashboard resurrection path specifically is fixed in source at `7fd8e0a3`
(PR #222) — sustained heartbeat silence now overrides the latched connection sources; physically
unqualified. The remaining freshness sources stand as written.

## Gap 3 — Conversation Has Split Terminal Truth

Successful playback completion is well bounded, but playback failure can leave the host speaking
forever. Model/TTS recovery changes host state without opening the corresponding firmware reply
window, and host capture commitment ends before firmware's utterance ceiling.

Update 2026-08-13: the capture-commitment mismatch is fixed in source at `8e76b865` (PR #226):
`capture_commit_ms` is decoupled from the reply window at 13,500 ms, validated between 12,000 and
14,500 ms. The playback-failure and reply-window terminal defects remain open, and the change is
physically unqualified.

Required bridge: one explicit host/device terminal-event contract with bounded speaking timeout,
playback-failure propagation, truthful reply-window acknowledgement, aligned 12/13/15-second
ceilings, rollover-safe timing, and outcome events. This is Milestone 1 work, not a Continuity Core
Expand All @@ -78,6 +87,11 @@ Synthetic demo events enabled by default contaminate that history. Negative vale
production streaming path, host context omits baseline/habituation/quiet/sleep variables, and
reboot resets all affect.

Update 2026-08-13: the demo default is off in source at `45032a43` (PR #230, compile-time
`STACKCHAN_DEMO_ENABLED_AT_BOOT` defaulting 0) and the streaming valence clamp is signed [-1, 1]
at `482c3ab5`. Both are physically unqualified; the restart reset and host-context omissions
remain.

Required bridge: make production demo off and preserve signed affect first. Specify authoritative
self-state, source, decay, restart semantics, and cross-modal compatibility before persisting any
temperament. Never persist transient error/fear/stale body state or claim subjective feeling.
Expand Down Expand Up @@ -168,7 +182,9 @@ repository, reproducibility, and documentation work then completes before Milest
first, then separately compile-disable unauthenticated firmware mutation while preserving
emergency stop/read-only status.
2. Repair other P0 truth/privacy violations with small contracts: memory delta authorization,
truthful presence/social freshness, production demo default, and signed affect.
truthful presence/social freshness, production demo default, and signed affect. (Update
2026-08-13: the demo default and signed affect are fixed in source at `45032a43`/PR #230 and
`482c3ab5`; physically unqualified.)
3. Complete Milestone 0 reproducible-build and document-truth work without changing robot behavior.
4. Close and physically qualify Conversation v2 terminal behavior as Milestone 1.
5. Implement the typed event journal/reducers/projections in Milestone 2 shadow mode only.
Expand Down
25 changes: 24 additions & 1 deletion CURRENT_CAPABILITY_AUDIT.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ Three source-reproduced P0 trust defects block natural-conversation closure:
3. the host's 10-second capture commitment can time out before firmware's 12-second endpoint and
reject a valid utterance ending at 12 seconds.

Update 2026-08-13: item 3 is fixed in source at `8e76b865` (PR #226): the host capture commitment
is decoupled from the reply window as its own `capture_commit_ms`, defaulting to 13,500 ms and
validated to sit above the firmware's 12,000 ms endpoint ceiling and at or below the host's
14,500 ms absolute capture lease. Items 1 and 2 remain open, and the change is physically
unqualified.

The firmware wake gate also uses rollover-unsafe raw millisecond comparisons. Multi-party privacy
suppression is useful but there is no qualified speaker attribution, addressed-to-robot gate, or
two-voice arbitration.
Expand Down Expand Up @@ -109,6 +115,12 @@ Phrase streaming clamps response-start valence to `[0,1]`; a `-0.72` concern val
as `0.0` while TTS retained `-0.72`. Cross-field validation also accepted happy text/earcon with
safety mode and contradictory arousal/valence.

Update 2026-08-13: both grounding defects are fixed in source. `45032a43` (PR #230) makes the boot
default compile-time `STACKCHAN_DEMO_ENABLED_AT_BOOT`, defaulting off, with serial `demo on`
remaining an explicit bench opt-in; `482c3ab5` sends response-start valence signed and clamped to
[-1, 1] instead of [0, 1]. Both are source changes only and physically unqualified. The cross-field
validation and lexical relationship-safety gaps remain open.

Relationship safety is prompt-backed but lexically enforced: four clear guilt/exclusivity/
discouraging-human-contact paraphrases passed unchanged. Affect resets at reboot; no durable
temperament contract exists, and current-main integrated physical affect is unqualified.
Expand All @@ -130,7 +142,8 @@ Separately, prompt room text expires but the relationship-card consumer reads an
summary. A stale one-person state can continue allowing preferred name, episodes, callbacks, and
approved facts after the social setting becomes unknown.

Other gaps include cached debug resurrecting dashboard connected/operational state, room summaries
Other gaps include cached debug resurrecting dashboard connected/operational state (fixed in
source at `7fd8e0a3`, PR #222; physically unqualified), room summaries
without source/confidence/contradiction, source-overwriting/double-counted transitions, indefinitely
valid target diagnostics after worker loss, inconsistent private-address/redirect policy between
camera clients, and privacy documentation that incorrectly says release camera endpoints are
Expand Down Expand Up @@ -197,6 +210,12 @@ stopped when only `motion_enabled=false` while rail/torque remain true, and it c
Ready/operational from stale cached debug after failed refresh. Unknown thermal telemetry is also
rendered as clear.

Update 2026-08-13: the stale connectivity/readiness half is fixed in source at `7fd8e0a3`
(PR #222): sustained heartbeat silence beyond 30 seconds now overrides the latched socket flag and
cached `_debug` snapshot and blanks the reported mode; a single missed or late sample is never
classified as failure. The motion-safety and thermal label defects remain open, and the fix is
physically unqualified.

Desktop companion renders forget/remove/Wi-Fi management controls with default no-op callbacks,
omits registry state, silently discards many operation failures, and retains phone-specific setup
copy. The overall flow remains a lab bring-up: launcher defaults to one robot IP, normal operation
Expand Down Expand Up @@ -276,5 +295,9 @@ The highest-risk findings are coupled even though their fixes should remain smal
- initiative can begin under one state and continue after a later safety/sleep transition because
production heartbeat and cancellation contracts are incomplete.

Update 2026-08-13: the demo-affect default (`45032a43`, PR #230), the signed-valence loss
(`482c3ab5`), and the stale dashboard connectivity latching (`7fd8e0a3`, PR #222) are fixed in
source; all remain physically unqualified, and the other links stand as written.

These chains support building typed provenance/freshness/authority shadow projections, but they do
not authorize a broad Continuity Core behavior switchover.
Loading