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>