KeiSeiKit-1.0/_primitives/_rust/kei-runtime/tests/discover_smoke.rs
Parfii-bot d68fddb59a feat(stream-d): kei-runtime — discover + validate + lint (invoke stub)
New crate _primitives/_rust/kei-runtime/ implementing §Runtime invocation
contract from locked substrate schema.

CLI (clap-derive):
- list-atoms [--root] [--crate] [--kind]   → walk + print
- invoke <atom-id> --input <json|@file>    → discover + validate input (stub exec)
- schema-lint [--root] [--crate]           → 6-check validator
- pipe <dag.toml>                          → "not yet implemented" stub

Modules (≤ 200 LOC each, largest lint.rs @ 171):
- src/discover.rs — walk_atoms walks <root>/*/atoms/*.md, parses frontmatter
- src/validate.rs — JSONSchema draft-07 via jsonschema 0.17.1
- src/invoke.rs — MVP stub: discover → parse → validate_input → boundary ack
- src/lint.rs — 6 checks: required fields, kind enum, side_effects shape,
  schema path existence + draft-07 declaration, wikilink resolution
- src/main.rs — clap CLI, exit 0|1|2 per §Runtime contract

Intentional stub boundary: invoke returns structured JSON ack (exit 0),
wire-up to concrete atom impls deferred to integration pass (needs
Stream B atoms landed first).

Registered kei-runtime in workspace members.

Tests: 2/2 integration smoke (lint_smoke, discover_smoke) green.

Stream D of substrate v1 parallel build.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 00:09:58 +08:00

50 lines
1.5 KiB
Rust

//! Integration test — walk_atoms returns 2 well-formed records from temp root.
use kei_runtime::discover::walk_atoms;
use std::fs;
use std::path::Path;
fn write_atom(root: &Path, crate_name: &str, verb: &str) {
let atoms = root.join(crate_name).join("atoms");
let schemas = atoms.join("schemas");
fs::create_dir_all(&schemas).unwrap();
let input = format!("{verb}-input.json");
let output = format!("{verb}-output.json");
fs::write(schemas.join(&input), "{}").unwrap();
fs::write(schemas.join(&output), "{}").unwrap();
let md = format!(
r#"---
atom: {crate_name}::{verb}
kind: query
version: "0.1.0"
input:
schema: schemas/{input}
output:
schema: schemas/{output}
side_effects: []
idempotent: true
stability: stable
---
# {crate_name}::{verb}
"#,
);
fs::write(atoms.join(format!("{verb}.md")), md).unwrap();
}
#[test]
fn walk_atoms_finds_two_records() {
let tmp = tempfile::tempdir().unwrap();
write_atom(tmp.path(), "kei-alpha", "search");
write_atom(tmp.path(), "kei-beta", "fetch");
let mut atoms = walk_atoms(tmp.path());
atoms.sort_by(|a, b| a.full_id.cmp(&b.full_id));
assert_eq!(atoms.len(), 2);
assert_eq!(atoms[0].full_id, "kei-alpha::search");
assert_eq!(atoms[0].crate_name, "kei-alpha");
assert_eq!(atoms[0].verb, "search");
assert_eq!(atoms[0].kind, "query");
assert_eq!(atoms[1].full_id, "kei-beta::fetch");
assert!(atoms[1].input_schema_path.ends_with("schemas/fetch-input.json"));
assert!(atoms[1].output_schema_path.ends_with("schemas/fetch-output.json"));
}