KeiSeiKit-1.0/_primitives/_rust/kei-atom-discovery/tests/taxonomy_smoke.rs
Parfii-bot a4e667de10 KeiSeiKit-public — clean state
Single-commit clean baseline after security scrub of niche-tells,
project codenames, internal jargon, and contributor-email leaks.

Contents:
- 100 Rust crates (_primitives/_rust/)
- 37 agent manifests (_manifests/) + generated specs (_generated/)
- 67 user-invocable skills (skills/)
- 33 hooks (hooks/)
- Composition blocks (_blocks/)
- Documentation (docs/, README.md)
- TS adapter packages (_ts_packages/)
- Assembler (_assembler/)
- Roles (_roles/)
- Templates (_templates/)
- Forgejo CI (.forgejo/)

Author: Denis Parfionovich <info@greendragon.info>

License: see LICENSE.
2026-05-01 12:09:03 +08:00

154 lines
4.7 KiB
Rust

//! Taxonomy + Lineage facet parsing smoke tests.
//!
//! Covers (a) full 7-facet taxonomy + lineage with multiple parents,
//! (b) partial taxonomy (only kingdom + mechanism) — remaining fields None,
//! (c) backward-compat: atom without any [taxonomy]/[lineage] still parses,
//! (d) lineage.parents array parses correctly (multi-parent diamond lineage).
use kei_atom_discovery::{discover_atoms, Lineage, TaxonomyFacets};
use std::fs;
use std::path::Path;
use tempfile::tempdir;
const ATOM_FULL: &str = r#"---
atom: kei-task::create
kind: command
version: "0.1.0"
input:
schema: schemas/create-input.json
output:
schema: schemas/create-output.json
side_effects:
- { op: write, domain: kei-task-db }
idempotent: false
stability: stable
keywords: [task]
related: []
taxonomy:
kingdom: atom
mechanism: transform
domain: task
layer: atom-substrate
stage: runtime
stability: stable
language: rust
lineage:
parents:
- "[[kei-task::add-dependency]]"
- "[[rules/RULE 0.12]]"
creator: ag-orchestrator-human
created: "2026-04-23"
fork_from: dna-abc123
---
# body
"#;
const ATOM_PARTIAL: &str = r#"---
atom: kei-task::update
kind: command
version: "0.1.0"
input:
schema: schemas/create-input.json
output:
schema: schemas/create-output.json
side_effects: []
taxonomy:
kingdom: atom
mechanism: transform
lineage:
parents: []
---
# body
"#;
const ATOM_NO_FACETS: &str = r#"---
atom: kei-task::delete
kind: command
version: "0.1.0"
input:
schema: schemas/create-input.json
output:
schema: schemas/create-output.json
side_effects: []
---
# body
"#;
fn write_atom(root: &Path, crate_name: &str, verb: &str, body: &str) {
let atoms_dir = root.join(crate_name).join("atoms");
fs::create_dir_all(atoms_dir.join("schemas")).unwrap();
fs::write(atoms_dir.join(format!("{verb}.md")), body).unwrap();
fs::write(atoms_dir.join("schemas").join("create-input.json"), "{}").unwrap();
fs::write(atoms_dir.join("schemas").join("create-output.json"), "{}").unwrap();
}
fn find<'a>(
atoms: &'a [kei_atom_discovery::AtomMeta],
full_id: &str,
) -> &'a kei_atom_discovery::AtomMeta {
atoms
.iter()
.find(|a| a.full_id == full_id)
.expect("atom present")
}
#[test]
fn full_taxonomy_and_lineage_parse() {
let tmp = tempdir().unwrap();
write_atom(tmp.path(), "kei-task", "create", ATOM_FULL);
let atoms = discover_atoms(tmp.path());
let a = find(&atoms, "kei-task::create");
let tax: &TaxonomyFacets = a.taxonomy.as_ref().expect("taxonomy present");
assert_eq!(tax.kingdom.as_deref(), Some("atom"));
assert_eq!(tax.mechanism.as_deref(), Some("transform"));
assert_eq!(tax.domain.as_deref(), Some("task"));
assert_eq!(tax.layer.as_deref(), Some("atom-substrate"));
assert_eq!(tax.stage.as_deref(), Some("runtime"));
assert_eq!(tax.stability.as_deref(), Some("stable"));
assert_eq!(tax.language.as_deref(), Some("rust"));
let lin: &Lineage = a.lineage.as_ref().expect("lineage present");
assert_eq!(lin.creator.as_deref(), Some("ag-orchestrator-human"));
assert_eq!(lin.created.as_deref(), Some("2026-04-23"));
assert_eq!(lin.fork_from.as_deref(), Some("dna-abc123"));
}
#[test]
fn partial_taxonomy_leaves_rest_none() {
let tmp = tempdir().unwrap();
write_atom(tmp.path(), "kei-task", "update", ATOM_PARTIAL);
let atoms = discover_atoms(tmp.path());
let a = find(&atoms, "kei-task::update");
let tax = a.taxonomy.as_ref().expect("taxonomy present");
assert_eq!(tax.kingdom.as_deref(), Some("atom"));
assert_eq!(tax.mechanism.as_deref(), Some("transform"));
assert!(tax.domain.is_none());
assert!(tax.layer.is_none());
assert!(tax.stage.is_none());
assert!(tax.stability.is_none());
assert!(tax.language.is_none());
let lin = a.lineage.as_ref().expect("lineage present");
assert!(lin.parents.is_empty());
assert!(lin.creator.is_none());
}
#[test]
fn no_facets_section_still_parses_backward_compat() {
let tmp = tempdir().unwrap();
write_atom(tmp.path(), "kei-task", "delete", ATOM_NO_FACETS);
let atoms = discover_atoms(tmp.path());
let a = find(&atoms, "kei-task::delete");
assert!(a.taxonomy.is_none(), "no [taxonomy] → None");
assert!(a.lineage.is_none(), "no [lineage] → None");
}
#[test]
fn lineage_parents_array_preserved() {
let tmp = tempdir().unwrap();
write_atom(tmp.path(), "kei-task", "create", ATOM_FULL);
let atoms = discover_atoms(tmp.path());
let a = find(&atoms, "kei-task::create");
let lin = a.lineage.as_ref().expect("lineage present");
assert_eq!(lin.parents.len(), 2);
assert_eq!(lin.parents[0], "[[kei-task::add-dependency]]");
assert_eq!(lin.parents[1], "[[rules/RULE 0.12]]");
}