This document owns the current test layers, review evidence, physical acceptance boundary, and release gate.
Several words below are used in a narrower sense than ordinary English, and most are also names in the code or on the wire. GLOSSARY.md gives the plain meaning of each one and where the name appears.
../README.mdandPRODUCT.mdavoid these terms entirely.
Check the generated device contract from the repository root:
python3 tools/protocol_codegen.py --checkCheck the complete asset/scene branch with its owning verifier:
tools/spritekit/venv/bin/python tools/spritekit/verify.pyThat verifier checks the tracked scene header and native parser vector before it discovers or runs any spritekit test.
Check the host bridge from packages/code-chan:
npm ci
npm run typecheck
npm testnpm test uses Node's recursive discovery and its pretest checks both
generated contracts. Test count is not a completion criterion; changed tests
must be audited for their production path, oracle, mocks, and adversarial
meaning.
Check firmware from firmware/stackchan:
pio test -e native
pio run -e cores3-stackchan
pio run -e cores3-stackchan -t buildfsThe asset and scene tests prepare outputs in memory or write only below a temporary directory. They do not refresh tracked vectors, asset build directories, or firmware installation data.
The scene-package generator must also be run without --check before
buildfs or uploadfs, because the generated installation directory is
ignored.
Host checks exercise the real HostBridgeRuntime,
DeviceProtocolSession, ForegroundCoordinator, selected producer adapter,
loopback ingress, and transport boundary. They cover:
- hello, initial snapshot, and operational synchronization before hook service;
- epoch rejection, protocol fault, and transport loss;
- graceful close requiring the exact accepted
goodbye_ackand completed local write, identical retry after a lost receipt, rejection and deadline failure, listener retention through serial cleanup, and listener reacquisition after both successful and failed close; - executable termination that coalesces repeated
SIGINTandSIGTERM, retains both handlers throughout the awaited close, and preserves close failure after removing them; - scheduled synchronous non-blocking serial reads, retry classification, complete line delivery, terminal failure once, and no descriptor access by a scheduled read after close;
- prompt lease ownership, same-turn continuation, simultaneous sessions, and ignored foreign sessions;
- concurrent hook-handler exclusion across prompt admission, coordinator correlation, and device publication;
- main-response Stop closing tool and attention activity and canceling permission while active children, incomplete child delivery, and undelivered background results continue draining;
- producer-bound adapter, device-session, coordinator, event, and response types, with runtime rejection of a mismatched composition;
- Claude-only status-line usage ingress that a Codex bridge refuses, a relay that
fails closed below Claude Code 2.1.196, and an exact bounded canonical loopback
sample — unexpected keys, uncanonical or oversized identifiers, and out-of-range
metrics are rejected as HTTP 400 while a valid but stale sample is a 200 with no
state change; host projection of the bounded
0–100percentages to the canonical prompt identity; and session admission that binds a sample to the current foreground working turn and drops a stale or foreign one; - the opt-in status-line installer: a version preflight that refuses an old or
missing
claudebefore any settings read or write, exact-entry ownership that preserves a foreign or moved-checkout entry, an untracked local-settings target that leaves the tracked file byte-identical, and byte-invariant failure on malformed settings; - canonical device-protocol snapshot invariants declared in
device.jsonand emitted to both codecs from one contract edit, with generic codegen that does not branch on message field names, and field-specific scene alphabets shared by the native parser and the Python builder; - producer-specific terminal evidence, with Codex root/child completion kept separate from Claude Stop, StopFailure, and continuation behavior, and notifications unable to complete either producer;
- Claude background-result paths with both child-before-Stop and Stop-before-child ordering, one later response wakeup, one final outcome, and no state change from an unowned child terminal;
- distinct Codex parent and child turns, exact child start/stop pairs, child-tool non-promotion, duplicate child-turn rejection, and no device answer for Codex or Claude child permissions;
- Codex
Stoproot completion and exactSubagentStopchild completion in the supported non-continuing hook composition, including both arrival orders, duplicate idempotency, and a draining child that a later prompt cannot erase; - Codex user interruption without
StoporSessionEndkeeping the same episode, with a further prompt from that session joining it so its evidence correlates and its terminal event settles it, and with no elapsed-time release on any path; - exclusion of documented Claude child-owned prompt, tool, and notification hooks from parent lifecycle state;
- completed-lineage non-revival and session idle/end release;
- impossible, duplicate, stale, and wrong-turn producer sequences;
- permission admission, timeout, abort, exact device response, and no-answer settlement, including service-queue progress while the physical decision is pending and after abort or expiry;
- Codex documented turn IDs and Claude documented prompt IDs;
- exact codec shapes, limits, duplicate-key rejection, and UTF-8 framing.
Native firmware checks execute the production parsers, wire builders,
DeviceConnection, ExpressionLifecycle, BodyActuationProcess,
BodyMotionProgramProcess, BodyCalibrationProcess, DisplayOutputProcess,
LedOutput, SoundOutput, the board power target, scene package parser,
scene controller, compositor,
layout validator, and touchscreen classifiers. They cover:
- source and epoch exclusion, acknowledged startup, uncertain USB liveness, goodbye receipt replay without effect replay, stale-close exclusion after a replacement owner, fault, and current-owner routing;
- complete snapshot replacement, activity/outcome replay suppression, and permission answerability;
- display initialization and operation deadlines at strict-before, exact, and late boundaries, using the same predicate in result admission and periodic observation;
- generation supersession, stale and duplicate results, wake during suspend, and result-queue failure;
- one boot-to-terminal display owner across the dark boot gate, presenter initialization, calibration frames, normal scene frames, local fault presentation, suspension, and explicit darkness; first-visible ordering is wake, complete frame transfer, then confirmed backlight enable, while every failure and dark path uses the common panel-sleep and confirmed-rail-disable tail;
- calibration display failure before body-output admission performs no body mutation, while the same failure after admission requests exactly one typed body cleanup and preserves the display-specific cause;
- explicit calibration-record provenance and boot selection; compatible
full-envelope validation; state- and region-bounded calibration input;
torque-disabled preparation; fresh stationary pose evidence; a separate
release-gated motion confirmation; invalidation of capture-only record
version 1; production-motion-owner synchronization; exact right, center,
left, and center pose order; persistence only after four live
ControllerSettledoutcomes; exact persistence readback; and cleanup without persistence on load limit, device fault, rejection, unavailable evidence, deadline, persistence failure, and uncertain output disable; - body activation with the rail-enable command confirmed before evidence-driven torque-disable retries, installed two-axis minimum/maximum position-limit and directional-dead-zone acquisition, measured raw pose admission, and exact two-axis hardware goal-register write/read confirmation;
- the production
StackChanBodyMotionowner against an independent scripted servo-bus model: missing, malformed, unordered, and pose-excluding installed limits; directional dead zones outside their documented domain; target rejection outside a confirmed installed range; bounded interpolation; exact final-goal readback; stable controller-stop sampling independent of residual; exact-target feedback remaining pending whilemoving=1; both exact-target and 25-step residual feedback producingControllerSettledafter stablemoving=0samples; retained directed-progress evidence; current/load-backed pitchLoadLimited; non-zero-statusDeviceFault; invalid feedback; and unavailable final-goal or feedback evidence retained across intervening valid samples; - lifecycle consumption of typed actuation outcomes, strict activation and
quiescence deadlines, exact
body_activation_timeout, separate readiness and neutral-presentation results, newer semantic-program supersession, recoverable ordinaryNotPresented, and all-attempt quiescence, including completed versus incomplete disable-command tails; native adversarial cases reject software-only goal acceptance and preserve the implicated axis through the matching bounded local fault-frame projection. Native evidence does not claim the powered interval before torque-disable confirmation is physically motionless; - production application ordering from goodbye admission through connected
expression release, disconnected publication, disconnected semantic-program
admission, and only then
goodbye_ack, plus the calibrated neutral pose's expected raw target; - one production body-actuation caller across runtime and calibration; independent child/lifecycle generations, stale-result exclusion, immediate state-evidence semantic supersession, and rapid working-to-idle-to-turn- outcome replacement; the exact fixed-pitch left/right/center working sequence, controller-settlement-gated center followed immediately by the next sweep's first pose, bounded targets, distinct interactive presentation-fault meaning, and wrap-safe presentation deadlines;
- independent LED and sound hardware writers: expression and outcome replacement, transient cancellation, RGB darkness, observed speaker stop, bounded missing-evidence failure, and wrap-safe presentation scheduling; application composition checks that ordinary sleep requests auxiliary cleanup before body quiescence;
- the production shutdown composition: one stopping status, expression-owned body quiescence and display suspension, adoption of in-flight sleep safety work without duplicate owner commands, no graceful result before both body and display safety evidence, one PMIC call on graceful, child-fault, and deadline paths, first-fault retention, failed-request reporting, and duplicate-hold exclusion;
- permission-control isolation, wake-only touchscreen presses, and body-touch non-authorization;
- exact unversioned scene-package shape, package size, palette and pixel bounds, layout visibility, control separation, background connectors, and render layer order;
- generated scene-catalog freshness and accepted-set parity: every builder limit comes from the package descriptor, while firmware resource identity, kind, playback, timing, and role validation comes from the same tracked scene and asset lineage;
- the exact final manifest emitted by the Python builder, through a tracked generated vector, deserializes with the production firmware parser and passes the production fixed-role validator;
- working caption composition from manifest labels, the
0–9and%glyphs, the bounded worst-case caption, rejection of over-budget usage labels, and the display-only reclassification of a usage-only snapshot change so it refreshes the caption without waking body, servos, LED, or sound; - hook projection idempotence: projecting an already-projected hook returns the same value, whatever the projection reduces. The relay and the bridge both project, so losing this degrades what terminal events prove and turns stop settling. The check exists because that regression was observed on hardware, not as a hypothetical;
- retained-episode expression: a stopped response whose obligations are still outstanding is waiting, shows its manifest caption, carries no usage, keeps its turn identity, plays no cue, and leaves the device free to sleep; a Codex root that finished while its exact child is live reaches the same shared meaning, and a child that starts after the response stopped is admitted rather than faulted.
The board-shutdown composition check uses the real application, connection, expression, body, and display owners and replaces only physical hardware ports. Its oracle requires connected graceful shutdown to combine exact stopping acknowledgement with body and display safety in either arrival order. It also proves that a missing acknowledgement cannot reach PMIC before the aggregate deadline, while stopping-send failure, child fault, and deadline paths each retain their defined one-shot fail-safe result. A target return never proves physical power removal.
The CoreS3 target build proves that target-specific M5Unified, FreeRTOS,
StackChan-BSP, panel, body, and PMIC code compiles together. buildfs proves
the generated package can be assembled into the configured LittleFS image.
Neither command proves a physical effect.
A passing command is evidence only for its exercised boundary. Review must also establish:
- one owner contains each invariant-bearing process;
- adapters and the application loop cannot reorder or bypass that owner;
- stale, duplicate, malformed, late, or cross-owner input cannot reach a side effect;
- time represents a request or failure boundary, never successful completion;
- generated contracts, source, tests, and public documents use the same current vocabulary;
- obsolete classes, pull-style shutdown requests, version readers, aliases, fallback layouts, and migration paths are absent;
- tests use production composition where the invariant crosses components and do not derive their oracle from the implementation under test.
Final software inspection includes git diff --check, contract freshness, the
complete changed-tree review, and a stale-symbol search. The generated native
scene parser vector is tracked contract evidence. Installation output,
dependency directories, .WORK/ material, and device captures remain
untracked.
Compilation and native doubles are not physical acceptance. Hardware acceptance requires one recorded working-tree hash, generated scene hash, firmware binary hash, identified CoreS3, matching filesystem-first installation, and direct observation of the affected display, touchscreen, body touch, servo, LED, sound, USB, and PMIC boundaries.
The device answers on ten messages: hello_ack, goodbye_ack, snapshot_ack,
device_initializing, device_operational, device_stopping, device_fault,
decision, touch, and effect_ack. PROTOCOL.md owns their meaning.
That set establishes what the device was told and that it accepted the telling. It reports no panel-sleep state, no servo position or motion, and nothing about legibility. No amount of host-side driving substitutes for looking: whether the body actually rests, whether the panel actually sleeps, and whether a caption is actually readable are irreducibly visual, and an acceptance run must budget a person for them rather than infer them from an acknowledged snapshot.
State the division before the run, not after. A case whose evidence is an acknowledgement may be recorded from the trace; a case whose evidence is a physical effect is recorded only from observation, and an unobserved case is recorded as unobserved rather than as passed.
The recorded firmware binary is byte-reproducible: the same sources rebuilt at a
different time yield the same firmware.bin, so an unchanged hash after a
rebuild is a reproducibility signal and not evidence of a stale install. The
LittleFS image is not byte-reproducible, so the generated scene content hash,
not the image hash, is the scene's identity in an acceptance record.
Record both, and record what a hash covers. A working-tree hash that moves because documentation changed does not invalidate an installed pair; state the reason the hash moved instead of silently re-pinning it, and state whether an unchanged generated hash was measured again or carried forward by inference from unchanged inputs.
The current integrated source is not physically accepted until all applicable cases below pass from that one installed state:
- From one new firmware installation without a code-chan calibration record,
confirm that the local calibration screen appears without a bridge or
ordinary scene, that the head can be aligned while torque remains disabled,
and that the first confirmation captures but does not store the observed
home after stable live evidence. Clear both hands, press
START SAFE MOTION TEST, and verify that no motor starts before release. Observe the bounded right, center, left, and safe-center sequence without a device fault, load-limit fault, or abrupt motion. Confirm the success screen appears only after the return evidence and reports both outputs disabled, then release the restart touch and boot normally. One complete disconnected prompt with uncorrupted tracked image resources must become visible before ordinary servo motion, body LEDs, sound, body touch, or permission input are enabled. Body activation must reach the interactive neutral pose inside its bound without abrupt or cumulative yaw. - Two consecutive automatic ordinary-suspend and touchscreen-wake cycles and two short-button suspend/wake cycles without a bridge. The disconnected prompt must remain free of hero, drones, decisions, arrival, and sleep effect. Each first touchscreen press is wake-only, all four wakes must avoid abrupt yaw, and every cycle must end in the same interactive neutral prompt.
- Two connected idle short-button suspend/wake cycles. Body output must park, sound stop, code-chan LEDs darken, the suspend projection appear, and touchscreen and short-button wake must each restore one complete visible frame before body output resumes.
- A Codex bridge sequence: acknowledged producer-ready, first-prompt working
showing the
WORKINGcaption, two-session exclusion, same-turn continuation, subagent draining, harmless approve and reject, terminal outcome, and session-end release. - The same sequence with a Claude bridge, including one physical rejection
that proves the harmless operation did not execute. With the Claude
status-line command installed, confirm the working caption shows the remaining
usage percentages and returns to
WORKINGwhen no sample is current, and that the usage read-out never alters hero motion, drones, or sound. - A task longer than 60 seconds for each producer must remain working until real terminal or session evidence arrives. An interruption that emits no supported terminal evidence must emit no outcome. For a passive Codex Desktop interruption, submit the next prompt on the same session and confirm it joins the episode rather than being refused: its evidence must correlate without an error prompt, and its terminal event must settle the episode. The bridge has to be restarted only when a session dies while its response is still active, because nothing can then arrive to release it.
- Bridge or link loss with permission pending must return no answer, remove controls, reject late device input, and permit a later fresh epoch to synchronize without inherited replica or deduplication state.
- Five consecutive external Codex bridge start/stop cycles must each complete
hello, snapshot, and operational synchronization without a runtime-status
timeout. Each stop must receive its current-epoch close acknowledgement,
cancel transient output, return the head to neutral, remove stale working
presentation, and leave the disconnected prompt rather than
BRIDGE UNCERTAIN. Then verify USBUncertainpresentation after silence and recovery from a valid current-epoch message. - Battery-powered long hold: exactly one stopping observation, safe rest, sound stop, code-chan LED darkness, servo torque and power disable, display suspension, and physical power removal. The PMIC indicator is identified separately from code-chan-controlled LEDs.
- USB-powered long hold: record the same ordered safety effects, the host's
device_stoppingresponse and successful terminal result before the PMIC removes USB, the PMIC request evidence, whether rails are physically removed while VBUS remains, and the state after cable removal. A lit PMIC or charge indicator is not reported as a code-chan LED failure. A live but non-interactive terminal state with no documented recovery is a failure, not successful shutdown. - Inject display and body failures through non-actuating owner tests and verify exact canonical fault presentation, no duplicate body-motion wait after the disable-command tail completes, and that no late result enables output or issues a second PMIC request after the deadline-owned fail-safe tail. Do not physically block a servo to induce a timeout.
- Record a 30-second cadence sample and verify stable 24 Hz presentation without catch-up bursts or partial frames.
Physical observations must distinguish firmware execution evidence from electrical outcome. An accepted AXP2101 register write proves the firmware reached the PMIC boundary; it does not by itself prove that board rails fell. Conversely, disappearance of serial or display alone does not prove code-chan LED and servo shutdown order.
The supported distribution model is a source checkout with the documented Node.js, Python, PlatformIO, hook, serial, scene-generation, filesystem, and firmware procedures. No npm publication is required.
Public redistribution is not release-complete while the repository has no
tracked LICENSE. License selection is a user product decision and is not
inferred by implementation work.
The current integrated source still requires the applicable unaccepted cases from the hardware matrix above. The identified installation has recorded acceptance for repeated suspend/wake, current Codex and Claude harmless permission decisions, and pending-permission link loss. The host lifecycle correction after that recording does not change firmware, the device protocol, or permission authorization, so those observations remain applicable.
On 2026-08-03, the preceding Claude host source physically kept a background
child active across the main response boundary, produced no intermediate
completion effect or sound, continued through the later result, emitted one
final completion, and remained at CLAUDE READY without a later MISS. The
2026-08-04 attempt/commit replacement instead remained working after its final
Stop because the expected idle notification did not arrive. The current source
removes that notification dependency and restores producer-bound Stop
settlement, so both observations are supporting evidence but do not accept the
replacement lifecycle implementation.
The current producer-lifecycle boundary remains open until one stable Codex
root-plus-child completion sequence and one Claude background-child episode verify no
intermediate ready/effect/sound, exactly one final outcome, no later MISS,
and normal bridge close with the final installed configuration. Battery-powered
long hold and the post-change 30-second cadence sample also remain open. These
are missing physical evidence, not software pass claims.
The Claude physical permission path is confirmed on hardware, including its
trigger. During an ordinary session on Claude Code 2.1.216 a PermissionRequest
delivery arrived unprompted, the device presented the decision controls, and an
approve decision returned over serial. That decision could only have come from
the device: the coordinator's answer entry point is reachable from the serial
decision message alone, with no timeout, default, or auto-approve path.
This corrects an earlier reading. A previous long session on the same version saw
no PermissionRequest arrive at all, and that was recorded as an open question of
whether the version still emits the event or had moved interception into a
PreToolUse decision. The event is not gone — it fires on this version and the
whole path works. What actually varies is whether anything is asked, which
depends on the session's permission mode and remembered allowances. Absence of
physical prompts is therefore a configuration observation, not an adapter defect,
and no adapter change is warranted. Codex needs no equivalent investigation on
this basis.