fix(audit-batch-2): regressions from prev batch + 2nd-wave audit findings
12-agent audit (waves 3+4 Opus+Sonnet) on commit3759fb0found 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 (3759fb0) — 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>
This commit is contained in:
parent
3759fb0f64
commit
784dfbae6f
12 changed files with 117 additions and 2313 deletions
|
|
@ -15,7 +15,7 @@
|
||||||
"source": "github",
|
"source": "github",
|
||||||
"repo": "KeiSei84/KeiSeiKit"
|
"repo": "KeiSei84/KeiSeiKit"
|
||||||
},
|
},
|
||||||
"description": "Full KeiSeiKit — 12-agent fleet, 39 skills, 9 hooks, 23 Rust primitives, sleep-sync cloud consolidation, MCP server layer"
|
"description": "Full KeiSeiKit — 38 agent manifests, 68 skills, 38 hooks, 105 Rust workspace crates (47 installable primitives via MANIFEST.toml `full` profile + 14 shell primitives), sleep-sync cloud consolidation, MCP server layer"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "keisei",
|
"name": "keisei",
|
||||||
"version": "0.16.0",
|
"version": "0.16.0",
|
||||||
"description": "Constructor-Pattern agent kit for Claude Code: composable behavioral blocks, 23 Rust primitives, 39 portable skills, 9 pre-wired hooks, typed artifact handoff, sleep-sync cloud consolidation, MCP server layer.",
|
"description": "Constructor-Pattern agent kit for Claude Code: 38 agent manifests, 68 portable skills, 38 hooks, 105 Rust workspace crates (47 installable primitives + 14 shell primitives via MANIFEST.toml `full` profile), typed artifact handoff, sleep-sync cloud consolidation, MCP server layer.",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "KeiSei",
|
"name": "KeiSei",
|
||||||
"url": "https://github.com/KeiSei84"
|
"url": "https://github.com/KeiSei84"
|
||||||
|
|
|
||||||
|
|
@ -229,9 +229,9 @@ Orchestrator skill `landing-page` composes 11 skills across 6 recipes
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
Stack: **Rust core** (102 crates, ≤2 MB each, 12-trait runtime + plugin
|
Stack: **Rust core** (105 workspace crates, ≤2 MB each, 12-trait runtime
|
||||||
registry) + **TypeScript glue** (6 adapters: gmail / grok / recall /
|
+ plugin registry) + **TypeScript glue** (6 adapters: gmail / grok /
|
||||||
telegram / youtube / mcp-server). Backend impls cover:
|
recall / telegram / youtube / mcp-server). Backend impls cover:
|
||||||
|
|
||||||
| Trait | Impls |
|
| Trait | Impls |
|
||||||
|---|---|
|
|---|---|
|
||||||
|
|
|
||||||
2295
_ts_packages/package-lock.json
generated
2295
_ts_packages/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -154,7 +154,7 @@ The substrate is layered. Each layer has a single contract; layers below are sta
|
||||||
│ @keisei/vscode-cortex · MCP clients (Cline, OpenClaw, Cursor MCP) │
|
│ @keisei/vscode-cortex · MCP clients (Cline, OpenClaw, Cursor MCP) │
|
||||||
├──────────────────────────────────────────────────────────────────────────┤
|
├──────────────────────────────────────────────────────────────────────────┤
|
||||||
│ Layer 3 — Skills (markdown wizards) │
|
│ Layer 3 — Skills (markdown wizards) │
|
||||||
│ 45 `/commands` under skills/<name>/SKILL.md │
|
│ 68 `/commands` under skills/<name>/SKILL.md │
|
||||||
│ Each is an AskUserQuestion-driven phase-pipeline (5-9 phases typical) │
|
│ Each is an AskUserQuestion-driven phase-pipeline (5-9 phases typical) │
|
||||||
├──────────────────────────────────────────────────────────────────────────┤
|
├──────────────────────────────────────────────────────────────────────────┤
|
||||||
│ Layer 2 — Recipes (TOML DAGs) │
|
│ Layer 2 — Recipes (TOML DAGs) │
|
||||||
|
|
@ -162,8 +162,8 @@ The substrate is layered. Each layer has a single contract; layers below are sta
|
||||||
│ Runtime: kei-pipe │
|
│ Runtime: kei-pipe │
|
||||||
├──────────────────────────────────────────────────────────────────────────┤
|
├──────────────────────────────────────────────────────────────────────────┤
|
||||||
│ Layer 1 — Primitives (cubes) │
|
│ Layer 1 — Primitives (cubes) │
|
||||||
│ 53 Rust crates + 13 shell primitives │
|
│ 105 Rust workspace crates (47 declared in MANIFEST.toml `full` profile)│
|
||||||
│ Each ≤ 200 LOC per file, ≤ 30 LOC per function (Constructor Pattern) │
|
│ + 14 shell primitives. Each ≤ 200 LOC / file, ≤ 30 LOC / function. │
|
||||||
├──────────────────────────────────────────────────────────────────────────┤
|
├──────────────────────────────────────────────────────────────────────────┤
|
||||||
│ Layer 0 — Atoms (locked vocabulary) │
|
│ Layer 0 — Atoms (locked vocabulary) │
|
||||||
│ 13 verbs: INGEST PARSE TRANSFORM ENRICH VALIDATE DECIDE DISPATCH │
|
│ 13 verbs: INGEST PARSE TRANSFORM ENRICH VALIDATE DECIDE DISPATCH │
|
||||||
|
|
|
||||||
|
|
@ -1349,6 +1349,6 @@ Sorted alphabetically by name.
|
||||||
|
|
||||||
## Schema notes
|
## Schema notes
|
||||||
|
|
||||||
- `dna` wire format: `<block_type>::<caps>::<scope_sha8>::<body_sha8>-<nonce8>` (80 chars).
|
- `dna` wire format: `<block_type>::<caps>::<scope_sha8>::<body_sha8>-<nonce8>` (≥33 chars; role + caps slugs are variable — see docs/DNA-FORMAT.md).
|
||||||
- Active vs superseded: rows where `superseded_by IS NULL` are active.
|
- Active vs superseded: rows where `superseded_by IS NULL` are active.
|
||||||
- See `_primitives/_rust/kei-shared/src/dna.rs` for canonical DNA spec.
|
- See `_primitives/_rust/kei-shared/src/dna.rs` for canonical DNA spec.
|
||||||
|
|
|
||||||
|
|
@ -122,10 +122,13 @@ Claude Code agent on Anthropic's cloud picks up the queue (up to 480
|
||||||
minutes total across ≤ 5 tasks, packed greedily in FIFO order) and
|
minutes total across ≤ 5 tasks, packed greedily in FIFO order) and
|
||||||
works until the budget or checkpoint fires.
|
works until the budget or checkpoint fires.
|
||||||
|
|
||||||
Biological analog: the overnight consolidation of un-finished intentions
|
Biological analog: the post-sleep insight gain documented by
|
||||||
(Wagner et al. 2004, *Nature*). Things unsolved when you fell asleep are
|
Wagner et al. 2004, *Nature* 427:352–355
|
||||||
often solved by morning not because the brain ran harder, but because
|
[VERIFIED: doi:10.1038/nature02223]. The original paper showed that
|
||||||
it ran offline.
|
problems unsolved when you went to bed are sometimes solved on waking
|
||||||
|
not because the brain ran harder but because it ran offline; the study
|
||||||
|
did not isolate a specific sleep stage, and our metaphor is a loose
|
||||||
|
mapping of that observation onto the kit's offline consolidation.
|
||||||
|
|
||||||
### Phase B — REM consolidation
|
### Phase B — REM consolidation
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@ list and exits 0 without writing.
|
||||||
|
|
||||||
## What does NOT get installed
|
## What does NOT get installed
|
||||||
|
|
||||||
- 102 Rust crates (cortex, frustration-loop, sleep-layer, …)
|
- 105 Rust workspace crates (cortex, frustration-loop, sleep-layer, …)
|
||||||
- 67 skills, 37 agent manifests, 82 substrate blocks
|
- 68 skills, 38 agent manifests, 85 substrate blocks
|
||||||
- `kei-cortex` HTTP / WS daemon
|
- `kei-cortex` HTTP / WS daemon
|
||||||
- Forgejo, dev hub, Datasette, restic, mdbook, gdrive-import
|
- Forgejo, dev hub, Datasette, restic, mdbook, gdrive-import
|
||||||
- launchd plists (`disk-reclaim`, sleep-layer cron)
|
- launchd plists (`disk-reclaim`, sleep-layer cron)
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ Day →→→ │ Phase A Phase B Phase C │ →
|
||||||
<uuid>.md (always) (every N days)
|
<uuid>.md (always) (every N days)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Biological analog.** Your Mac is the hippocampus (fast, stateful, volatile — captures raw episodes). The memory-repo is the transport layer. The cloud agent is the neocortex (slow, stateless, generalising). The morning `git pull` is the recall. Phase A mirrors the "sleep on it" effect (Wagner et al. 2004, *Nature*), Phase B mirrors REM dream-state pattern extraction, Phase C mirrors NREM slow-wave system consolidation.
|
**Biological analog.** Your Mac is the hippocampus (fast, stateful, volatile — captures raw episodes). The memory-repo is the transport layer. The cloud agent is the neocortex (slow, stateless, generalising). The morning `git pull` is the recall. Phase A mirrors the "sleep on it" insight effect (Wagner et al. 2004, *Nature* 427:352–355 [VERIFIED: doi:10.1038/nature02223]; the original study did not isolate a specific stage — secondary literature attributes the effect primarily to slow-wave sleep, our mapping is loose). Phase B mirrors REM dream-state pattern extraction. Phase C mirrors NREM slow-wave system consolidation.
|
||||||
|
|
||||||
**Phase interaction rules (important):**
|
**Phase interaction rules (important):**
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -210,11 +210,11 @@ KeiSeiKit is a **multi-tier agent composition substrate** built on four mutually
|
||||||
| **ARCHITECTURE.md** | Stack overview + trait impl matrix | Compute/Git/Memory/Auth/Notify/Network/LLM/ServiceManager impls per backend |
|
| **ARCHITECTURE.md** | Stack overview + trait impl matrix | Compute/Git/Memory/Auth/Notify/Network/LLM/ServiceManager impls per backend |
|
||||||
| **AGENT-ROLES.md** | Generated role matrix (human-readable) | 7 roles × capabilities × tools × escalation (auto-generated from _roles/*.toml) |
|
| **AGENT-ROLES.md** | Generated role matrix (human-readable) | 7 roles × capabilities × tools × escalation (auto-generated from _roles/*.toml) |
|
||||||
| **PHILOSOPHY.md** | Substrate philosophy + design principles | Single-source-of-truth, Constructor Pattern, no overlays, decomposability |
|
| **PHILOSOPHY.md** | Substrate philosophy + design principles | Single-source-of-truth, Constructor Pattern, no overlays, decomposability |
|
||||||
| **DNA-INDEX.md** | Agent DNA (deterministic identity) format | 80-char DNA breakdown: role::caps::scope-sha8::body-sha8-nonce |
|
| **DNA-INDEX.md** | Agent DNA (deterministic identity) format | ≥33-char variable-length DNA breakdown: role::caps::scope-sha8::body-sha8-nonce |
|
||||||
| **IMPORT-RUNTIME.md** | Foreign-project ingestion pipeline | Decompose → match → extract skills → plan → execute (Hermes proof-of-concept) |
|
| **IMPORT-RUNTIME.md** | Foreign-project ingestion pipeline | Decompose → match → extract skills → plan → execute (Hermes proof-of-concept) |
|
||||||
| **PUBLISHING.md** | Community npm registry + scoped package publishing | keigit.com npm, OAuth, per-user PAT, `npm publish` / `npm install` flow |
|
| **PUBLISHING.md** | Community npm registry + scoped package publishing | keigit.com npm, OAuth, per-user PAT, `npm publish` / `npm install` flow |
|
||||||
| **RULES-AS-BLOCKS.md** | How user ~/.claude/rules/*.md become prompt blocks | Rule fragment extraction, RULE re-composition, link-tracking |
|
| **RULES-AS-BLOCKS.md** | How user ~/.claude/rules/*.md become prompt blocks | Rule fragment extraction, RULE re-composition, link-tracking |
|
||||||
| **QUICKSTART.md** | 60-second install guide | 11 install profiles (minimal/core/full + MCP/Cortex/Cursor/Continue/etc) |
|
| **QUICKSTART.md** | 60-second install guide | 12 install profiles (outcome-only/minimal/core/frontend/ops/dev/mcp/cortex/local-mirror/dashboard/full-hub/full) |
|
||||||
| **INSTALL.md** | Full installation docs | Prereqs, profiles, lib-*.sh breakdown, troubleshooting |
|
| **INSTALL.md** | Full installation docs | Prereqs, profiles, lib-*.sh breakdown, troubleshooting |
|
||||||
| **CONVERGENCE-PLAN.md** | Multi-stream parallel work roadmap | UI / Atoms refactor / Graph / Runtime phases (2026-06 closure target) |
|
| **CONVERGENCE-PLAN.md** | Multi-stream parallel work roadmap | UI / Atoms refactor / Graph / Runtime phases (2026-06 closure target) |
|
||||||
| **REFERENCE.md** | Command-line reference for kei-* binaries | kei-runtime, kei-sage, kei-registry, kei-import, kei-capability, kei-forge |
|
| **REFERENCE.md** | Command-line reference for kei-* binaries | kei-runtime, kei-sage, kei-registry, kei-import, kei-capability, kei-forge |
|
||||||
|
|
@ -361,7 +361,7 @@ These are concatenated in role-declared order, with `\n\n---\n\n` separators bet
|
||||||
| Capabilities exist + have both toml + text.md | assembler `validate-capability` + CI | compose fails; missing fragments |
|
| Capabilities exist + have both toml + text.md | assembler `validate-capability` + CI | compose fails; missing fragments |
|
||||||
| JSON Schemas are valid draft-07 | `kei-schema-lint` + CI | atom discovery skips malformed schema |
|
| JSON Schemas are valid draft-07 | `kei-schema-lint` + CI | atom discovery skips malformed schema |
|
||||||
| Gates/verifies registered in kei-agent-runtime | `cargo test --all` | gate lookup fails; aborting capability |
|
| Gates/verifies registered in kei-agent-runtime | `cargo test --all` | gate lookup fails; aborting capability |
|
||||||
| Agent DNA is 80 chars unique per invocation | kei-ledger fork + DNA-INDEX.md | collision risk; query ambiguity |
|
| Agent DNA is variable-length (≥33 chars) unique per invocation | kei-ledger fork + DNA-INDEX.md | collision risk; query ambiguity |
|
||||||
| No file edits outside files-whitelist | scope::files-whitelist gate | merge blocked; scope violation |
|
| No file edits outside files-whitelist | scope::files-whitelist gate | merge blocked; scope violation |
|
||||||
| Files ≤ 200 LOC, functions ≤ 30 LOC | quality::constructor-pattern verify | merge blocked; pattern violation |
|
| Files ≤ 200 LOC, functions ≤ 30 LOC | quality::constructor-pattern verify | merge blocked; pattern violation |
|
||||||
| cargo check + tests green | quality::cargo-check-green + tests-green | merge blocked; integration failure |
|
| cargo check + tests green | quality::cargo-check-green + tests-green | merge blocked; integration failure |
|
||||||
|
|
@ -381,7 +381,7 @@ These are concatenated in role-declared order, with `\n\n---\n\n` separators bet
|
||||||
| **Role** | Bundle of capabilities + tool allowlist + escalation policy | `edit-local`, `read-only`, `git-ops` |
|
| **Role** | Bundle of capabilities + tool allowlist + escalation policy | `edit-local`, `read-only`, `git-ops` |
|
||||||
| **Gate** | PreToolUse Rust impl blocking tool calls (deny) | `policy::no-git-ops` blocks `^git` |
|
| **Gate** | PreToolUse Rust impl blocking tool calls (deny) | `policy::no-git-ops` blocks `^git` |
|
||||||
| **Verify** | On-return Rust impl validating agent output + integration | `quality::cargo-check-green` runs `cargo check --workspace` |
|
| **Verify** | On-return Rust impl validating agent output + integration | `quality::cargo-check-green` runs `cargo check --workspace` |
|
||||||
| **DNA** | 80-char deterministic agent identity; "did this run before?" without embeddings | `code-impl::edit-local::7f1a2c3d::5e9b4f2a-nonce` |
|
| **DNA** | ≥33-char variable-length deterministic agent identity; "did this run before?" without embeddings | `code-impl::edit-local::7f1a2c3d::5e9b4f2a-nonce` |
|
||||||
| **Simulated merge** | Orchestrator creates test branch, applies agent diff, runs checks from there | catches integration regressions pre-merge |
|
| **Simulated merge** | Orchestrator creates test branch, applies agent diff, runs checks from there | catches integration regressions pre-merge |
|
||||||
| **Hands off** | Agent delegates work to another agent via manifest `[[handoff]]` table | `code-implementer` hands off to `ml-implementer` |
|
| **Hands off** | Agent delegates work to another agent via manifest `[[handoff]]` table | `code-implementer` hands off to `ml-implementer` |
|
||||||
|
|
||||||
|
|
@ -402,7 +402,7 @@ These are concatenated in role-declared order, with `\n\n---\n\n` separators bet
|
||||||
| Bridges | stable | 11 cross-tool format generators (.cursorrules, .windsurf/rules, GEMINI.md, etc.) |
|
| Bridges | stable | 11 cross-tool format generators (.cursorrules, .windsurf/rules, GEMINI.md, etc.) |
|
||||||
| Sleep Layer (Phase A/B/C) | stable | Incubation (tasks), REM consolidation (reports), NREM deep-sleep (conflicts) |
|
| Sleep Layer (Phase A/B/C) | stable | Incubation (tasks), REM consolidation (reports), NREM deep-sleep (conflicts) |
|
||||||
| Foreign-project ingestion | stable | kei-import <repo> proof-of-concept via Hermes validation |
|
| Foreign-project ingestion | stable | kei-import <repo> proof-of-concept via Hermes validation |
|
||||||
| Nightly consolidation | active | Running 2026-05-02; Phase A + B + C observed; reports 495 DNA indices |
|
| Nightly consolidation | active | Running 2026-05-02; Phase A + B + C observed; reports 565 DNA indices (per docs/DNA-INDEX.md header 2026-05-03) |
|
||||||
|
|
||||||
**Roadmap:**
|
**Roadmap:**
|
||||||
- Model router (Bayesian posterior, currently manual routing)
|
- Model router (Bayesian posterior, currently manual routing)
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,19 @@ _outcome_install_ledger() {
|
||||||
local db="$AGENTS_DIR/ledger.sqlite"
|
local db="$AGENTS_DIR/ledger.sqlite"
|
||||||
mkdir -p "$AGENTS_DIR"
|
mkdir -p "$AGENTS_DIR"
|
||||||
local kl="$KIT_DIR/_primitives/_rust/kei-ledger/target/release/kei-ledger"
|
local kl="$KIT_DIR/_primitives/_rust/kei-ledger/target/release/kei-ledger"
|
||||||
|
# Cross-version downgrade guard (audit fix 2026-05-03 W3): if an
|
||||||
|
# existing DB is at a NEWER schema (user_version > 9, e.g. user
|
||||||
|
# later upgrades to a full kit that adds a v10 migration), do NOT
|
||||||
|
# re-run any init path — the SQL fallback would otherwise reset
|
||||||
|
# user_version and the binary path may replay incompatible v9 ALTERs.
|
||||||
|
if [ -f "$db" ] && command -v sqlite3 >/dev/null 2>&1; then
|
||||||
|
local current_v
|
||||||
|
current_v=$(sqlite3 "$db" "PRAGMA user_version;" 2>/dev/null || echo 0)
|
||||||
|
if [ "${current_v:-0}" -gt 9 ] 2>/dev/null; then
|
||||||
|
say "ledger already at schema v$current_v (>9); skipping init to preserve newer schema"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
if command -v kei-ledger >/dev/null 2>&1; then
|
if command -v kei-ledger >/dev/null 2>&1; then
|
||||||
kei-ledger --db "$db" init >/dev/null 2>&1 \
|
kei-ledger --db "$db" init >/dev/null 2>&1 \
|
||||||
&& say "ledger initialised via kei-ledger CLI" && return 0
|
&& say "ledger initialised via kei-ledger CLI" && return 0
|
||||||
|
|
@ -67,16 +80,21 @@ _outcome_install_ledger() {
|
||||||
fi
|
fi
|
||||||
warn "no kei-ledger or sqlite3 found; ledger NOT initialised."
|
warn "no kei-ledger or sqlite3 found; ledger NOT initialised."
|
||||||
warn " install one of: brew install sqlite, or rerun after a full kit install."
|
warn " install one of: brew install sqlite, or rerun after a full kit install."
|
||||||
return 0
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Append STATUS-TRUTH MARKER instruction to CLAUDE.md (idempotent: skip
|
# Append STATUS-TRUTH MARKER instruction to CLAUDE.md (idempotent: skip
|
||||||
# if marker phrase is already present).
|
# if our specific marker comment is already present).
|
||||||
_outcome_install_claude_md() {
|
_outcome_install_claude_md() {
|
||||||
local cm="$HOME_DIR/.claude/CLAUDE.md"
|
local cm="$HOME_DIR/.claude/CLAUDE.md"
|
||||||
mkdir -p "$HOME_DIR/.claude"
|
mkdir -p "$HOME_DIR/.claude"
|
||||||
if [ -f "$cm" ] && grep -q "STATUS-TRUTH MARKER" "$cm" 2>/dev/null; then
|
# Audit fix 2026-05-03 (W3): match the literal HTML comment marker we
|
||||||
say "CLAUDE.md already contains STATUS-TRUTH MARKER instruction; skipping"
|
# wrote, NOT the broad phrase "STATUS-TRUTH MARKER" — the broad phrase
|
||||||
|
# is also used in RULE 0.16 documentation that many users already have
|
||||||
|
# in their CLAUDE.md, which would cause a false-positive skip and the
|
||||||
|
# outcome-only instruction would never land.
|
||||||
|
if [ -f "$cm" ] && grep -qF '<!-- outcome-only profile (KeiSeiKit) -->' "$cm"; then
|
||||||
|
say "CLAUDE.md already contains outcome-only marker; skipping"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
backup_file "$cm" 2>/dev/null || true
|
backup_file "$cm" 2>/dev/null || true
|
||||||
|
|
@ -133,17 +151,22 @@ install_profile_outcome_only() {
|
||||||
cp -f "$snippet" "$HOME_DIR/.claude/settings.json" \
|
cp -f "$snippet" "$HOME_DIR/.claude/settings.json" \
|
||||||
&& say "created settings.json from outcome-only snippet"
|
&& say "created settings.json from outcome-only snippet"
|
||||||
else
|
else
|
||||||
# Audit fix 2026-05-03: backup_file MOVES the target. We need the file
|
# Audit fix 2026-05-03 (W3): backup_file MOVES the target which would
|
||||||
# still in place for jq to read during merge — copy aside instead so
|
# leave _jq_merge_hooks with no file to read. Use cp -p to copy aside
|
||||||
# _jq_merge_hooks reads the original. The trap-pair entry registered
|
# AND register the pair in BACKUP_PAIRS so the rollback trap restores
|
||||||
# by backup_file restores on rollback if the merge fails.
|
# it on later failure (was orphan-bak-not-in-rollback-contract).
|
||||||
cp -p "$HOME_DIR/.claude/settings.json" \
|
local _ts
|
||||||
"$HOME_DIR/.claude/settings.json.bak-$(date +%s)"
|
_ts=$(date +%s)
|
||||||
|
local _bak="$HOME_DIR/.claude/settings.json.bak-$_ts"
|
||||||
|
cp -p "$HOME_DIR/.claude/settings.json" "$_bak"
|
||||||
|
BACKUP_PAIRS+=("$HOME_DIR/.claude/settings.json|$_bak")
|
||||||
if ! _jq_merge_hooks "$snippet" "$HOME_DIR/.claude/settings.json"; then
|
if ! _jq_merge_hooks "$snippet" "$HOME_DIR/.claude/settings.json"; then
|
||||||
err "settings.json merge failed; the .bak file remains as recovery"
|
err "settings.json merge failed; rollback trap will restore from $_bak"
|
||||||
rm -f "$snippet"
|
rm -f "$snippet"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
# Success: remove our backup (rollback contract released)
|
||||||
|
rm -f "$_bak"
|
||||||
fi
|
fi
|
||||||
rm -f "$snippet"
|
rm -f "$snippet"
|
||||||
say "outcome-only profile installed."
|
say "outcome-only profile installed."
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,17 @@
|
||||||
-- outcome-only-schema.sql — minimal SQLite schema for the outcome-only
|
-- outcome-only-schema.sql — minimal SQLite schema for the outcome-only
|
||||||
-- profile. Mirrors `_primitives/_rust/kei-ledger/src/migrations_list.rs`
|
-- profile. Mirrors `_primitives/_rust/kei-ledger/src/migrations_list.rs`
|
||||||
-- but flattened: a single transaction that creates the v9-equivalent
|
-- but flattened: a single transaction that creates the v9-equivalent
|
||||||
-- shape of `agents` + `skill_invocations`. No PRAGMA user_version bump
|
-- shape of `agents` + `skill_invocations`, plus the v3 BEFORE-INSERT/
|
||||||
-- is performed (the Rust runner expects to own that); if/when the user
|
-- UPDATE triggers that enforce branch length ≤256.
|
||||||
-- later upgrades to a full kit install, `kei-ledger init` is idempotent
|
--
|
||||||
-- — IF NOT EXISTS guards keep both paths compatible.
|
-- PRAGMA user_version = 9 is set OUTSIDE the transaction (after COMMIT)
|
||||||
|
-- so it lands atomically and is portable across SQLite versions
|
||||||
|
-- (transaction-aware PRAGMA writes are documented-undefined on
|
||||||
|
-- pre-3.37 builds). The shell installer (`_outcome_install_ledger`
|
||||||
|
-- in `lib-profile-outcome-only.sh`) guards re-runs against an
|
||||||
|
-- already-upgraded DB by reading user_version BEFORE invoking this
|
||||||
|
-- file; that prevents silent downgrade if the user later runs full
|
||||||
|
-- kit which bumps schema past v9.
|
||||||
--
|
--
|
||||||
-- Two tables:
|
-- Two tables:
|
||||||
-- agents → outcome rows (kei-model-router posterior)
|
-- agents → outcome rows (kei-model-router posterior)
|
||||||
|
|
@ -66,10 +73,30 @@ CREATE INDEX IF NOT EXISTS idx_skill_invocations_name_ts
|
||||||
CREATE INDEX IF NOT EXISTS idx_skill_invocations_success
|
CREATE INDEX IF NOT EXISTS idx_skill_invocations_success
|
||||||
ON skill_invocations(skill_name, success);
|
ON skill_invocations(skill_name, success);
|
||||||
|
|
||||||
-- Audit fix 2026-05-03: bump user_version to 9 so a later `kei-ledger init`
|
-- v3 triggers — enforce branch length ≤256 chars (mirrors
|
||||||
-- short-circuits via the `current >= 9` gate instead of replaying v1..v9
|
-- `migrations_list.rs:30-44` v3 migration). Without these, the flat
|
||||||
-- migrations whose ALTER TABLE ADD COLUMN steps would error with "duplicate
|
-- schema would silently accept rows that the Rust kei-ledger flow
|
||||||
-- column" against the already-flat schema this file installed.
|
-- rejects, creating cross-version drift.
|
||||||
PRAGMA user_version = 9;
|
CREATE TRIGGER IF NOT EXISTS trg_agents_branch_len_ins
|
||||||
|
BEFORE INSERT ON agents
|
||||||
|
BEGIN
|
||||||
|
SELECT RAISE(ABORT, 'branch length exceeds 256')
|
||||||
|
WHERE length(NEW.branch) > 256;
|
||||||
|
SELECT RAISE(ABORT, 'parent_branch length exceeds 256')
|
||||||
|
WHERE NEW.parent_branch IS NOT NULL AND length(NEW.parent_branch) > 256;
|
||||||
|
END;
|
||||||
|
CREATE TRIGGER IF NOT EXISTS trg_agents_branch_len_upd
|
||||||
|
BEFORE UPDATE OF branch, parent_branch ON agents
|
||||||
|
BEGIN
|
||||||
|
SELECT RAISE(ABORT, 'branch length exceeds 256')
|
||||||
|
WHERE length(NEW.branch) > 256;
|
||||||
|
SELECT RAISE(ABORT, 'parent_branch length exceeds 256')
|
||||||
|
WHERE NEW.parent_branch IS NOT NULL AND length(NEW.parent_branch) > 256;
|
||||||
|
END;
|
||||||
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
|
-- PRAGMA user_version is set OUTSIDE the transaction so the write is
|
||||||
|
-- portable across SQLite versions. The shell installer guards against
|
||||||
|
-- silent downgrade by checking user_version BEFORE invoking this file.
|
||||||
|
PRAGMA user_version = 9;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue