12-agent audit (waves 3+4 Opus+Sonnet) on commit88de01cfound that 2 of my prior fixes had regressions, plus the prev batch missed 8 stale-text sites and 2 latent bugs. This batch closes them all. == Regressions in audit-batch (88de01c) — now fixed == 1. PRAGMA user_version=9 placement — could silently downgrade schema on cross-version install (existing v10 DB → re-run reset to 9 → migrations replay → ALTER TABLE duplicate-column errors) - install/sql/outcome-only-schema.sql: PRAGMA moved OUTSIDE the transaction (after COMMIT) for portability across SQLite versions - install/lib-profile-outcome-only.sh::_outcome_install_ledger: added downgrade guard — reads existing user_version BEFORE running ANY init path; if >9, skips entirely (preserves newer schema) - VERIFIED: simulated v10 DB → re-run prints "skipping init to preserve newer schema"; user_version stays at 10 (was downgraded to 9 in the prior batch) [REAL: ran in this session] 2. backup_file mv→cp workaround left orphan backups + bypassed rollback contract (BACKUP_PAIRS not registered) - install/lib-profile-outcome-only.sh: now manually appends to BACKUP_PAIRS so rollback trap restores on later failure; removes the .bak on success path - Comment updated to explain the workaround vs backup_file mv 3. CLAUDE.md skip-guard "STATUS-TRUTH MARKER" was too broad — false-positive on existing kit users (RULE 0.16 doc text matches) - lib-profile-outcome-only.sh: changed grep to literal HTML comment marker `<!-- outcome-only profile (KeiSeiKit) -->` (specific marker written by the installer itself) == Tier 1 missed in prev batch — now fixed == 4. _ts_packages/package-lock.json referenced packages/cortex-ui which does NOT exist on disk → npm ci would fail with ELSPROBLEMS in CI - Regenerated via fresh `rm package-lock.json && npm install` - npm ci now exits 0 cleanly [REAL: ran in this session] - Lockfile shrunk 2403→0 lines on the cortex-ui section (full regen) 5. v3 triggers (branch length cap ≤256) were MISSING from outcome-only-schema.sql — sqlite3 fallback path skipped a schema feature that the Rust kei-ledger flow enforces, creating cross-flow drift - Added trg_agents_branch_len_ins + trg_agents_branch_len_upd mirroring migrations_list.rs:30-44 - Header comment in outcome-only-schema.sql rewritten to match current behavior (was stale) - VERIFIED: end-to-end install creates 2 triggers [REAL: sqlite3 .schema | grep trg_agents_branch_len returns 2] 6. README.md:232 said "102 crates" while README.md:9 said "105 crates" — internal contradiction in same doc - README:232 → "105 workspace crates" 7. ARCHITECTURE.md:165 "53 Rust crates + 13 shell primitives" stale - Updated to "105 Rust workspace crates (47 declared in MANIFEST.toml `full` profile) + 14 shell primitives" 8. ARCHITECTURE.md:157 "45 /commands" stale - Updated to 68 9. plugin.json + marketplace.json description strings still had pre-fix counts (23 primitives / 39 skills / 9 hooks / 12 agents) - Both rewritten to match README:9 SSoT (38 agents / 68 skills / 38 hooks / 105 workspace crates / 47 installable + 14 shell) 10. PROFILE-OUTCOME-ONLY.md:28-29 "What does NOT get installed" still cited 102/67/37/82 - Updated to 105/68/38/85 11. encyclopedia/substrate-overview.md §6/§11/§12 still said "80-char DNA"; §13 said "495 DNA indices"; §6 said "11 install profiles (.../Cursor/Continue/etc)" - All 4 sites fixed to current language (≥33-char variable, 565 DNAs, 12 install profiles) 12. docs/DNA-INDEX.md:1352 said wire format is "(80 chars)" - Updated to "(≥33 chars; role + caps slugs are variable — see docs/DNA-FORMAT.md)" == Tier 2 honesty fixes == 13. Wagner et al. 2004 citation in SLEEP-LAYER.md:26 lacked [VERIFIED] marker (W3 doc consistency caught it) - Added [VERIFIED: doi:10.1038/nature02223] + clarification that the original study did not isolate a specific sleep stage; SWS attribution comes from secondary literature (Diekelmann/Born) 14. PHILOSOPHY.md:125 attributed "overnight consolidation of un-finished intentions" to Wagner 2004 — that paper is about insight gain on the Number Reduction Task, not Zeigarnik-effect cued memory - Rewritten to accurately describe Wagner 2004's actual finding + [VERIFIED: doi:10.1038/nature02223] Verification: - `npm ci` in _ts_packages/ exits 0 [REAL: ran in this session] - `cargo check --workspace` exits 0 in _primitives/_rust [REAL: ran in this session] - Outcome-only end-to-end fresh install produces user_version=9 + 2 triggers (correct schema shape) - Outcome-only re-run against v10 DB preserves user_version=10 (downgrade guard works) - CLAUDE.md skip-guard now triggers ONLY on literal marker, not on RULE 0.16 phrase NOT addressed in this batch (deferred to a future round): - github KeiSei84/{KeiSeiKit, KeiSeiKit-1.0} 404 (user-side action: publish repo or update refs) - keigit user `keisei` does not exist (user-side: create org or rename scope) - KEIGIT_TOKEN secret not configured (user-side action) - Forgejo registration disabled (admin-side) - safeEqual timing leak in TS server (LOW per W3 reassessment) - HTTP bind 0.0.0.0 default (MEDIUM) - Unbounded request body (MEDIUM) - Outcome-only confirm-screen bypass (RULE 0.1 spirit) - Ledger fallthrough false summary - Node 20 deprecation (deadline 2026-06-02, 30 days) - Hook count triple-discrepancy (38 README / 53 DNA-INDEX / 35 maturity-row) - 100-row router claim still in README:117 + PROFILE-OUTCOME-ONLY.md - INSTALL.md numerics without [REAL:] markers - Stale .bak files accumulation policy (cosmetic) - README per-claim [REAL: ] markers for 6 of 7 numerics Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4.9 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
- 105 Rust workspace crates (cortex, frustration-loop, sleep-layer, …)
- 68 skills, 38 agent manifests, 85 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
rm -f ~/.claude/memory/time-metrics/agent-toolstats.jsonl
# CLAUDE.md cleanup — portable across BSD (macOS) and GNU sed via awk.
# The original line `sed -i.bak '/.../,+1 d'` used the GNU `,+N` address
# extension which BSD sed does NOT support; on macOS it silently no-ops,
# leaving an orphan instruction. The awk recipe below works on both.
awk 'BEGIN{skip=0} /<!-- outcome-only profile \(KeiSeiKit\) -->/ {skip=2; next} skip>0 {skip--; next} {print}' \
~/.claude/CLAUDE.md > ~/.claude/CLAUDE.md.tmp \
&& mv ~/.claude/CLAUDE.md.tmp ~/.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.
The 5th rm removes the sidecar telemetry JSONL the backfill hook
writes (per-agent token counts + tool stats; local-only, no network
egress, but worth deleting if you uninstalled for privacy reasons).
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.