# akicita
Bounded autonomy for self-acting systems. Named for the *akicita*, the Lakota camp marshals who policed the warriors **within** the tribe during the hunt — internal enforcement with bounded authority.
Extracted from Bad Apple's Curious self-improvement loop, generalized for any system that proposes and applies changes to itself: agents, daemons, robots, autopilots.
## The ladder
| `off` | Nothing runs. Proposals denied. |
| `suggest` | Proposals recorded for human review. Nothing applied. |
| `safe-apply` | In-bounds proposals on unprotected surfaces apply automatically. |
| `full` | Same, without the safe-apply surface restriction — **protected surfaces are still never auto-applied.** |
Protected surfaces are hard boundaries, not level settings: a proposal touching one is *proposed and logged for human review* at every level. Some doors only a human opens.
## What the marshal enforces
- **Autonomy ladder** — persisted to disk, re-read live so a human can lower autonomy mid-run.
- **Protected surfaces** — basenames and path prefixes that never auto-apply.
- **Blast-radius caps** — max lines/bytes per proposal; oversize *holds* (it isn't denied, it's escalated).
- **Rate limits** — minimum interval between automatic applications.
- **Dedupe** — a proposal already decided isn't refiled.
- **Journal** — every decision lands as NDJSON. Refusals are as much the record as permits.
## Usage
```rust
use akicita::{Akicita, Config, Decision, Level, Proposal};
use std::path::PathBuf;
let mut config = Config::default();
config.protected_basenames.insert("PolicyEngine.rs".into());
config.max_lines = 20;
config.max_bytes = 1_000;
config.journal_path = Some(PathBuf::from("marshal_journal.ndjson"));
let marshal = Akicita::new(
Level::SafeApply,
config,
Some(PathBuf::from("autopilot_level")),
);
let patch = Proposal::patch(
"src/feature.rs",
"// old code",
"// new code",
"replace stub with implementation",
);
match marshal.check(&patch) {
Decision::Permit => apply(&patch),
Decision::Hold { reason } => record_for_human(&reason),
Decision::Deny { reason } => drop_and_log(&reason),
}
```
See `examples/marshal.rs` for the full walk.
## Origin
Bad Apple's self-improvement loop applies bounded patches to its own source — capped at 20 lines / 1000 bytes, one per run, with protected control files it can never touch automatically and a dedupe so rejected proposals aren't refiled. The marshal pattern survived nightly operation; this crate is the extracted organ.
## License
MIT