akicita 0.1.1

Bounded autonomy for self-acting systems: an autonomy ladder (off/suggest/safe-apply/full), protected surfaces that never auto-apply, blast-radius caps, rate limits, and dedupe — named for the Lakota camp marshals who kept warriors inside the bounds
Documentation
# 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

| Level | Behavior |
|---|---|
| `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