47 crates, 771 tests green (up from 753 at v0.33.0). Zero new
features — pure hygiene.
## kei-shared extract (SSoT for DNA format)
New crate `kei-shared` consolidates DNA-parse logic that was duplicated
across kei-agent-runtime + kei-dna-index. Both consumers migrated to
import ParsedDna / parse_dna / is_hex8 from kei_shared.
- 12 tests (10 integration + 2 unit)
- kei-dna-index LOC reduction: -60 in parsed.rs (body replaced by wrapper)
- kei-agent-runtime preserves lenient DnaError (legacy 4-hex parse path)
- Format-string SSoT: kei_shared::compose_dna is sole source
## MEDIUM audit residuals closed (kei-entity-store)
A. DDL panic coverage — verified exhaustive match across all 12
FieldKind variants; new test ddl_never_panics_on_any_fieldkind
compile-time-breaks if a variant added without test update.
B. Update FTS reindex invariant — doc + new update_invariant.rs module
with debug_assert validating non-input FTS columns don't drift
pre/post UPDATE. Zero release-mode cost (cfg-gated).
C. WAL fallback — wal_pragma_fallback_keeps_store_usable test (cfg(unix))
verifies read-only-parent dir doesn't brick Store::open.
D. Search Unicode edge cases — 4 new tests (punctuation, emoji,
zero-width, mixed RTL). has_searchable_token already correct, no
source change needed; tests pin current behavior.
Added: residual_audit_smoke.rs (8 tests), update_invariant.rs module.
kei-entity-store: 57 → 65 tests.
## Docs drift fixed (count claims → reality)
- README.md: "36 crates → 47 crates", "500+ tests → 800+ tests"
- PLUGIN.md, docs/INSTALL.md, docs/REFERENCE.md, docs/SUBSTRATE-SCHEMA.md
all synced to real counts.
- CHANGELOG.md: 6 new version blocks (v0.28 → v0.33) consolidated
in existing style.
- Historical snapshots (HANDOFF-WAKE v0.29, CONVERGENCE-PLAN, etc)
deliberately preserved — they're version-scoped, not drift.
## Known deviation from task spec
kei-shared's [workspace] table was dropped (Cargo rejected "multiple
workspace roots" when parent workspace pulls via path dep). Crate
registered in workspace.members instead. Verified cargo check + test
clean in both modes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Makes KeiSeiKit installable both as classic kit AND as an
Anthropic Claude Code plugin.
.claude-plugin/plugin.json — plugin manifest (name, version,
description, author OBJECT per schema, repository, license)
.claude-plugin/marketplace.json — own marketplace declaration
(owner OBJECT per schema, plugins[].source OBJECT)
.claude-plugin/mcp-template.json — template for .mcp.json (actual
.mcp.json write is blocked by hook; user copies template manually)
PLUGIN.md — dual-install docs (plugin vs classic)
hooks/hooks.json — uses ${CLAUDE_PLUGIN_ROOT} (per Anthropic
schema, NOT ${PLUGIN_ROOT}); wraps hooks under top-level
"hooks": {...} key
Schema corrections caught during agent validation:
- marketplace.json owner MUST be object (not string)
- hooks.json requires "hooks": {...} top-level wrapper
- env var is ${CLAUDE_PLUGIN_ROOT} not ${PLUGIN_ROOT}
Companion edits in install-split bundle: install/lib-args.sh
gains an 8-line plugin-first banner in print_help() directing
users toward the plugin install path as recommended default.
Dual-install strategy: users can pick
- `claude plugin marketplace add <url>` then install — latest
and iteration-friendly (this PR enables it)
- classic ./install.sh — legacy kit path, full 37-primitive
control
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>