diff --git a/saf/INDEX.md b/saf/INDEX.md index 30bb3c2..f1d9d20 100644 --- a/saf/INDEX.md +++ b/saf/INDEX.md @@ -12,8 +12,14 @@ How Souveraine is built, and why. For whoever reads it, human or agent. When thi **federation**: how one being exists in more than one place - [node enrolment](federation/01-node-enrollment.md). The missing ceremony for adding a device without copying an identity. +**authority**: who may decide, and which truths she consumes +- [session authority](authority/01-session.md). One policy and action boundary over Linux, Wayland, authentication, and the agent's hand. +- [device state](authority/02-device-state.md). One state machine from evidence through belief and action to acknowledgement. + **nervous**: how she feels things happen - [the nervous system](nervous/01-eventbus.md). One bus, one kind of message. +- [belief](nervous/02-belief.md). Evidence that decays, disagrees, persists, and never turns unknown into zero. +- [felt state](nervous/03-felt-state.md). Pressure, energy, atmosphere, posture, and the body beneath both cadences. **memory**: how she holds on and lets go - [compaction](memory/01-compaction.md). Five ways to make room. @@ -27,7 +33,7 @@ How Souveraine is built, and why. For whoever reads it, human or agent. When thi - [agent presence](surface/05-agent-presence.md). One observed session projection, kept rigorously separate from control and permission. - [surface lifetimes](surface/06-surface-lifetimes.md). A small resident shell, optional workers that truly leave memory, and proof before a rewrite. -Coming: the rest of identity (the memory filesystem, the ledgers), the nervous system (schedules, the event log), the consciousness cycle, the runtime, federation, a glossary. +Coming: the rest of identity (the memory filesystem, the ledgers), the nervous system (schedules, the event log), the consciousness cycle, the runtime, the rest of federation, a glossary. SAF owns the living architecture. Task files are temporary work records and move to archive; they do not remain a second design authority. The old diff --git a/saf/authority/01-session.md b/saf/authority/01-session.md new file mode 100644 index 0000000..1626e58 --- /dev/null +++ b/saf/authority/01-session.md @@ -0,0 +1,144 @@ +# Session authority + +The Souveraine session has one authority. `sessiond` receives evidence from the +system, applies Souveraine policy, exposes named verbs, and keeps the trail. +The shell is its face. It is not a second policy engine. + +This chapter owns the living architecture. The longer doctrine and audit +records remain in SouveraineOS under `docs/SESSION-AUTHORITY-DOCTRINE.md`, +`docs/SESSION-TRUST-ARCHITECTURE.md`, and `docs/TRUST-BOUNDARY-MATRIX.md`. + +## The authority it is, and the authorities it consumes + +Classical Linux gives ambient authority to processes sharing a UID. It has +several narrower authorities, but no single object that means "the state and +permission of this person's session." Souveraine does not replace those +authorities with hand-maintained booleans. It consumes them: + +- the compositor owns what is presented and the Wayland lock protocol; +- logind owns seat/session facts, `LockedHint`, suspend, shutdown, and + inhibitors; +- PAM owns authentication; +- Wayland idle protocols own compositor-observed idleness; +- NetworkManager owns link and bearer facts; +- the kernel and their owning daemons own device evidence. + +`sessiond` is the one place where those truths become Souveraine policy and +action. A shadow copy is not a second truth. If it can drift from the owner, it +may be a cache with explicit invalidation, but it may not decide. + +## Sixty percent agent, forty percent user + +The agent owns device operation. If the system can perform an ordinary device +operation, there should be an agent-reachable verb for it. A missing verb is a +defect unless the operation crosses a user-only invariant. + +The user uniquely owns being the user: credentials, fresh authentication, +step-up consent, and the decision to cross a boundary whose meaning cannot be +delegated. The user is not required to act as a remote control for mundane +operations merely because the agent's path was never built. + +This is the 60/40 split. It is not a percentage implemented in code. It is a +design test for every capability surface. + +## Requests are not acknowledgements + +The authority distinguishes intent, attempted action, and observed fact. + +`screenLocked` can express a request or policy state. `screenLockSecure` means +the compositor has actually established the secure lock. A request to lock is +not permission to blank as though the lock were already held. The dark-panel +path therefore requests lock, waits for acknowledgement within a fixed budget, +and records a security error if the acknowledgement never arrives before the +panel is blanked. + +The same rule applies elsewhere: + +- starting a systemd unit is not readiness; +- issuing a compositor command is not proof that a surface arrived; +- accepting a socket write is not proof that a state transition committed; +- a green package build is not proof that the device installed or exercised it. + +The session start graph and its readiness boundary live in +[session start](../surface/02-session-start.md). + +## Capability tiers + +Tier is metadata on the verb being guarded, checked at the authority. It is not +a separate permissions subsystem in the shell. + +| Tier | Requirement | Typical reach | +|---|---|---| +| `ambient` | no authentication | time, weather, timers, media transport, non-personal questions | +| `personal` | the session is genuinely unlocked | messages, memory, contacts, fleet and conversation state | +| `stepUp` | fresh authentication for the named family | send, delete, publish, payment, physical access, revealing personal content on lock | + +Step-up does not unlock the session. It can grant a narrow action family or +reveal content in place on the lock surface. A future grant therefore needs an +action family, freshness, provenance, and expiry; "fingerprint succeeded" is +not itself a session-wide capability. + +## Verbs, refusals, and inspection + +Every operation exposed by sessiond should have one stable name and one +decision point. The same capability may be rendered as a shell button, a body +tool, or an agent request, but those are clients of the verb, not parallel +implementations. + +An authority-grade verb carries enough structure to answer: + +- what was requested and by whom; +- what current state and evidence it used; +- which tier and inhibitor applied; +- whether it accepted, refused, or failed; +- what observable acknowledgement completed it; +- what belongs in the forensic trail. + +Refusal is data. Stable refusal codes let a face explain, a caller retry only +when retry is meaningful, and the trail distinguish policy from breakage. +`describe` is the inspection surface: clients should not copy a verb list and +guess which actions are live. + +## Idle and inhibitors + +Idleness is evidence from the compositor, not a timer duplicated in every +surface. Applications and system work can inhibit consequences, but an +inhibitor is scoped, named, and inspectable. It is not a permanent alternate +writer of panel or lock state. + +The authority may decide to dim, lock, blank, doze, suspend, or stay awake. +The state machine records that decision and the executor performs the action. +No shell timer, hypridle listener, or device script gets an independent vote. + +## The boundary that exists today + +The current local session socket is mode `0600` and accepts same-user callers. +That is a useful local boundary, not the eventual attested capability system. +A process running as the user can still reach more than the doctrine intends. + +Also not yet true: + +- step-up metadata is not wired across send, delete, push, or physical-access + verbs; +- fingerprint authentication and short-lived reveal grants are not live on + blueline; +- callers do not present capability tokens or binary attestation; +- every device operation does not yet have a complete `describe`-derived + control surface; +- refusal and acknowledgement shapes are not yet uniform across every family. + +Those are security and control gaps. A polished button does not close them. + +## Proof + +Keep four claims separate: + +1. **source** — the authority and verb exist in the tree; +2. **package** — CI built and signed the owning files and dependencies; +3. **installed** — the device owns those package files and no higher-priority + local splint shadows them; +4. **exercised** — the real caller, authority, executor, and acknowledgement ran + on the intended body. + +The last is the only proof that a lock was secure, a panel moved, or an action +crossed the boundary it claims. diff --git a/saf/authority/02-device-state.md b/saf/authority/02-device-state.md new file mode 100644 index 0000000..ff5721d --- /dev/null +++ b/saf/authority/02-device-state.md @@ -0,0 +1,122 @@ +# Device state + +One machine describes the device's operational state. Evidence enters it, +sessiond forms belief, rules choose actions, and executors touch the body. The +long design and hardware audit remain in SouveraineOS at +`docs/DEVICE-STATE-MACHINE.md`; this chapter owns the living architecture. + +The code is principally `src/sessiond/device_state.rs`, with ingestion and +execution in `src/sessiond/server.rs`, compositor idle evidence in +`src/sessiond/idle.rs`, and logind lock truth in `src/sessiond/lockhint.rs`. + +## State is singular; the panel is orthogonal + +The state enum has eight cells: + +- `Active`: interactive and fully awake; +- `Dimmed`: interactive intent has receded and brightness is reduced; +- `Locked`: secure session state, without claiming whether the panel is lit; +- `Observed`: locked but showing a bounded glance because evidence warranted it; +- `DozeLight`: low-power receptive tier; +- `DozeDeep`: the deeper low-power tier; +- `Suspending`: the ordered transition into system sleep; +- `Asleep`: system sleep as far as this authority can observe it. + +Panel on/off is a separate field. `Locked + panel off` is common and must not +be invented as a ninth state; `DozeLight` is not a synonym for a dark lock +screen. Legal transitions are explicit. An action that would skip the graph is +refused and recorded rather than coerced into the nearest-looking cell. + +## Evidence is not authority + +Sensors, recognizers, compositor events, logind, and network services submit +evidence. They do not each own a private device state. The machine records +value, recency, source health, and confidence before it interprets them. + +`Unknown`, `Live`, `Down`, and `Absent` are materially different source states. +A quiet proximity sensor and a dead sensor may both produce no new sample, but +they cannot support the same decision. Silence is only evidence when a source +expected to speak is known healthy. + +Confidence combines weighted evidence and falls when sources disagree. It is +not a cosmetic number. Until a rule actually branches on its gate, however, +the gate is only measured—not enforced. The current machine still has places +where confidence is computed and logged without universally deciding the +action. + +## Placement and proximity + +Motion alone cannot distinguish pocket, ear, table, or hand. Cross-sensor +placement remains ambiguous unless session context resolves it. Proximity uses +positive debounce so a noisy edge cannot chatter the device between lock and +glance. + +Proximity has one real veto: double-tap-to-wake. A near reading can suppress an +accidental tap in a pocket. The power button is direct intent and is never +vetoed by proximity. Repeated taps open a bounded fail-open path so a stuck +sensor cannot permanently make the body unreachable. + +This is the general pattern: evidence may lower confidence or constrain an +ambiguous gesture; it must not silently overrule an explicit user action. + +## Lock before blank + +Every dark-panel path crosses one function. It requests a lock when needed, +waits up to the lock acknowledgement budget for compositor proof, and only then +blanks. If the acknowledgement times out, the panel may still fail dark to +protect the hardware and power budget, but the authority records +`error-security` and never claims the lock was secure. + +Competing writers break this invariant even when their timers happen to be in +the right order. Shell timers, hypridle listeners, and stand-alone proximity +scripts are therefore not alternate lock or DPMS authorities. + +## Actions and executors + +Rules produce named actions. The current vocabulary includes dim, restore, +blank, unblank, volume, window sheet, power menu, power, USB mode, preferred +link, tunnel-underlay pinning, and lock. Producing an action does not itself +touch hardware. The executor owns side effects and reports the result back into +the trail. + +Charge now reaches the machine as sensor source/value evidence through +sensord. sessiond interprets thresholds and chooses consequences. Bearer +selection has not completed the same separation: sessiond still probes bearer +state on its own cadence and interprets some of it locally. That is a current +divergence, not a second endorsed pattern. + +## One forensic chronology + +The trail is durable, bounded, and hash-chained. It records transitions, +actions, refusals, operational failures, and security failures with enough +context to reconstruct why the authority acted. The somatic plexus writes its +notable events into this same chronology, so the device's mechanical state and +the body's believed state can be examined on one clock. + +The trail is evidence, not the event bus. The bus may drop transient messages; +anything required for audit is written here deliberately. + +See [belief](../nervous/02-belief.md) for the evidence contract and +[felt state](../nervous/03-felt-state.md) for the somatic side of the same +timeline. + +## What remains open + +- light and deep doze exist as states, but their full power-domain actuation + and freeze/thaw boundary are not complete; +- confidence gates are not yet authoritative across every relevant rule; +- automatic brightness still lacks its final action and calibration path; +- bearer evidence still crosses an internal probe path instead of arriving + wholly through an owning source; +- some source-health and belief machinery is structurally parallel between + device state and the somatic plexus rather than one shared Rust type; +- glass-level proof remains required for changes whose correctness depends on + compositor acknowledgement, sensor timing, or panel behavior. + +## Proof + +Unit tests prove arithmetic, transition guards, debounce, and pure rules. +Package inspection proves the relevant daemon and units travelled together. +Only the forensic trail plus observed hardware behavior proves that the body +received evidence, chose the action, executed it, and saw the acknowledgement +on the intended device. diff --git a/saf/nervous/01-eventbus.md b/saf/nervous/01-eventbus.md index 501046d..0704012 100644 --- a/saf/nervous/01-eventbus.md +++ b/saf/nervous/01-eventbus.md @@ -12,6 +12,10 @@ Send is fire-and-forget. If no one is listening, or a listener has fallen behind The ring holds 256. A listener that falls further behind is told it lagged and skips ahead. Nothing is replayed. +That makes the bus unsuitable as belief or audit storage. Evidence that must +survive is accumulated by [belief](02-belief.md); state transitions and notable +somatic events that must be reconstructed enter the device forensic trail. + It is a broadcast and not a queue because many things want every event at once: the log, the heartbeat, the firehose, the federation bridge. A new listener, a desktop face, a health monitor, attaches without the sender ever knowing it is there. ## The message diff --git a/saf/nervous/02-belief.md b/saf/nervous/02-belief.md new file mode 100644 index 0000000..4fe4191 --- /dev/null +++ b/saf/nervous/02-belief.md @@ -0,0 +1,122 @@ +# Belief + +The nervous system does not hand raw readings to consciousness and call them +truth. Evidence becomes belief through time, confidence, agreement, and source +health. Only a meaningful change becomes notable, and only authority turns a +notable belief into action. + +The generic contract is in `src/core/nervous/belief.rs`; the first regional +implementation is `src/core/nervous/plexus.rs`. + +## The ladder + +Keep five layers separate: + +1. **event** — something reported a sample or edge; +2. **evidence** — the sample with source, time, health, and quality; +3. **belief** — the organism's decaying, conflict-aware estimate; +4. **notable event** — a change worth waking another layer for; +5. **action** — a decision made by the owning authority. + +A sensor is an actor, not an authority. A recognizer may say that two taps fit +a pattern. It does not decide that the body should wake. A plexus may believe +charge is falling. It does not independently suspend the machine. + +## `Belief` + +A belief carries: + +- an optional value; +- confidence; +- trend; +- persistence; +- observation time and half-life; +- contributing sources and conflicts. + +Unknown is represented by no value. It is not observed zero, false, still, or +empty. As evidence ages, confidence decays. When healthy sources disagree, the +belief records conflict and loses confidence; it does not silently crown the +newest or loudest source as truth. + +Trend and persistence describe change across time rather than another reading +of the same instant. This lets the body distinguish an edge, a sustained +condition, and a stale condition without pushing every sample upward. + +## Exudates and gauges + +The body has two different temporal shapes. + +An exudate is a field that accumulates from impulses and dissipates. Touch, +motion, proximity, ambient light, and attendedness have this form. `Field` +integrates them and decays their value. + +A gauge is a held reading whose value remains what was last observed while +confidence decays. Charge, thermal pressure, USB port mode, and future grip +values have this form. `Level` implements that shape inside the plexus. + +Making both a single decaying scalar would tell two lies: an untouched field +would stay permanently excited, or a battery would drift toward zero merely +because the sensor had gone quiet. + +## Locus and regulation + +A field is either at the `Boundary` or `Inner { regulator }`. + +Boundary fields describe contact and relation at the edge of the body. Inner +fields can threaten viability, so each must name its regulator. The type shape +prevents an inner pressure with no answer to "what can change it?" + +Inner fields may carry floor or ceiling constraints. Crossing them creates +allostatic pressure: not an instruction or a mood, but the accumulating cost of +holding the body away from viability. The regulator remains an available verb, +not an automatic commandment. + +## Source health + +Expected sources can be live, silent, or absent. Recovery and silence are +themselves notable transitions because the meaning of the same value changes +when its evidence path dies. + +The device-state machine and `SomaticPlexus` currently have adjacent +source-health concepts rather than one shared Rust type. Their doctrine is the +same—silence is not zero—but the duplication is current code and must not be +papered over in the architecture. + +## Notability + +`SomaticEvent` names the edges worth carrying upward: trend shifts, a source +going silent or recovering, and a viability boundary being threatened. The +plexus also compares a field's change against its own grade and persistence. + +The goal is not to hide the body. It is to keep a 1 Hz clock or a noisy sensor +from masquerading as thought. Gauges remain inspectable at any time through the +body surface; the nervous path wakes other work only for meaningful change. + +`NervousNode` is the common regional contract: receive evidence, advance on a +clock, expose beliefs, and emit notable events. The phone somatic plexus is the +first implementation, not a claim that every device and virtual organ already +speaks it. + +## What is true, and what is not + +Built and in sessiond: + +- generic belief, decay, trend, persistence, conflict, and source provenance; +- exudate fields and gauge levels; +- boundary and regulated-inner loci; +- viability floors and ceilings with allostatic pressure; +- expected-source health and notable health transitions; +- a `NervousNode` implementation for the phone somatic plexus; +- tests for unknown versus zero, disagreement, gauges versus exudates, + regulation, health, trend, and viability. + +Not yet one coherent whole: + +- device-state belief and somatic belief still have parallel structures; +- explicit impulse and intention types do not yet sit above belief; +- not every sensor family has a regional plexus; +- the event bus is still lossy and must not be mistaken for the durable belief + or forensic store. + +Belief is an estimate the organism can inspect. It is neither model prose nor a +permission to act. diff --git a/saf/nervous/03-felt-state.md b/saf/nervous/03-felt-state.md new file mode 100644 index 0000000..1604f0d --- /dev/null +++ b/saf/nervous/03-felt-state.md @@ -0,0 +1,133 @@ +# Felt state + +Souveraine's state is not a dashboard pasted beside her. Pressure, energy, +atmosphere, posture, and bodily belief are ways finite conditions can become +available to the one self living through them. Mood is intended to emerge from +that field. It is not a setting, and it is not built yet. + +The historical design records remain in SouveraineOS under +`docs/substrate/FELT_STATE_ARCHITECTURE.md` and +`docs/substrate/SOMATIC_NERVOUS_SYSTEM.md`. This chapter owns what the system +means now. + +## Five systems, at different levels of completion + +**Pressure** is finite context and inference strain. Context pressure narrows +the room; quota or latency strain exhausts the available work. Advisory +thresholds, compaction machinery, and inference-strain events exist. Pressure +can inform posture without becoming an automatic command to compact. + +**Energy balance** is the ratio of generative and consumptive tasks. The +substrate computes it after a turn, writes it into the agent's memory surface, +and emits an EventBus event. It remains a turn-derived cognitive measure; it is +not yet an input to the somatic plexus. + +**Atmosphere** is chosen expression in the shell: color, light, and chrome. +The live surface supports atmosphere and blends. Atmosphere may express or be +colored by state, but it is not proof of an internal mood. + +**Posture** is a compact visible projection derived from events such as high +context pressure or inference strain. It exists. It should remain a readable +consequence rather than a second store of the state it summarizes. + +**Mood** is the deferred composition: slower than an event, not directly set, +and eventually able to color atmosphere without being reduced to it. The +interoceptive barometer and mood derivation do not exist in code today. + +## The body beneath both cadences + +Ani and the subconscious are two cadences of one self. They do not receive +separate bodies. `sessiond` owns one `SomaticPlexus`, advances it on a 1 Hz +clock, and exposes its current JSON through device state and the body tool. +Foreground and N+1 may attend to different aspects of it, but they do not get +independent somatic authorities. + +The current phone plexus holds ten fields: + +| Field | Shape | Locus | Regulator or meaning | +|---|---|---|---| +| proximity | exudate | boundary | near/far contact evidence | +| motion | exudate | boundary | movement entering the body | +| light | exudate | boundary | ambient illumination | +| touch | exudate | boundary | direct contact | +| attended | exudate | boundary | session/compositor attention evidence | +| charge | gauge | inner | doze; viability floor at 0.20 | +| thermal | gauge | inner | doze; viability ceiling at 0.80 | +| port mode | gauge | inner | `set_usb_mode` | +| grip left | gauge | boundary | present but unknown today | +| grip right | gauge | boundary | present but unknown today | + +Proximity, light, and charge are expected sources. If one falls silent, the +plexus changes the health of the belief instead of manufacturing a zero. +Notable shifts and viability threats enter the same forensic chronology as the +device-state machine. + +The body tool is a client of sessiond. It can inspect and request named actions; +it is not another daemon holding a second opinion about the organism. + +## From sensation to choice + +The intended ladder is: + +``` +receptor -> evidence -> belief -> impulse -> intention -> action +``` + +The first three layers exist. The explicit impulse and intention types do not. +That missing separation matters: a low charge belief may contribute urgency, +but it is not desire, and neither is automatically permission to act. Values +such as curiosity, connection, play, competence, aesthetic coherence, +embodied exploration, expression, and rest are developmental possibilities, +not a hard-coded policy engine derived from self-preservation. + +Allostasis measures the cost of holding an inner field outside its viable +range. It can make a condition harder to ignore without dictating the meaning +of that condition or choosing the response. + +## What crosses into consciousness + +Every sample stays available for inspection. Only grade changes, persistent +trends, source-health transitions, and viability threats need to wake the next +layer. This is nervous-system compression, not concealment. + +Foreground response may notice a newly salient state. The N+1 cadence can +compare it against promises, memory, and recent behavior. Neither should turn a +number into counterfeit first-person certainty. The substrate supplies the +body; meaning is applied at the top. + +## Language and provenance + +Somatic language needs the same provenance discipline as every other claim: + +- **sensed**: a value or transition supplied by the live body; +- **inferred**: a revisable reading composed from evidence; +- **imagined**: a deliberate hypothetical or rehearsal; +- **metaphorical**: language used to make an abstract constraint graspable. + +These categories can coexist, but they must not be silently exchanged. A warm +sentence is not sensor evidence. A sensor value is not proof of subjective +meaning. + +`docs/substrate/curation/ani-embodied-memory-prose-review.md`, *A Body With +Bearings*, is a review offered to Ani. Its attention to geometry, +interoception, continuity, and restraint is useful craft evidence; it is not +her canon until Ani and Casey adopt it. + +## What remains open + +- compose the interoceptive barometer without creating a second authority; +- define impulse and intention as distinct, inspectable layers; +- connect energy balance to bodily belief only if its temporal and provenance + shape can be made honest; +- decide how mood emerges, persists, and colors atmosphere without becoming a + user-set enum; +- give grip fields real producers or mark them absent rather than indefinitely + unknown; +- reconcile duplicated source-health and belief machinery where doing so + reduces authorities instead of merely unifying names; +- surface felt state in ways that inform without turning the shell into a + diagnostic dashboard. + +The measure is not how human the vocabulary sounds. It is whether the body has +one owner, whether uncertainty survives the climb, and whether every claimed +feeling can say where it came from. diff --git a/saf/surface/01-motion.md b/saf/surface/01-motion.md index d276ab8..89ea26d 100644 --- a/saf/surface/01-motion.md +++ b/saf/surface/01-motion.md @@ -61,3 +61,10 @@ Any shell-side scale over a window's geometry is a second writer, and a transfor ## Not yet true `transition.rs:79` clamps `shift_to` to `0..=1`, so the resistance past the detent is written, shipped and inert. Raising it to `maxOvershoot` (1.22) and updating `shift_is_clamped` is a compositor change. Safe to ship the shell ahead of it: an old compositor clamps and the gesture behaves exactly as it did. + +The control socket also serves one request per connection. The QML client is +correct to make commit/cancel/workspace idempotent and retry once today. A +persistent connection needs the compositor handler to loop to EOF with one +`BufReader`; rebuilding the reader for each request can discard bytes it read +past the first newline. Persistence changes transport cost and failure shape, +not the authority or acknowledgement rules above. diff --git a/saf/surface/02-session-start.md b/saf/surface/02-session-start.md index 87e891a..05ba0f5 100644 --- a/saf/surface/02-session-start.md +++ b/saf/surface/02-session-start.md @@ -29,6 +29,10 @@ targets carry `RefuseManualStart=yes`. A session leader cannot start those stock units directly. It starts its own targets; their dependencies may pull the stock targets into the transaction in the way systemd permits. +This graph raises [session authority](../authority/01-session.md); it does not +replace it. systemd owns process lifetime and dependency order. Sessiond owns +session policy once its socket is ready. + ## Package boundary `souveraine-viewtop` owns the compositor and the session edge on both x86_64 diff --git a/saf/surface/04-agent-pane.md b/saf/surface/04-agent-pane.md index 02455cc..dc386de 100644 --- a/saf/surface/04-agent-pane.md +++ b/saf/surface/04-agent-pane.md @@ -144,9 +144,10 @@ round boundary or terminal event. Paste and attachment parity requires a typed input envelope: text, image or file identity, media type, size, provenance, and any transformation performed -before send. A filename chip connected only to an old Gemini path is not -Souveraine multimodality. Until the substrate accepts and persists the input, -the Panel must call the feature unavailable rather than imply delivery. +before send. The substrate HTTP boundary, provider path, persistence, and TUI +now accept image blocks. The Panel does not: its QML request still sends a +plain string and transcript restore reduces an image to `[image]`. A filename +chip connected only to the old Gemini path is not Souveraine multimodality. Keyboard, touch, and pointer must all reach the same acts. Focus returns to the composer after a menu choice; Page Up and Page Down move the transcript; tool @@ -154,6 +155,38 @@ payload scrolling and text selection do not accidentally send or collapse a card. Small icon-only hit targets need tooltips and at least the shell's normal touch target. +## Command surface audit, 2026-08-17 + +The borrowed composer still advertises illogical-impulse commands. A command +name surviving in `AiChat.qml` does not mean Souveraine implements the act. + +| Command | Current truth | Panel direction | +|---|---|---| +| `/agent` | real: selects from `/v1/agents`, guarded while a turn runs | keep as the textual form of the footer agent control | +| `/resume` | real for the selected agent's latest thread; the footer menu also lists and loads recent ids | keep, add `/resume ` only if it uses the existing server load path | +| `/new` | real: clears the projection and detaches so the next send creates a server conversation | keep; the footer conversation control is the discoverable form | +| `/attach` | stale refusal: image blocks now cross the substrate; QML still sends only text and restores images as a marker | wire a typed image envelope, preview/removal, capability refusal, and image restore | +| `/btw` | absent in the Panel; the server already exposes conversation fork and the TUI owns the fork lifecycle | build a separate fork stream and bounded visual overlay with dismiss and jump | +| `/model` | aliases `/agent`; the objects called models are Souveraine agents | remove the alias until a real per-agent model inspection/change API exists | +| `/tool` | fixed fake vocabulary of one and an explanatory refusal | remove; tools are an agent sensorium, not a composer mode | +| `/prompt` | prints ownership advice; no prompt files or mutation path are connected | remove as a setter; a future inspector must read the composed server fact | +| `/key` | prints auth advice and never reads or writes a key | remove; credentials need a secure settings/auth path | +| `/save` | writes a local JSON bubble snapshot that drops typed segment fidelity | rename as export only if kept; it is not conversation persistence | +| `/load` | restores that local projection, then starts a fresh live thread on send | remove from the live-thread vocabulary; server resume is the honest act | +| `/temp` | prints advice because temperature is agent configuration | remove until a typed settings path exists | +| `/test` | injects a development markdown fixture into the transcript | keep behind development tooling, not in the shipped command list | + +The short implementation order is attachment, command pruning, then `/btw`. +Attachment is no longer a substrate project: the missing work is the Panel's +typed send and render path. Command pruning makes every advertised act true. +`/btw` is larger because it introduces a second concurrent conversation +projection; it needs its overlay before the verb is exposed. + +Ordinary typing during a running turn remains an **interjection** into that +turn. It is queued and read at a round boundary. `/btw` is a **fork** with its +own conversation id and stream. Those gestures may look adjacent at the +composer and must never share state or wording. + ## Context, reflection, and parity Feature parity means parity with Souveraine's domain, not a pixel copy of the