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>
- Real crate count: 39 (was claimed 18 pre-audit; README agent caught it)
- 620 tests green (up from 538 at v0.28)
- Wave 13 entry added with 3 primitives + 2 HIGH fixes
Known follow-ups for v0.29.1:
- HttpDriver re-run (worktree lost mid-session)
- agent_id path-traversal validator re-run (worktree lost mid-session)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Added [primitive.*] entries for kei-agent-runtime, kei-capability,
kei-provision, kei-entity-store, kei-pipe, kei-cache, kei-spawn,
kei-replay. Profile memberships:
- ops: +kei-provision (total 9)
- dev: +7 substrate+automation primitives (total 17)
- full: +8 (total 46)
docs/INSTALL.md + README.md updated with new counts.
Not registered (lib-only, no main.rs): kei-atom-discovery.
Flag for follow-up: kei-forge + kei-runtime are in workspace but not
in MANIFEST (were before my scope). regen-counts.sh will soft-warn.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Both atom substrate (6-week lock) and agent substrate (3-week lock) were
calibrated for calendar windows that were 30-100× slower than actual
execution. Phases shipped in hours, not weeks. Keeping calendar locks
delays breaking consolidations that can safely ship now.
Unlocks: verb templates, schema fragments, PatternGate, CommandVerify,
role expression, DNA identity — all can ship as breaking changes with
standard review gate (audit + integration tests).
No more calendar-week locks. Future locks: agent-hours or
"until declared phases land."
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PreToolUse hooks route through kei-capability check when orchestrator
registers a capability via KEI_CAPABILITY_NAME env var on agent spawn.
hooks/agent-capability-check.sh (22 LOC):
- Pass-through (exit 0) when KEI_CAPABILITY_NAME unset — no-op by default
- Fail-open (exit 0) when kei-capability binary missing — kit convention
- Sources _lib/gate.sh for KEI_DISABLED_HOOKS / KEI_HOOK_PROFILE respect
- exec kei-capability check "$CAP_NAME" when active
hooks/agent-capability-verify.sh (24 LOC):
- Orchestrator-driven, NOT a Claude Code native hook
- Carries env: AGENT_ID, TASK_TOML, WORKTREE_PATH, MAIN_REPO, RUN_MODE
- exec kei-capability verify "$CAP_NAME"
Registered in hooks/hooks.json + settings-snippet.json under both
PreToolUse:Bash and PreToolUse:Edit|Write matchers. Internal NotApplicable
returns exit 0 so non-matching tool calls cost nothing.
install.sh unchanged — hooks/*.sh glob picks up both new files.
tests/hook_wiring_integration.sh (64 LOC) — 3 contract assertions:
(1) pass-through on unset KEI_CAPABILITY_NAME
(2) deny+exit 2 on git-op pattern
(3) allow+exit 0 on cargo-check pattern
Multi-capability routing (for phase 5): KEI_CAPABILITY_NAME currently
holds ONE name. When a role requires N capabilities, orchestrator will
either iterate or kei-capability gains a compose subcommand. Design
note left for phase 5.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sibling SSoT to SUBSTRATE-SCHEMA.md (atom substrate). This one decomposes
agent invocations rather than code primitives.
Core contribution — the capability TRIPLET, not just text:
- text.md — what agent reads (prompt fragment)
- gate.sh — PreToolUse hook (runtime enforcement)
- verify.sh — on-return predicate run from main repo (not worktree)
Motivation from substrate v1 orchestration audit:
- 40% prompt boilerplate across 7 spawns (git-ban + constructor-pattern +
report format etc. copy-pasted each time)
- Self-reported green tests broke at integration (E1 jsonschema
regression — agent claimed PASS from worktree but main workspace
failed; caught only by integration test)
- Scope violations (E1 touched invoke.rs when E3 was supposed to own it;
surfaced only at merge)
Triplet closes all three gaps: capabilities aren't promises agents make
in prose, they're enforced by gate hooks pre-exec and verified by
predicates on return from main branch clean state.
Schema specifies:
- Capability atom layout: _capabilities/<category>/<slug>/
- capability.toml frontmatter shape
- text.md / gate.sh / verify.sh contracts
- Role = bundle of capabilities (5 roles: read-only, explorer, edit-local,
edit-shared, git-ops)
- task.toml shape (orchestrator-written per spawn; parameterizes roles)
- kei-agent-runtime crate contract: compose + spawn + verify + run
- Initial 10-capability inventory for phase 1
- 6-question decision log with defaults
- 5-phase parallel build plan (phases 1-4 parallel, ~5-7 days wall time)
Open questions flagged at bottom for review before AGENT-SCHEMA-LOCKED.md.
Once locked: sibling SSoTs (atoms + agents) evolve symmetrically — agents
compose atoms, atoms compose agents (ultimate goal).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three post-E1/E2/E3-merge items:
1. Schema amendment A-1 (architect P0-a, non-breaking clarification):
input.schema and output.schema are REQUIRED for all atom kinds. The
shared kei-atom-discovery parses them as Option<PathBuf> only to allow
tolerant skip-on-missing (stderr warn), not to permit absent schemas.
Resolves Stream C / Stream D enforcement asymmetry documented in
critic finding #6.
2. Cross-stream integration test (architect P0-b): tests/substrate_integration.sh
builds release binaries, scaffolds a test atom corpus, runs
schema-lint + list-atoms + atoms-discover + invoke; asserts all four
streams agree on the same atom corpus and exit codes honour the
locked §Runtime contract. Previously missing — only manual smoke
checks existed.
3. Fix regression introduced by E1's jsonschema 0.18 upgrade:
"relative URL without a base" on compile when schema declared a
relative $id like "kei-task/atoms/schemas/create-input.json".
validate.rs now synthesises an absolute file:// $id from the
canonicalised schema path before compile. Internal $refs still
resolve relative to the schema file; LocalFileResolver still confines
to the schema's parent dir. Integration test catches this.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Schema at SUBSTRATE-SCHEMA.md (revised 2026-04-22) is immutable until
~2026-06-03 or explicit user revocation. 4 parallel streams may now
proceed independently against this contract.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Schema revisions per user review 2026-04-22 (all 6 open questions resolved
— see §Decision log in SUBSTRATE-SCHEMA.md):
- #3 side_effects: string tags → structured { op, domain } objects (user:
"лучше сразу с запасом")
- #4 capabilities.toml: DROPPED entirely (user: "почему не мд?"). SSoT is
atoms/*.md. Crate-level metadata moves to Cargo.toml
[package.metadata.keisei] — Cargo-native, no drift, no build.rs, no
generated files to commit. kei-sage + kei-runtime walk atoms/*.md
directly.
- #5 atom template: shipped in this PR (user: "ui же параллельно! создавай
все!") so Streams B/C/D can scaffold atoms from day 0 without waiting
for Stream A (kei-forge UI).
- #1/#2/#6 confirmed as drafted (draft-07, `::` separator, per-atom errors).
New files:
- _templates/atom/ — 5-file template set with placeholder substitution
(__CRATE__, __VERB__, __KIND__, __DESCRIPTION__ etc). Covers
atoms/<verb>.md, schemas/<verb>-{input,output}.json, src/atoms/<verb>.rs,
tests/<verb>_smoke.rs. Each file is a minimal working skeleton.
- scripts/new-atom.sh — POSIX bash generator (bash for $'\n' / readonly /
trap). Validates verb is lowercase kebab-case, kind is one of
command|query|stream|transform. Refuses to overwrite existing files.
Rolls back on any failure (trap ERR deletes all generated files so no
half-scaffolded state). Tested: produces 5 files, placeholder
substitution correct on smoke-test crate.
Stream B (atoms refactor) updated to drop the "generates capabilities.toml
via build.rs" wording — now just "writes atoms/*.md + updates Cargo.toml
[package.metadata.keisei]". Stream D reads atoms/*.md + Cargo.toml, not
capabilities.toml.
Schema status: revisions applied, decision log complete. Ready for
SCHEMA-LOCKED.md marker commit once user signs off on revised doc.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Substrate thesis requires a single source of truth before parallel work
streams (UI/Atoms/Graph/Runtime) can proceed independently without drift.
This document is that SSoT.
Key decisions baked in (open to revision before lock):
- Atom = one verb on a primitive, not one crate. Target ~150 atoms
across current 25 crates. Crate = physical container, atom = unit of
composition.
- File layout: src/atoms/<verb>.rs (code) + atoms/<verb>.md (docs with
machine-parseable YAML frontmatter) + atoms/schemas/*.json (JSON
Schema draft-07 for input/output) + capabilities.toml (auto-generated
aggregator, committed to repo).
- Atom kinds: command / query / stream / transform. Combined with
side_effects[] and idempotent flag, runtime decides retry safety,
parallelism, caching.
- Naming: <crate>::<verb> globally unique. Rust :: separator keeps it
native-feeling.
- Versioning: atoms inherit crate SemVer. Breaking change to an atom =
new atom (create-v2), old marked deprecated.
- Runtime contract: `kei-runtime invoke <atom-id> --input <json>` with
schema validation at entry + exit, ledger row per invocation.
- Graph contract: kei-sage auto-walks atoms/*.md, resolves [[atom-id]]
wikilinks, exposes rank / related / search / graph over atom corpus.
- UI contract: kei-forge web wizard generates .md + .json + .rs + test
from form input; postcondition cargo check + kei-schema-lint pass.
Document declares 4 stream interfaces explicitly — each stream knows
what it reads from this schema, what it writes, what it does NOT depend
on from other streams. Enables true parallel work.
6 open questions flagged for user review at bottom:
1) JSON Schema draft-07 vs 2020-12
2) Atom ID separator :: vs /
3) side_effects strings vs structured
4) capabilities.toml committed vs gitignored
5) kei-atom-template in this PR or defer to Stream A
6) Error model per-atom vs shared registry
STATUS: DRAFT — awaits user approval + SCHEMA-LOCKED.md marker before
parallel streams start. Once locked, breaking changes require explicit
revocation + all-streams sync.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>