KeiSeiKit-1.0/docs/PROFILE-OUTCOME-ONLY.md
Parfii-bot c9dc94393c feat(install): outcome-only minimum profile
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>
2026-05-03 16:59:53 +08:00

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-push hook, no agent generation. If you do not like what ~/.claude/agents/ledger.sqlite collects, 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:Agentagent-outcome-backfill.sh
  • PostToolUse:*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-cortex HTTP / WS daemon
  • Forgejo, dev hub, Datasette, restic, mdbook, gdrive-import
  • launchd plists (disk-reclaim, sleep-layer cron)
  • no-github-push.sh hook (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.