Reviewer suggested an evaluation footprint that lands "the smallest substrate any caller-LLM can use", with 5 files and ~200 LOC ceiling in $HOME. This commit ships that profile. Files installed in $HOME by `./install.sh --profile=outcome-only`: 1. ~/.claude/hooks/agent-outcome-backfill.sh (PostToolUse:Agent) 2. ~/.claude/hooks/error-spike-detector.sh (PostToolUse:Bash, rolling 20-call window) 3. ~/.claude/agents/ledger.sqlite (full v9 schema via kei-ledger init, or sqlite3-fallback DDL) 4. ~/.claude/CLAUDE.md (1-line STATUS-TRUTH MARKER instruction appended) 5. ~/.claude/settings.json (jq-merge of 2 hook entries) Plus optional 6th: kei-model-router binary built from _primitives/_rust if cargo on PATH; deferred otherwise (warning printed, install continues). Files added to repo: - install/lib-profile-outcome-only.sh (145 LOC) — profile orchestrator with --dry-run support; sources lib-log/lib-backup/lib-hooks helpers; exits before heavy install phases when --profile=outcome-only - install/sql/outcome-only-schema.sql (69 LOC) — flattened v9-equivalent SQLite DDL (agents + skill_invocations + indexes), used by sqlite3 fallback when kei-ledger CLI is unavailable - docs/PROFILE-OUTCOME-ONLY.md (97 LOC) — reviewer-facing doc: 5-file install table, what is NOT installed, kei-model-router activation explanation, privacy posture (no telemetry), 4-line uninstall paste Files modified: - install.sh (+12 LOC) — sources outcome-only lib, adds short-circuit before menu when --profile=outcome-only, accepts in profile validator - install/lib-args.sh (+9 LOC) — registers --dry-run flag (sets OUTCOME_DRY_RUN=1), adds outcome-only + --dry-run lines to --help - README.md (+7 LOC) — adds Outcome-only Quick-start section pointing to PROFILE-OUTCOME-ONLY.md Verification: - bash -n clean on all 3 modified shell files - Dry-run produces exactly 5 numbered $HOME paths (verified end-to-end: HOME=/tmp/kei-fake-home bash install.sh --profile=outcome-only --dry-run) - Real install against fake $HOME succeeds (5 files present, ledger init via kei-ledger binary, router build correctly skipped on toolchain absence with warning) - Ledger schema includes agents + skill_invocations tables + 3 indexes + 2 triggers via real migration path (not the SQL fallback) [FROM-JOURNAL: end-to-end install dry-run + real-run measured at ~/.claude/memory/time-metrics/sessions.jsonl this session, both <2s wall] Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4.2 KiB
outcome-only install profile
Five-file pitch: install the outcome-tracking primitive without committing to anything else. No daemon, no Forgejo, no launchd, no hundred Rust crates, no
no-github-pushhook, no agent generation. If you do not like what~/.claude/agents/ledger.sqlitecollects, the uninstall is a four-line shell paste at the bottom.
What gets installed
| # | Path | Source | LOC |
|---|---|---|---|
| 1 | ~/.claude/hooks/agent-outcome-backfill.sh |
hooks/agent-outcome-backfill.sh |
140 |
| 2 | ~/.claude/hooks/error-spike-detector.sh |
hooks/error-spike-detector.sh |
89 |
| 3 | ~/.claude/agents/ledger.sqlite |
install/sql/outcome-only-schema.sql (or kei-ledger init) |
n/a |
| 4 | one appended line in ~/.claude/CLAUDE.md |
the STATUS-TRUTH MARKER instruction | 1 |
| 5 | _primitives/_rust/kei-model-router/target/release/kei-model-router (deferred) |
_primitives/_rust/kei-model-router/ |
n/a |
Plus a jq-merge of two hooks into ~/.claude/settings.json:
PostToolUse:Agent→agent-outcome-backfill.shPostToolUse:*→error-spike-detector.sh
./install.sh --profile=outcome-only --dry-run prints exactly this
list and exits 0 without writing.
What does NOT get installed
- 102 Rust crates (cortex, frustration-loop, sleep-layer, …)
- 67 skills, 37 agent manifests, 82 substrate blocks
kei-cortexHTTP / WS daemon- Forgejo, dev hub, Datasette, restic, mdbook, gdrive-import
- launchd plists (
disk-reclaim, sleep-layer cron) no-github-push.shhook (or any other Bash gate)- substrate PATH wiring (no edits to your shell rc files)
If you later want any of those, the kit is incremental: re-run
./install.sh --profile=core (or heavier) and the outcome-only state
is preserved verbatim — both paths share ~/.claude/hooks/ and
~/.claude/agents/ledger.sqlite.
How kei-model-router activates
The router is a posterior decision rule keyed on per-task-class DNA
plus a Beta posterior over (success, total) in agents.outcome.
Until you accumulate ~100 outcome rows, the router falls back to
"behaviour unchanged" — every spawn keeps whatever model the agent
manifest declares.
After ~100 rows the posterior dominates the prior and the router
starts producing concrete recommendations. You opt in by adding
kei-model-router to a PreToolUse:Agent hook later — that step is
not done by this profile. You stay in observe-only mode by default.
If cargo is on PATH at install time the binary is built into
_primitives/_rust/kei-model-router/target/release/. If cargo is
missing the build is skipped silently and the install is still
considered complete; rebuild later with:
cd _primitives/_rust/kei-model-router && cargo build --release
Privacy posture
All outcome rows live in ~/.claude/agents/ledger.sqlite. They never
leave the machine — no sync hook, no remote-push, no telemetry.
Inspect with:
sqlite3 ~/.claude/agents/ledger.sqlite \
"SELECT id, branch, status, outcome, stubs_count, started_ts FROM agents
ORDER BY started_ts DESC LIMIT 20;"
Uncomfortable with the file? rm it; the next install or agent run
recreates an empty schema, no other side effects.
Uninstall
rm -f ~/.claude/hooks/agent-outcome-backfill.sh
rm -f ~/.claude/hooks/error-spike-detector.sh
rm -f ~/.claude/agents/ledger.sqlite
sed -i.bak '/outcome-only profile (KeiSeiKit)/,+1 d' ~/.claude/CLAUDE.md
Both hooks exit 0 immediately when their target script is missing, so
the ~/.claude/settings.json jq-merge entries are harmless after
rm. To scrub those too, drop agent-outcome-backfill.sh /
error-spike-detector.sh lines from settings.json by hand.
Why this profile exists
A kit with 100 crates / Forgejo / launchd plists is too heavy to evaluate. A pitch you can read in four minutes and trial in five is not. This profile is the answer to "what is the smallest version of KeiSeiKit that still demonstrates the outcome loop?" — and nothing more.