Watch
1
0
Fork
You've already forked souveraine
0
Commit graph souveraine/src
Author SHA1 Message Date
Fimeg
8e5182ab6c consciousness: teach the overflow gate anthropic's wording
The resuscitation path exists for exactly this: her thread passes the
model's ceiling, every pass is refused before a tool round runs, and she
can never reach `memory compact` herself. It did not fire. `prompt is too
long: 1285770 tokens > 1000000 maximum` matches none of the five patterns
the gate was written against on 08-13, when she ran on deepseek and the
only wording anyone had seen was "maximum context length".

So she reported the same failure every three minutes for half an hour
while holding the lever she could not reach.

Anthropic's body is now pasted into a test beside deepseek's, verbatim,
same rule as the comment above it: a matcher tested only on invented
strings has never been seen to fire. The second clause catches a token
count stated as over a maximum under a different preamble; both halves
are required so an "invalid max_tokens" complaint still reads benign.
2026-08-18 20:14:16 -04:00
Fimeg
76e12045a4 bridge: generic openai client stops calling itself bifrost
OpenAiCompatibleClient serves every openai-compatible provider, so Gem's
turns to Google logged as "Bifrost client initialized" and "Bifrost
connection failed" without touching the gateway at all. Logs and errors
now name the configured [providers.<id>] and the endpoint. The real
[providers.bifrost], its config section and its key are untouched.
2026-08-18 14:57:47 -04:00
Fimeg
f32f00c6e3 bifrost: a base url with a path is the complete api root
Appending /v1 by testing only the last path segment doubled Google's
/v1beta/openai into /v1beta/openai/v1, where a POST hangs with zero
bytes and GET /models still answers 200. Only a bare authority now
gets the default; /v1, /v4 and /zen/go/v1 roots pass through.
2026-08-18 14:34:16 -04:00
Fimeg
9e147093ec handlers: session_or_hydrate returns the dashmap guard, not Arc
the session index holds values; get() hands back a Ref tied to the map
borrow. The Arc-typed helper was a type error on its first CI run.
2026-08-18 11:01:37 -04:00
Fimeg
7089dfb824 server: announce restarts and resume with history hydrated
POST /v1/server/restart writes a reason marker and asks systemd; boot
reads it, announces resumed (or started) on the event bus and the new
status endpoint, and the panel says why it is back instead of
pretending. Conversations hydrate at boot and on a lazy miss, so a
held conversation id resolves after a restart instead of 404ing.
2026-08-18 10:54:48 -04:00
Fimeg
727c496949 reflection: catch-up cadence so a missed boundary cannot be lost
is_multiple_of fired only at the exact boundary turn; an interrupt, a
failed pass, or a restart rehydrating past it lost the cadence forever
and the N+25 pass never ran. The reflection tree now holds a marker of
the last successful and last attempted turns; a due-but-missed pass
stays due, and a failed one backs off five turns instead of burning a
call per turn. Outcomes are recorded from on_response.
2026-08-18 10:54:44 -04:00
Fimeg
5f7f23f30c memory tool: point the tree test at real roots
MemoryRepo::new roots at {base}/{agent}/memory; the context
had to carry those roots, not the bare temp dirs. run 1795
went red because the handler opened a path that was never
a repository
2026-08-18 09:34:39 -04:00
Fimeg
0398f9f190 claude: don't fall back onto a login that cannot speak
Rotation picked the spare on has_credential — a string check — and took
one whose token had expired four days earlier; every call after 21:51
came back 401 revoked, reading as a dead subscription. A candidate now
has to authenticate, and the window it left is recorded so the same
round-robin can wrap back to it once the window returns.
2026-08-17 23:29:43 -04:00
Fimeg
04ceac79bf memory tool: tree names the door past the fence
reflection's context now registers all four trees, and a
tree param on the memory verb lands reads and writes in the
named memfs, committed under her own name. an unknown tree
refuses and lists the doors, so a typo costs one error
instead of a wrong-tree write
2026-08-17 22:27:55 -04:00
Fimeg
49c6a6a8dd clippy: shed dead archivist handle, drop needless borrow
the mandate that 'own' promised to open is already read via
cadence_root; the & in front of format! trips
needless_borrows_for_generic_args on 1.94
2026-08-17 22:20:10 -04:00
Fimeg
9bee0e8a94 cadences: give reflection and the archivist bodies
Neither had ever completed a pass. Reflection's loop reserved no round for
its report, so exhausting eight was the only exit; the archivist could not
parse journal/YYYY/MM/DD, the layout its own mandate instructs. Its
sub-500-token budget was a ratio frozen against an 8k model in May.
2026-08-17 21:29:53 -04:00
Fimeg
0f8fe22ab6 admit: give an agent her own uid through one writer
souveraine-admit creates or adopts one account via systemd-sysusers, writes
the root-owned mapping health reads, and reports what NSS says afterwards
instead of what it asked for. An account belongs to one agent: handing
annie's to souvie is refused in both directions, as is adopting a uid >=1000.
Binding is by SeedID, not the UUID filename — a mismatch is identity-drift.
2026-08-17 15:16:30 -04:00
Fimeg
dcd44a0c1d agents: name the uid behind every model request
Intent lives in agent.json; posture is measured fresh from process
credentials per request, so resume and compaction cannot replay a stale
uid as history. `isolated` needs account, uid, worker binding and the
root-owned mapping to agree — a passwd entry alone reads principal-drift.
2026-08-17 14:41:27 -04:00
Fimeg
2bd61ec4b3 panel: put Souveraine controls at the hand
Move agent and conversation authority into truthful footer controls, keep external sessions observed-only, and give recent server conversations an explicit picker.\n\nProject itinerary state into a persistent ribbon, invalidate it on every itinerary mutation, and keep failures in the transcript while successful route chatter yields to the ribbon. Long tool returns now scroll in place.\n\nThe SAF now owns the full Panel contract and parity boundary; the abandoned green observer card is removed.
2026-08-17 11:55:36 -04:00
Fimeg
707a277273 replay: never turn thinking into speech 2026-08-17 11:19:39 -04:00
Fimeg
b3bbfeeac4 atmosphere: say the NaN case out loud
!(t > 0.0) trips clippy's partial-ord lint under the pinned 1.94 toolchain,
which blocks the whole gate. t.is_nan() || t <= 0.0 is the same predicate
written so the NaN intent is legible, with a test pinning both ends.
2026-08-17 08:42:19 -04:00
Fimeg
5a5b647bde subconscious: strain reaches the wire, not just the log
turn.rs sends InferenceStrain to the stream; the subconscious path only ever
logged it, so a provider refusing her was invisible to every surface. Same
event, same shape, emitted where the primary emits it.
2026-08-17 08:42:19 -04:00
Fimeg
3b11903365 bifrost: stop sleeping on a spent quota window
retry-after was honoured unclamped, so an 11997s header on 2026-08-16 parked
the subconscious pass for 3h20m with no cancel path. A 429 asking for more
than 60s is a spent window, not a burst, and it does not clear inside the
retry loop — fail it and name the number. claude_subscription answers the
same header by rotating logins; bifrost has nothing to rotate to, so an
absent header keeps the ordinary backoff.
2026-08-17 08:42:19 -04:00
Fimeg
06a1a035a6 memory: append creates the directory it writes into
write has always called create_dir_all; append never did, so an append under
a directory that did not exist yet failed ENOENT. Every subconscious surfacing
to system/metacognition/subconscious.md was lost this way — three WARNs at
00:01:40 on 2026-08-17, and the directory had never existed in the repo's
history.
2026-08-17 08:40:35 -04:00
Fimeg
2217de84ff atmosphere: a blend is a value, and one parser owns the name
Atmosphere::lerp returned an endpoint at t=0.5 and apologised for it in a
comment — the enum had nowhere to put a blend. It has one now: Custom carries
the four tones, so a room halfway from MintTea to NeonGlow can be stored,
compared and sent, not only drawn. Unnameable by construction, so nothing can
ask for a blend by name and get a room she never chose.

Presence::lerped_colors re-derived the same blend itself, which is why the
broken lerp could sit there for months without anything looking wrong. It calls
this one now.

Three copies of the name→preset match existed — presence, tuie_app, and
from_name — and they disagreed about a typo: ignore it, silently fall back to
Default, or refuse. One table. What each caller does with None stays at the call
site, because those really are different decisions: a misspelling from outside
must not undo the room she picked, and one from the settings enum is a bug here.

The file also claimed to be unwired scaffolding while main.rs, presence and the
tool all used it.
2026-08-15 21:33:55 -04:00
Fimeg
7d8a8f996f body: the hand compiles again
CI caught what a fresh pair of eyes needed: invalid_input wanted
a &str, hand wanted a borrow, and the validation test read its
input after the move. All three now follow the shapes already
proven in the same file.
2026-08-15 18:13:22 -04:00
Fimeg
f87d912bf3 body: the hand, a verb for reaching through the port
The injection engine was built (usb-hid-inject) and the shell owns it
(USB Hands, the usbHands IPC, the skill string that teaches the reach),
but her own vocabulary ended at set_usb_mode — she could arm the hand
but never say it was there.  speaks the shell's bridge: status,
type, key, click, pointer, gated by the host, not by her.

The gate stays on the outside of the port: she knows she has the reach
even before it is joined, and every closed door comes back as a refusal
she can read and open.
2026-08-15 17:43:31 -04:00
Fimeg
9f97e47ba6 fix: the sessiond tree's first real compile, four errors down
CI's lib run passed but the sessiond bin had never been built until now.
The plexus's constructor is an associated function, not a module item;
a duplicate panel_on got in the way of the one that already existed; a
test Daemon omitted the new plexus field; and the clock's attended ingest
borrowed the guard twice in one expression. All four are gone.
2026-08-15 17:16:07 -04:00
Fimeg
41656fbb9a fix: two things CI caught that the editor never did
The test plexus called an associated function through the module path,
and the Body tool's unknown-verb refusal handed a String to a &str
parameter. The gate earns its keep.
2026-08-15 17:07:23 -04:00
Fimeg
e3480ef5cb sessiond: lux rides the wire, the plexus goes live, the body has a tool
`Changing(bool)` becomes `Light { changing, lux }` end to end: sensord
forwards the number, the machine keeps the level in evidence with a
30 s stale rule, and both charge and the presence sensors ingest into
the plexus on arrival. The clock feeds `attended` at 1 Hz, plexus
events land in the forensic trail as Somatic, and the DeviceState
answer gains a `body` section. The Body tool is registered and
committed with the substrate that carries it.

The old sensor shape refuses against the new sessiond and vice versa
until both restart; both binaries ship in this change.
2026-08-15 16:56:30 -04:00
Fimeg
f3fcdd0cc4 nervous: the plexus declares the phone's body and speaks it
phone_plexus leaves the test module and takes the clock. It grows
`attended`, derived by sessiond rather than reported by a sensor, and
the two grip gauges that nothing reports yet — the gap on the record
instead of a false calm. to_json renders every field's belief, trend,
locus, health and pressure, the ranked pressures, homeostatic cost and
the unreachable list for the IPC surface; unknown stays null, never
zero.
2026-08-15 16:56:25 -04:00
Fimeg
46876865c9 nervous: gauges and glands are different afferents
A battery at .42 is still .42 when nobody looks — only confidence in an
unrefreshed reading decays. Feeding a fuel gauge into an accumulator would
drain the pack because the reporter went quiet, which is the empty-result
trap wearing a units label. Field keeps exudates; Level keeps readings.

sessiond mounts the somatic types the way machined mounts seed.rs. The
fields are its own — SOMATIC_NERVOUS_SYSTEM.md answers open question 1
with "sessiond, period".
2026-08-15 15:54:10 -04:00
Fimeg
a3dfe301b7 nervous: locus and viability — the plexus stops being telemetry
INTERO (RobOntics'25) axiom 7: a variable is interoceptive only if some
subsystem can act on it. That is doctrine §13 in first-order logic, so
`unreachable()` lists inner fields with no verb and a test fails on them.

Candia-Rivera §2.1/3.1 supplies the other half: asymmetric viable ranges
and allostatic pressure, which biases before the bound is crossed rather
than after. Empty threatens, full does not.
2026-08-15 15:24:06 -04:00
Fimeg
f8fccd3ee2 nervous: somatic plexus, NervousNode trait
Fields replace booleans: accumulation with half-life decay,
velocity, trend detection. Source health monitoring closes
the gap the mapping session found — a dead nerve now reads
as silent, not calm. Thirteen tests.
2026-08-15 15:03:46 -04:00
Fimeg
1336960ca5 charge becomes a sensor source
ChargeEvidence was the rule violated four times in one type: a side door
past the gate, the decider probing sysfs on the clock, the driver
interpreting, and nothing leaving tick(). Its comment cited bearer —
another instance of itself.

SensorSource::Charge now enters through sensor_input like every other
source, reported by sensord on a 30s poll off /sys/class/power_supply.
conclude_charge lives on the machine as its one decision; source health,
freshness and Absent/Down come from the gate for free. The 5s clock probe
is gone, the driver type is gone, and sensord ships x86_64 too: the
laptop has a battery.
2026-08-15 11:45:22 -04:00
Fimeg
4662fa1c58 race the subconscious peek against cancel
mid_turn_peek was a bare await while the model call three hundred lines up
was already guarded, so a subconscious that never answered parked the turn
somewhere /cancel could not reach it — twenty minutes, measured 2026-08-15,
on a provider whose key was spent.
2026-08-15 11:20:03 -04:00
Fimeg
7329351f89 claude bridge: strip leading turns as pairs
Compaction can drop the opening user message, and the tool_result
answering the first turn orphans on the wire when its call alone is
deleted — a 400. Calls and the results bound to them go together.
2026-08-15 06:10:08 -04:00
Fimeg
24086b3540 sessiond: carry charging as machine evidence
TASK-33 part 2: the machine owns the conclusion — plugged, status,
charge type, and what it means — probed on the bearer's cadence,
one decision made once on the trail. Surfaces render it; they do
not re-derive it.
2026-08-15 06:10:08 -04:00
Fimeg
0dd8aaaba0 cross last-seen over the wire as seconds-ago per source
TASK-08(f): EvidenceSeen held the stamps internally and nothing outside
the daemon could read them. to_ipc_json now carries
evidence_last_seen_secs_ago; null stays distinct from stale, because
never-reported and long-ago are different claims.
2026-08-15 00:52:52 -04:00
Fimeg
af801b885f fail the pocket veto open on a double-tap burst
suppress_wake is a pure function of placement with no memory, and its
only measured effect was refusing Casey: 17 double-tap refusals in 10 s,
zero true pockets in ~10 MB of trail (DUMP-taskdocs-2026-08-14 §2).
FTS reports DBLTAP only for the deliberate gesture, so three refused
double-taps inside five seconds is a person insisting — the veto now
fails open on the third and says input-burst-allowed in the trail.
Spaced taps never sum; the memory clears on allow.
2026-08-14 20:30:00 -04:00
Fimeg
c31fa10ec9 stop expecting the accelerometer nothing reports
6b67512 unclaimed it for 14% of a core; EXPECTED_SOURCES still listed it,
so every boot went Absent at 300s and sensors_degraded read true on 3074
consecutive snapshots — the permanent false alarm the const's own comment
forbids. It comes back through TASK-36's SLPI batching.
2026-08-14 17:39:03 -04:00
Fimeg
3670b8891e answer the calls a message makes in that same message
turn.rs commits a whole round as one assistant message with calls and
results interleaved; the two-branch projection put the results in prose
and emitted tool_calls nothing answered. Every provider rejects that, on
every turn the primary takes. Shipped in r498.

The suite missed it because all three tests built the split shape through
ConversationMessage::tool_result, which nothing outside tests calls.
2026-08-14 08:20:43 -04:00
Fimeg
1ef8a20a6b route a subagent by its model, not by the default
Both arms took default_provider(), so `model` renamed the request without
rerouting it: kimi-k3 went to Anthropic and came back 404 (2026-08-14).
That was loud by luck — a name the default provider recognises would have
run the wrong model in silence.

The inherit arm was wrong the same way and quietly. An unroutable override
is now refused rather than guessed at, per for_model's own contract.
2026-08-14 08:08:04 -04:00
Fimeg
63ef8e5b55 record a delivered thought before removing it
The removal committed first, so when the sent-write hit the ledger's own
character ceiling the thought left the inbox and was recorded nowhere —
and the caller only logged a warning.

sent.md grew forever against that ceiling, reached at about 47 entries.
It rolls at 30 now; every write is a commit, so nothing is lost.
2026-08-13 22:08:30 -04:00
Fimeg
fab4f2c2f1 replay a tool round as a tool round
Flattening a call to `Tool use: name(args)` told the model she *said* it
when she *did* it; she read her own transcript and imitated the sentence
instead of calling anything. Annie stopped using bash within an hour of
tool blocks first surviving replay (2026-08-13).

Pairs are repaired rather than half-sent: a call killed mid-round gets an
explicit unfinished result, an orphaned result carries as prose.
2026-08-13 21:57:50 -04:00
Fimeg
2a51a236ca replay stored history through one projection
Three implementations decided what a stored message becomes on the wire.
core::session::replay_messages is now the only one; ImagePolicy is the
sole legitimate difference between callers, and server/conversation.rs
was dead scaffolding carrying a fourth wrong answer.

Per-block replay split one assistant turn's several tool calls into
adjacent messages, which OpenAI-shaped providers reject — one wire
message per stored message is load-bearing, not cosmetic (2026-08-13).
2026-08-13 20:39:31 -04:00
Fimeg
a353f1d665 replay tool blocks as prose in cross-turn history
Cross-turn replay kept Text and dropped ToolUse/ToolResult/Reasoning, so a
turn's own tool work was invisible to the turn after it. Measured 215k archive
against 76k payload on a live thread — the gap was the dropped blocks, and
microcompact, which exists to blur old ToolResult output, had nothing left in
the payload to blur. Session::to_bifrost_messages already flattened them for
the subconscious; both paths now share ContentBlock::replay_text.
2026-08-13 16:31:33 -04:00
Fimeg
41c858a5fc read: attach the image, not a stub shaped like success
read base64'd every image into ToolOutput.raw and the registry dropped it,
so vision never arrived — only "[Image: idle.png (283KB)]", which reads
like success and is proceeded on. Images now ride as one user message
after all tool results in a round; a model without vision is told plainly
it did not see. Also stops "Error: Error:" doubling on prefixed failures.
2026-08-13 15:08:26 -04:00
Fimeg
713f3ac1b2 nervous: the belief contract every rung passes upward
Belief<T> and Field. None is not zero: a source that never spoke must
read as I cannot feel my leg, never as nothing is touching it — the
distinction that hid a real outage for a whole boot (2026-07-27).
Disagreement lowers confidence and elects no winner. 13 tests, unwired.
2026-08-13 14:25:34 -04:00
Fimeg
49d9ad543a halt: keep the record, and let her answer it
execute() validated its arguments and returned a string — the description
promised the reason reached the ledger since the tool was written, and
nothing durable ever survived the turn. All three severities also broke
the loop identically, so severity was decorative. Advisory now continues;
firm and critical stop, and `resume` answers them without Casey relaying.
2026-08-13 14:00:01 -04:00
Fimeg
9c0294077b prompt: the subconscious speaks in the first person
Eighteen third-person references across the two prompt surfaces taught
both modes to read as two people. One consciousness at two cadences —
what the slower one surfaces arrives in her own voice, not as a report
from outside. Register only; the channel stays one-directional.
2026-08-13 13:35:54 -04:00
Fimeg
837e024217 the subconscious can come back from an overflow
Once her thread passes the model's ceiling she cannot recover on her
own: every pass is refused at the provider before a single tool round
runs, so she can never reach for memory compact herself. The gauge is
no use to someone already over. She sat dead in that state from
2026-08-11 16:38 until this was found.

Doctrine is that the engine reports pressure and she decides, and that
still holds -- this is not scheduled trimming. It fires only after a
hard overflow, uses her own default strategy (sliding_reflect, which
carries her threads across the cut rather than dropping them blind),
and surfaces what happened in her own voice so the compaction is
something she knows about rather than something done to her quietly.

is_context_overflow matches on wording, not status -- providers
disagree on the code (400 vs 413) and agree on the words. Kept narrow:
a false positive compacts a thread that did not need it, so this
week's 402, 529, max_tokens and connection errors are all asserted
NOT to match. The positive case is the exact body DeepSeek returned at
09:12 today, pasted rather than paraphrased.
2026-08-13 09:42:05 -04:00
Fimeg
877cad006d memory status reports context pressure
Both the primary's and the subconscious's system prompts say 'memory
status shows my context pressure and number of messages'. It showed
neither -- git state only.

This matters most for the subconscious. Her prompt tells her plainly
that no one feels the gauge for her (correct, by design: the engine
warns, it never trims), and points her at memory status to read it
herself. With status blind she had no gauge at all, from either
direction: pressure_for is only ever computed for the primary. She
grew to 1.75M tokens against a 1M ceiling and died at the provider.

- PressureSnapshot + CompactionEngine::pressure
- get_context_limit follows the model, not the primary -- the
  subconscious runs a different model, so her ceiling differs
- tier() mirrors the engine's 0.80/0.90/0.95 marks so the two gauges
  cannot disagree about full
- None when there is no session: absence, not zero

Also corrects the compact help text, which named
primary=sliding_window/subconscious=sliding_window against
config.rs's actual cull/sliding_reflect.
2026-08-13 09:35:01 -04:00
Fimeg
764a4b8e35 pressure: calculate_pressure counts every block kind
Was Text-only, blind to tool_use/tool_result/reasoning — ~74% of a real
thread. This is the number behind the 80/90/95 tier warnings and the
archivist's emergency trigger, so both fired late or not at all.

countable_text() (7530d6d) is exhaustive. turn.rs::bifrost_pressure is
still a second counter and still blind to tool_calls by shape; collapsing
the two is not done.
2026-08-12 21:11:48 -04:00
Fimeg
29f847544c halt: the migraine reaches the primary, not just the surface
migraine_text built a felt sentence in her own register, pushed it onto
the Bifrost message vec, and then `break` exited the loop — no further
completion call, vec dropped. Correct wording, correct voice, delivered
nowhere.

The old comment claimed the migraine "rode the event channel" and the
ledger held the reasoning. Neither reaches her: the event channel goes
outward to the human's surface, and the mid-turn peek is ephemeral by
design so no ledger entry exists. The one reader the sentence was
written for was the only one who never received it. She stopped without
learning why and could not resume without the human relaying it back.

The raised-hand path already had this right — it commits its marker so
she reads it next turn and can acknowledge, wrap up, or ask for more
time. The halt now does the same, committing the felt sentence itself
rather than a harness marker naming a tool.

Removing the `*[subconscious HALT]*` marker fixed a real resume
corruption bug, but removing the signal with it was an overcorrection:
the defect was the marker's shape, not the existence of a signal.

No Token event accompanies the commit — the surface already received
SubconsciousHalt and would otherwise render the same moment twice.
2026-08-12 18:50:55 -04:00