pub const MANIFEST_FILE: &str = "EKF.yaml";
pub const SUPPORTED_EKF_VERSION: &str = "0.1";
mod map;
mod model;
mod paths;
mod resolve;
mod validate;
pub use map::{parse_manifest, parse_manifest_file};
pub use model::*;
pub use resolve::resolve_package;
pub use validate::gate_intent;
#[cfg(test)]
mod tests {
use std::path::{Path, PathBuf};
use super::*;
#[test]
fn parses_v01_manifest_subset() {
let (manifest, diagnostics) = parse_manifest(
r#"
ekf_version: "0.1"
name: eidos-engine
partitions:
- id: docs.core
title: Core Docs
source: aun
roots: ["docs/"]
role: knowledge
tags: [docs, core]
- id: code.rust
source: glyph
roots: ["crates/"]
languages: ["rust"]
sources:
docs: ["docs/"]
skills:
- skills/
code:
- path: "crates/"
source: glyph
languages: ["rust", "python"]
evals: ["evals/"]
trust:
default_authority: human
gold_ground_threshold: 3
gates:
route:
min_p_at_1: 0.96
relations:
produces:
forward: creates
reverse: created by
context_score: 34
"#,
);
assert!(diagnostics.is_empty(), "{diagnostics:#?}");
assert_eq!(manifest.ekf_version.as_deref(), Some("0.1"));
assert_eq!(manifest.name.as_deref(), Some("eidos-engine"));
assert_eq!(manifest.partitions.len(), 2);
assert_eq!(manifest.partitions[0].id, "docs.core");
assert_eq!(manifest.partitions[0].source, "aun");
assert_eq!(manifest.partitions[0].roots, vec!["docs/"]);
assert_eq!(manifest.partitions[0].role.as_deref(), Some("knowledge"));
assert_eq!(manifest.partitions[0].tags, vec!["docs", "core"]);
assert_eq!(manifest.partitions[1].source, "glyph");
assert_eq!(manifest.partitions[1].languages, vec!["rust"]);
assert_eq!(manifest.sources.docs, vec!["docs/"]);
assert_eq!(manifest.sources.skills, vec!["skills/"]);
assert_eq!(manifest.sources.code.len(), 1);
assert_eq!(manifest.sources.code[0].path, "crates/");
assert_eq!(manifest.sources.code[0].source.as_deref(), Some("glyph"));
assert_eq!(manifest.sources.code[0].languages, vec!["rust", "python"]);
assert_eq!(
manifest.gates["route"]["min_p_at_1"], "0.96",
"gate value should be retained as a scalar string"
);
assert_eq!(manifest.trust["gold_ground_threshold"], "3");
assert_eq!(manifest.relations["produces"]["forward"], "creates");
assert_eq!(manifest.relations["produces"]["reverse"], "created by");
assert_eq!(manifest.relations["produces"]["context_score"], "34");
}
#[test]
fn four_space_indentation_parses_identically_to_two_space() {
let two_space = r#"
ekf_version: "0.1"
name: eidos-engine
partitions:
- id: docs.core
title: Core Docs
source: aun
roots: ["docs/"]
tags: [docs, core]
sources:
docs: ["docs/"]
code:
- path: "crates/"
source: glyph
languages: ["rust"]
trust:
gold_ground_threshold: 3
gates:
route:
min_p_at_1: 0.96
relations:
produces:
forward: creates
"#;
let four_space = r#"
ekf_version: "0.1"
name: eidos-engine
partitions:
- id: docs.core
title: Core Docs
source: aun
roots: ["docs/"]
tags: [docs, core]
sources:
docs: ["docs/"]
code:
- path: "crates/"
source: glyph
languages: ["rust"]
trust:
gold_ground_threshold: 3
gates:
route:
min_p_at_1: 0.96
relations:
produces:
forward: creates
"#;
let (two, two_diagnostics) = parse_manifest(two_space);
let (four, four_diagnostics) = parse_manifest(four_space);
assert!(two_diagnostics.is_empty(), "{two_diagnostics:#?}");
assert!(four_diagnostics.is_empty(), "{four_diagnostics:#?}");
assert_eq!(two, four);
assert_eq!(two.partitions.len(), 1, "partitions must not be dropped");
}
#[test]
fn flow_and_block_lists_are_interchangeable() {
let flow = r#"
ekf_version: "0.1"
partitions:
- id: code.rust
source: glyph
roots: ["crates/", "tools/"]
languages: [rust, python]
tags: [code]
"#;
let block = r#"
ekf_version: "0.1"
partitions:
- id: code.rust
source: glyph
roots:
- "crates/"
- "tools/"
languages:
- rust
- python
tags:
- code
"#;
let (from_flow, flow_diagnostics) = parse_manifest(flow);
let (from_block, block_diagnostics) = parse_manifest(block);
assert!(flow_diagnostics.is_empty(), "{flow_diagnostics:#?}");
assert!(block_diagnostics.is_empty(), "{block_diagnostics:#?}");
assert_eq!(from_flow, from_block);
assert_eq!(from_flow.partitions[0].roots, vec!["crates/", "tools/"]);
assert_eq!(from_flow.partitions[0].languages, vec!["rust", "python"]);
}
#[test]
fn single_and_double_quoted_scalars_unquote() {
let (manifest, diagnostics) = parse_manifest(
r#"
ekf_version: '0.1'
name: "eidos-engine"
partitions:
- id: 'docs.core'
title: "Core Docs"
source: aun
roots: ['docs/', "extra docs/"]
"#,
);
assert!(diagnostics.is_empty(), "{diagnostics:#?}");
assert_eq!(manifest.ekf_version.as_deref(), Some("0.1"));
assert_eq!(manifest.name.as_deref(), Some("eidos-engine"));
assert_eq!(manifest.partitions[0].id, "docs.core");
assert_eq!(manifest.partitions[0].title.as_deref(), Some("Core Docs"));
assert_eq!(manifest.partitions[0].roots, vec!["docs/", "extra docs/"]);
}
#[test]
fn invalid_yaml_yields_diagnostic_and_default_manifest() {
let (manifest, diagnostics) = parse_manifest("gates: [unclosed\n\t: flow");
assert_eq!(manifest, Manifest::default());
assert_eq!(diagnostics.len(), 1, "{diagnostics:#?}");
assert_eq!(diagnostics[0].kind, "yaml_error");
assert_eq!(diagnostics[0].severity, DiagnosticSeverity::Warning);
}
#[test]
fn gate_and_trust_scalars_keep_raw_text() {
let (manifest, diagnostics) = parse_manifest(
r#"
ekf_version: "0.1"
trust:
gold_ground_threshold: 5
gates:
route:
min_p_at_1: 0.96
min_partition_match_rate: 1.0
dogfood:
min_dogfood_score: 0.90
enabled: true
"#,
);
assert!(diagnostics.is_empty(), "{diagnostics:#?}");
assert_eq!(manifest.trust["gold_ground_threshold"], "5");
assert_eq!(manifest.gates["route"]["min_p_at_1"], "0.96");
assert_eq!(manifest.gates["route"]["min_partition_match_rate"], "1.0");
assert_eq!(manifest.gates["dogfood"]["min_dogfood_score"], "0.90");
assert_eq!(manifest.gates["dogfood"]["enabled"], "true");
}
#[test]
fn resolves_partitions_as_package_compartments() {
let tmp = tempfile::tempdir().unwrap();
for dir in ["knowledge", "src", "package-evals"] {
std::fs::create_dir_all(tmp.path().join(dir)).unwrap();
}
std::fs::write(
tmp.path().join(MANIFEST_FILE),
r#"
ekf_version: "0.1"
name: partitioned-package
partitions:
- id: knowledge.core
title: Core Knowledge
source: aun
roots: ["knowledge"]
role: knowledge
- id: code.app
source: glyph
roots: ["src"]
languages: ["rust"]
- id: eval.route
source: eval
roots: ["package-evals"]
role: route
"#,
)
.unwrap();
let config = resolve_package(PackageRequest {
start_dir: Some(tmp.path().to_path_buf()),
..Default::default()
});
assert!(config.report.manifest_found);
assert_eq!(
config.report.resolved.docs.as_deref(),
Some(tmp.path().join("knowledge").as_path())
);
assert_eq!(
config.report.resolved.code.as_deref(),
Some(tmp.path().join("src").as_path())
);
assert_eq!(config.report.partitions.len(), 3);
assert_eq!(config.report.partitions[0].id, "knowledge.core");
assert_eq!(config.report.partitions[0].status, "compiled");
assert_eq!(
config.report.partitions[0].roots,
vec![tmp.path().join("knowledge")]
);
assert_eq!(config.report.partitions[1].languages, vec!["rust"]);
assert_eq!(config.report.partitions[2].status, "eval");
assert!(
config
.report
.resolved
.source_roots
.iter()
.any(|root| { root.kind == "docs" && root.path == tmp.path().join("knowledge") })
);
assert!(
config
.report
.resolved
.source_roots
.iter()
.any(|root| { root.kind == "code" && root.path == tmp.path().join("src") })
);
assert!(
config.report.resolved.source_roots.iter().any(|root| {
root.kind == "evals" && root.path == tmp.path().join("package-evals")
})
);
}
#[test]
fn diagnoses_invalid_partitions() {
let tmp = tempfile::tempdir().unwrap();
std::fs::write(
tmp.path().join(MANIFEST_FILE),
r#"
ekf_version: "0.1"
partitions:
- id: broken
source: spaceship
roots: ["missing"]
- id: broken
source: aun
- source: glyph
roots: ["missing-code"]
"#,
)
.unwrap();
let config = resolve_package(PackageRequest {
start_dir: Some(tmp.path().to_path_buf()),
..Default::default()
});
assert!(config.report.diagnostics.iter().any(|diagnostic| {
diagnostic.kind == "unsupported_partition_source"
&& diagnostic.message.contains("spaceship")
}));
assert!(
config
.report
.diagnostics
.iter()
.any(|diagnostic| diagnostic.kind == "duplicate_partition")
);
assert!(
config
.report
.diagnostics
.iter()
.any(|diagnostic| diagnostic.kind == "partition_missing_id")
);
assert!(
config
.report
.diagnostics
.iter()
.any(|diagnostic| diagnostic.kind == "partition_missing_roots")
);
assert!(
config
.report
.diagnostics
.iter()
.any(|diagnostic| diagnostic.kind == "missing_source_root")
);
}
#[test]
fn resolves_trust_policy_and_reports_invalid_values() {
let tmp = tempfile::tempdir().unwrap();
std::fs::write(
tmp.path().join(MANIFEST_FILE),
r#"
ekf_version: "0.1"
trust:
gold_ground_threshold: 1
stale_after_days: nope
agent_accepted_ttl_days: 30
mystery: true
"#,
)
.unwrap();
let config = resolve_package(PackageRequest {
start_dir: Some(tmp.path().to_path_buf()),
..Default::default()
});
assert_eq!(config.report.trust_policy.gold_ground_threshold, 1);
assert_eq!(config.report.trust_policy.agent_accepted_ttl_days, Some(30));
assert_eq!(config.report.trust_policy.stale_after_days, None);
assert!(
config
.report
.diagnostics
.iter()
.any(|d| d.kind == "invalid_trust_policy"
&& d.message.contains("stale_after_days"))
);
assert!(
config
.report
.diagnostics
.iter()
.any(|d| d.kind == "unknown_trust_field" && d.message.contains("mystery"))
);
}
#[test]
fn accepts_partition_eval_gate_metrics() {
let tmp = tempfile::tempdir().unwrap();
std::fs::write(
tmp.path().join(MANIFEST_FILE),
r#"
ekf_version: "0.1"
gates:
coverage:
min_partition_judged_cases: 1
min_vocabulary_gap_judged_cases: 1
min_no_vocabulary_gap_judged_cases: 1
min_vocab_editable_target_judged_cases: 1
min_vocab_non_editable_target_judged_cases: 1
min_omitted_context_judged_cases: 1
min_omitted_compound_anchor_judged_cases: 1
graph:
max_unpartitioned_compiled_nodes: 0
context:
min_partition_match_rate: 1.0
min_vocabulary_gap_match_rate: 1.0
min_no_vocabulary_gap_match_rate: 1.0
min_vocab_editable_target_match_rate: 1.0
min_vocab_non_editable_target_match_rate: 1.0
min_omitted_context_match_rate: 1.0
min_omitted_compound_anchor_match_rate: 1.0
dogfood:
min_partition_match_rate: 1.0
"#,
)
.unwrap();
let config = resolve_package(PackageRequest {
start_dir: Some(tmp.path().to_path_buf()),
..Default::default()
});
assert!(
!config
.report
.diagnostics
.iter()
.any(|diagnostic| diagnostic.kind == "unknown_gate_metric"),
"partition gate metrics should be accepted: {:?}",
config.report.diagnostics
);
}
#[test]
fn resolves_relation_profiles_and_reports_invalid_values() {
let tmp = tempfile::tempdir().unwrap();
std::fs::write(
tmp.path().join(MANIFEST_FILE),
r#"
ekf_version: "0.1"
relations:
produces:
forward: creates
reverse: created by
context_score: 34
domain_kinds: [doc, section]
range_kinds: [function, type]
blocks:
forward: blocks
reverse: blocked by
context_score: nope
searchable: maybe
traversable: false
domain_kinds: [doc, bogus]
unknown: value
"#,
)
.unwrap();
let config = resolve_package(PackageRequest {
start_dir: Some(tmp.path().to_path_buf()),
..Default::default()
});
let produces = &config.report.relation_profiles["produces"];
assert_eq!(produces.forward_phrase, "creates");
assert_eq!(produces.reverse_phrase, "created by");
assert_eq!(produces.context_score, 34);
assert_eq!(produces.domain_kinds, vec!["doc", "section"]);
assert_eq!(produces.range_kinds, vec!["function", "type"]);
let supports = &config.report.relation_profiles["supports"];
assert_eq!(supports.forward_phrase, "supports");
assert_eq!(supports.reverse_phrase, "supported by");
assert_eq!(supports.context_score, 34);
assert!(supports.searchable);
assert!(supports.traversable);
let asserts = &config.report.relation_profiles["asserts"];
assert_eq!(asserts.forward_phrase, "asserts");
assert_eq!(asserts.reverse_phrase, "asserted by");
let qualifies = &config.report.relation_profiles["qualifies"];
assert_eq!(qualifies.forward_phrase, "qualifies");
assert_eq!(qualifies.reverse_phrase, "qualified by");
let blocks = &config.report.relation_profiles["blocks"];
assert_eq!(blocks.forward_phrase, "blocks");
assert_eq!(blocks.reverse_phrase, "blocked by");
assert_eq!(blocks.context_score, 4);
assert!(!blocks.traversable);
assert!(blocks.searchable);
assert_eq!(blocks.domain_kinds, vec!["doc"]);
assert!(
config.report.diagnostics.iter().any(
|d| d.kind == "invalid_relation_profile" && d.message.contains("context_score")
)
);
assert!(
config
.report
.diagnostics
.iter()
.any(|d| d.kind == "invalid_relation_profile" && d.message.contains("searchable"))
);
assert!(
config
.report
.diagnostics
.iter()
.any(|d| d.kind == "unknown_relation_field")
);
assert!(config.report.diagnostics.iter().any(|d| {
d.kind == "invalid_relation_profile" && d.message.contains("unsupported kind 'bogus'")
}));
}
#[test]
fn resolves_manifest_roots_and_reports_missing_sources() {
let tmp = tempfile::tempdir().unwrap();
std::fs::create_dir_all(tmp.path().join("docs")).unwrap();
std::fs::write(
tmp.path().join(MANIFEST_FILE),
r#"
ekf_version: "0.1"
name: package
sources:
docs: ["docs/"]
code:
- path: "missing-code/"
source: glyph
"#,
)
.unwrap();
let config = resolve_package(PackageRequest {
start_dir: Some(tmp.path().to_path_buf()),
..Default::default()
});
assert!(config.report.manifest_found);
assert_eq!(config.report.resolved.vault.as_deref(), Some(tmp.path()));
assert_eq!(
config.report.resolved.docs.as_deref(),
Some(tmp.path().join("docs").as_path())
);
assert!(
config
.report
.resolved
.source_roots
.iter()
.any(|root| root.kind == "docs" && root.status == "compiled")
);
assert!(
config
.report
.resolved
.source_roots
.iter()
.any(|root| root.kind == "code" && root.status == "compiled")
);
assert!(
config
.report
.diagnostics
.iter()
.any(|d| d.kind == "missing_source_root" && d.message.contains("missing-code"))
);
}
#[test]
fn explicit_relative_manifest_uses_current_package_root() {
let tmp = tempfile::tempdir().unwrap();
std::fs::write(
tmp.path().join(MANIFEST_FILE),
r#"
ekf_version: "0.1"
name: package
sources:
docs: ["docs/"]
"#,
)
.unwrap();
let old = std::env::current_dir().unwrap();
std::env::set_current_dir(tmp.path()).unwrap();
let config = resolve_package(PackageRequest {
manifest: Some(PathBuf::from(MANIFEST_FILE)),
..Default::default()
});
std::env::set_current_dir(old).unwrap();
assert_eq!(config.report.package_root.as_deref(), Some(Path::new(".")));
assert_eq!(
config.report.resolved.vault.as_deref(),
Some(Path::new("."))
);
assert!(
config
.report
.resolved
.source_roots
.iter()
.any(|root| root.kind == "vault" && root.path == Path::new("."))
);
}
#[test]
fn infers_zero_config_roots_without_manifest() {
let tmp = tempfile::tempdir().unwrap();
std::fs::create_dir_all(tmp.path().join("docs")).unwrap();
let config = resolve_package(PackageRequest {
start_dir: Some(tmp.path().to_path_buf()),
..Default::default()
});
assert!(!config.report.manifest_found);
assert_eq!(config.report.resolved.vault.as_deref(), Some(tmp.path()));
assert_eq!(
config.report.resolved.docs.as_deref(),
Some(tmp.path().join("docs").as_path())
);
assert_eq!(config.report.resolved.code.as_deref(), Some(tmp.path()));
assert!(
config
.report
.resolved
.source_roots
.iter()
.any(|root| root.kind == "vault" && root.status == "compiled")
);
assert!(
config
.report
.resolved
.source_roots
.iter()
.any(|root| root.kind == "code" && root.status == "compiled")
);
}
#[test]
fn cli_overrides_manifest_roots() {
let tmp = tempfile::tempdir().unwrap();
let override_docs = tmp.path().join("override-docs");
std::fs::create_dir_all(&override_docs).unwrap();
std::fs::write(
tmp.path().join(MANIFEST_FILE),
r#"
ekf_version: "0.1"
sources:
docs: ["docs/"]
"#,
)
.unwrap();
let config = resolve_package(PackageRequest {
start_dir: Some(tmp.path().to_path_buf()),
docs: Some(override_docs.clone()),
..Default::default()
});
assert_eq!(config.report.resolved.docs, Some(override_docs));
assert!(
config
.report
.resolved
.source_roots
.iter()
.any(|root| root.kind == "docs" && root.status == "compiled")
);
assert!(
!config
.report
.resolved
.source_roots
.iter()
.any(|root| root.path.ends_with("docs") && root.status == "declared"),
"CLI docs override should replace manifest docs roots in the package report"
);
}
#[test]
fn reports_legacy_workflows_source_warning() {
let tmp = tempfile::tempdir().unwrap();
std::fs::create_dir_all(tmp.path().join("workflows")).unwrap();
std::fs::write(
tmp.path().join(MANIFEST_FILE),
r#"
ekf_version: "0.1"
sources:
workflows: ["workflows"]
"#,
)
.unwrap();
let config = resolve_package(PackageRequest {
start_dir: Some(tmp.path().to_path_buf()),
..Default::default()
});
assert!(
config
.report
.diagnostics
.iter()
.any(|diagnostic| diagnostic.kind == "legacy_workflows_source")
);
assert!(
config
.report
.resolved
.source_roots
.iter()
.any(|root| root.kind == "workflows" && root.status == "planning")
);
}
#[test]
fn reports_all_v01_package_source_planes() {
let tmp = tempfile::tempdir().unwrap();
for dir in [
"knowledge",
"skills",
"agents",
"capabilities",
"brief-profiles",
"workflows",
"evals",
"src",
] {
std::fs::create_dir_all(tmp.path().join(dir)).unwrap();
}
std::fs::write(
tmp.path().join(MANIFEST_FILE),
r#"
ekf_version: "0.1"
sources:
docs: ["knowledge"]
skills: ["skills"]
agents: ["agents"]
capabilities: ["capabilities"]
brief_profiles: ["brief-profiles"]
workflows: ["workflows"]
evals: ["evals"]
code:
- path: "src"
source: glyph
"#,
)
.unwrap();
let config = resolve_package(PackageRequest {
start_dir: Some(tmp.path().to_path_buf()),
..Default::default()
});
let roots = &config.report.resolved.source_roots;
for kind in [
"vault",
"docs",
"skills",
"agents",
"capabilities",
"brief_profiles",
"workflows",
"evals",
"code",
] {
assert!(
roots.iter().any(|root| root.kind == kind),
"missing EKF source root kind {kind}: {roots:#?}"
);
}
assert!(
roots
.iter()
.any(|root| root.kind == "docs" && root.status == "compiled")
);
assert!(
roots
.iter()
.any(|root| root.kind == "brief_profiles" && root.status == "planning")
);
assert!(
roots
.iter()
.any(|root| root.kind == "workflows" && root.status == "planning")
);
assert!(
roots
.iter()
.any(|root| root.kind == "evals" && root.status == "eval")
);
}
}