Ignore legacy grace metadata in both activation paths. Keep superseded delivery,
admission ordering, discovery exclusion and the separate EOF stop budget.
Document the uniform policy and cover both windows and opt-in drain.
Card: SAU-357
Keep one registration and restart owner across process cleanup and upgrades.
Restart on failed process exit before or after readiness; give up after more
than five crashes in a sliding ten-second window. Respect explicit stop and
shutdown, and suppress boot-service fallbacks from retired hooks.
Cover deterministic lifetime, boundary, give-up and admission races, plus
real WASI failures on both sides of readiness. Document the host contract.
Card: SAU-358
Send rpc.superseded with the newly active hash before activation returns.
Add an opt-in SDK hook and drain helper that closes SDK listeners and idle
connections without cancelling active handlers or background work.
Document the additive notice and preserve existing grace, stop and restart rules.
Cover immediate notices, ignored notices, early service restarts, SDK draining
and duplicate-hook diagnostics.
Card: SAU-352
128 fast activate/revert cycles are not a realistic load. restarts_service
covers the restart of a service after an upgrade. nix flake check runs
the normal tests only.
The timing rules are in two tests (upgrade_and_discovery_deadlines,
stop_deadlines). All other tests use a grace period of 0 or core.stop,
poll with deadlines instead of sleeping, and use the persistent cache in
CARGO_TARGET_TMPDIR. The 128-cycle singleton test is an ignored stress
test that nix flake check runs; the normal run has a 4-cycle sample.
Warm, the activation suite takes 12 s (was 47 s), and cargo test
--workspace takes 65 s.
cargo.build and the runner (review T22R): builds use the network again;
core.unlock and core.notify in order under the runner; quiet test
output; manifest preparation keeps [workspace], target tables, renamed
and optional entries; cargo.rpc.discover; -32004 with data.output;
retention of 10 builds; light, empty test worlds with an in-memory
journal; only CARGO_/RUST_/SAUSAGE_ variables; stdin is null; the runner
through --config. A compile cache that cannot be created is not fatal.
Activation replaces plugin.wasm without a gap.
Console and main: init ships the workspace Cargo.lock and creates the
world atomically; each console command runs in its own task, so ps,
stop, and kill work during a slow call; SAUSAGE_HEADLESS; the terminal
mode is restored; signals during boot; chat text is not taken as a
command.
Tests: 20 more tests for PROTOCOL.md sections 2 to 10; the cargo tests
choose the libtest binary from cargo's JSON output and time out.
Activation path (review T6R): a broken plugin or a stray file in
/plugins blocks no activation; candidates replace their own entries;
discovery has a 10 s deadline and its process is stopped after the
answer; an unchanged hash keeps plugin.prev.wasm; activations run in
their own task; the watcher is not recursive; no duplicate services;
rpc.retired waits for live processes of its version; reads and hashes
on blocking threads.
Guest I/O and per-call paths: a stdin write error is EOF, stdout and
stderr are drained before the status; stderr is lossy UTF-8 and goes
to the journal from its own reader; compiled components are freed;
shutdown starts no new processes; lock queues drop stopping processes;
compile before the admission gate; CommandPre per component;
core.unlock in order; null errors are successes; the journal thread
survives SQLite errors.
sausage init builds the agent with cargo.build; sausage without a
command creates ./world. The console reads plain lines without a
terminal. PROTOCOL.md and DECISIONS.md describe the decided rules. The
flake tests the whole workspace and checks the packaged cargo.build.
- /proc is a core layer: core/ (PROTOCOL.md, graph.json, graph.dot,
locks.json, plugins/<name>/discover.json and client.rs) and one folder
per process (info.json, log, and its /self files).
- Locks are released only after the task ended, the store dropped, and
in-flight file operations returned.
- core.activate and core.revert with copies, discovery, compatibility
checks of imports and consumers, groups, force. An admission gate
makes the snapshot of old processes complete.
- Graph of discover documents by hash, refreshed by a file watcher.
- Upgrades: grace periods (x-sausage-grace), stop, service restarts,
rpc.retired.
- SDK plugins in the real core (cli/tests/sdk.rs).