Files
Skald-Circle/docs/self-rewriting.md
T
2026-07-10 15:02:09 +01:00

78 lines
4.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Self-Rewriting
## Restart Mechanism
The `restart` tool has **two modes**, branched on the `desktop` cargo feature:
| Mode | Behaviour | Triggers |
|---|---|---|
| **Headless** (`cargo run`, `run.sh`, Docker) | `libc::_exit(-1)` → exit code `255`. `run.sh` detects `255` and re-executes `cargo run`, which recompiles changed source files and relaunches. The supervisor is the only thing that can rebuild the binary. | The agent edited `src/**/*.rs` or `Cargo.toml` and wants the new code loaded. |
| **Desktop** (`--features desktop`, Tauri bundle) | `AppHandle::cleanup_before_exit()` (Tauri-side teardown) → `Command::new(current_exe).spawn()``std::process::exit(0)`. The same read-only bundled binary is relaunched — **no rebuild** (there is no source tree to rebuild from). | The user/agent wants to apply `config.yml` / DB changes that are only read at startup. Self-modification of `src/**/*.rs` has no effect in a bundle. |
The headless exit code `255` (`-1`) deliberately uses `libc::_exit()` rather
than `std::process::exit()` to skip C `atexit` handlers (e.g. Metal GPU cleanup
in `whisper-rs`, which would crash with SIGABRT and produce `134` instead of
`255`).
See [desktop.md](desktop.md) for the desktop-bundle architecture and the
`desktop::app_handle()` OnceLock that lets the tool reach the `AppHandle`.
---
## run.sh Exit Codes
| Exit code | Meaning | run.sh action |
|---|---|---|
| `0` | Graceful shutdown — SIGINT (Ctrl+C) **or** SIGTERM, both trapped in `main.rs` | Stop loop, exit 0 |
| `255` | Restart requested (`exit(-1)`) | `cargo run` again (recompile) |
| `143` | SIGTERM with no handler (`128+15`) — no longer reachable; see note | Stop loop, propagate code |
| other | Unexpected error (e.g. `101` panic) | Stop loop, propagate code |
`main.rs` traps **both** SIGINT and SIGTERM (`wait_for_shutdown_signal`) and runs the graceful shutdown path, so an external `kill` now exits `0` and logs `signal=SIGTERM` instead of dying silently with code `143`. To force a restart, use the `restart` tool (exit `255`) — never `kill` the process.
> The `run.sh` supervisor and exit-code table above apply only to **headless
> mode**. In desktop mode there is no supervisor; the Tauri process manages its
> own lifecycle and exit code `0` simply terminates the app.
---
## Safe Self-Modification Workflow
1. **Read** the relevant source files with `read_file` before making any changes.
2. **Edit** source files (`edit_file`, `write_file`, etc.).
3. **Check**: `execute_cmd` with command `cargo check 2>&1`. Inspect output.
4. **Fix** any compiler errors. Repeat steps 23 until clean.
5. **Restart**: call the `restart` tool only after a clean `cargo check`. The app rebuilds and relaunches automatically.
Never skip the `cargo check` step. A broken build will crash the supervisor loop with a non-zero non-255 exit code, stopping the app entirely.
---
## Requires Restart vs Does Not
| Change | Restart required? |
|---|---|
| `src/**/*.rs` | **Yes** |
| `Cargo.toml` / `Cargo.lock` | **Yes** |
| `agents/*/AGENT.md` | No — read at request time |
| `agents/*/meta.json` | No — read at request time |
| `config.yml` | No — read at startup only; take effect on next restart |
| `data/memory/**` | No — read at request time |
| `docs/**` | No |
---
## Risk Points
- **Never call `restart` mid-approval flow.** If a `PendingWrite` is waiting for user input, calling `restart` drops the `oneshot` sender, which unblocks the handler with an `Err` — the approval is cancelled and the tool call is aborted. Wait for the approval to resolve first.
- **Always check build before restart.** A compilation failure with `cargo run` returns a non-255 exit code, causing `run.sh` to stop the loop rather than retry.
- **`execute_cmd` requires user approval.** The user must approve the shell command in the UI before it executes.
---
## When to Update This File
- The restart mechanism or exit codes change
- The safe-modification workflow gains or loses a step
- New file types are added that do/don't require a restart