diff --git a/_assembler/src/validator.rs b/_assembler/src/validator.rs index 2472216..9a5a2cb 100644 --- a/_assembler/src/validator.rs +++ b/_assembler/src/validator.rs @@ -4,7 +4,7 @@ //! Detailed sub-checks live in their own cubes: //! - `placeholders::check` — {{PLACEHOLDER}} substitution guard //! - `schemas_export::load` — dynamic artifact-schema whitelist loader -//! - this file — structural checks + artifact-schema names +//! - `validator_tests` — unit tests (split per Constructor Pattern) use crate::manifest::Manifest; use crate::placeholders; @@ -21,23 +21,40 @@ pub const OBLIGATORY: &[&str] = &["baseline", "evidence-grading", "memory-protoc pub const KNOWN_ARTIFACT_SCHEMAS: &[&str] = schemas_export::BUILTIN; pub fn validate(m: &Manifest, blocks_dir: &Path) -> Result<(), String> { + check_obligatory_blocks(m)?; + check_blocks_exist(m, blocks_dir)?; + check_handoff_targets(m, blocks_dir)?; + check_domain_fields(m)?; + placeholders::check(m)?; + let known = schemas_export::load(blocks_dir); + check_artifact_schemas(m, &known)?; + check_substrate_role(m, blocks_dir)?; + Ok(()) +} + +fn check_obligatory_blocks(m: &Manifest) -> Result<(), String> { for required in OBLIGATORY { if !m.blocks.iter().any(|b| b == required) { return Err(format!("missing obligatory block: {required}")); } } - if m.handoff.is_empty() { return Err("at least one handoff required".into()); } + Ok(()) +} +fn check_blocks_exist(m: &Manifest, blocks_dir: &Path) -> Result<(), String> { for block in &m.blocks { let path = blocks_dir.join(format!("{block}.md")); if !path.exists() { return Err(format!("block '{block}' not found at {}", path.display())); } } + Ok(()) +} +fn check_domain_fields(m: &Manifest) -> Result<(), String> { if m.domain_in.is_empty() { return Err("domain_in must have at least one entry".into()); } @@ -47,18 +64,32 @@ pub fn validate(m: &Manifest, blocks_dir: &Path) -> Result<(), String> { if m.role.trim().is_empty() { return Err("role must not be empty".into()); } + Ok(()) +} - placeholders::check(m)?; - let known = schemas_export::load(blocks_dir); - check_artifact_schemas(m, &known)?; - check_substrate_role(m, blocks_dir)?; - +/// Verify every `handoff[i].target` resolves to `_manifests/.toml`. +/// Prevents dangling references to unauthored manifests from silently +/// passing validation. See audit 2026-05-02. +pub fn check_handoff_targets(m: &Manifest, blocks_dir: &Path) -> Result<(), String> { + let manifests_dir = blocks_dir + .parent() + .ok_or_else(|| "blocks_dir has no parent (can't locate _manifests/)".to_string())? + .join("_manifests"); + for (i, h) in m.handoff.iter().enumerate() { + let target_path = manifests_dir.join(format!("{}.toml", h.target)); + if !target_path.exists() { + return Err(format!( + "handoff[{i}].target '{}' has no manifest at {}", + h.target, + target_path.display() + )); + } + } Ok(()) } /// If a manifest declares `substrate_role`, verify the role file exists -/// and every capability it references has a `text.md`. Keeping the check -/// here (not only at assemble time) turns mistakes into up-front failures. +/// and every capability it references has a `text.md`. fn check_substrate_role(m: &Manifest, blocks_dir: &Path) -> Result<(), String> { let Some(role) = &m.substrate_role else { return Ok(()); }; let root = blocks_dir @@ -73,7 +104,7 @@ fn check_substrate_role(m: &Manifest, blocks_dir: &Path) -> Result<(), String> { /// v0.15: if a manifest references artifact schema names, they must be in the /// known whitelist. Missing fields are allowed (non-breaking extension). -fn check_artifact_schemas(m: &Manifest, known: &BTreeSet) -> Result<(), String> { +pub fn check_artifact_schemas(m: &Manifest, known: &BTreeSet) -> Result<(), String> { if let Some(name) = &m.produces_artifact { check_known(name, "produces_artifact", known)?; } @@ -99,101 +130,5 @@ fn check_known(name: &str, field: &str, known: &BTreeSet) -> Result<(), } #[cfg(test)] -mod tests { - use super::*; - use crate::manifest::{Handoff, Manifest}; - - fn base() -> Manifest { - Manifest { - name: "test".into(), - description: "d".into(), - tools: vec!["Read".into()], - model: "opus".into(), - role: "r".into(), - blocks: vec!["baseline".into(), "evidence-grading".into(), "memory-protocol".into()], - domain_in: vec!["x".into()], - forbidden_domain: vec!["y".into()], - handoff: vec![Handoff { - target: "a".into(), - trigger: "b".into(), - expects_artifact: None, - produces_artifact: None, - }], - output_extra_fields: vec![], - memory_project: None, - project_claudemd: None, - references: None, - produces_artifact: None, - substrate_role: None, - rule_blocks: vec![], - } - } - - fn builtin_set() -> BTreeSet { - schemas_export::BUILTIN.iter().map(|s| (*s).to_string()).collect() - } - - #[test] - fn artifact_schemas_absent_passes() { - let m = base(); - assert!(check_artifact_schemas(&m, &builtin_set()).is_ok()); - } - - #[test] - fn artifact_schemas_known_names_pass() { - let mut m = base(); - m.produces_artifact = Some("spec".into()); - m.handoff[0].expects_artifact = Some("plan".into()); - m.handoff[0].produces_artifact = Some("patch".into()); - assert!(check_artifact_schemas(&m, &builtin_set()).is_ok()); - } - - #[test] - fn artifact_schemas_reject_unknown_produces() { - let mut m = base(); - m.produces_artifact = Some("not-a-schema".into()); - let err = check_artifact_schemas(&m, &builtin_set()).unwrap_err(); - assert!(err.contains("not-a-schema"), "err: {err}"); - assert!(err.contains("produces_artifact"), "err: {err}"); - } - - #[test] - fn artifact_schemas_reject_unknown_expects_in_handoff() { - let mut m = base(); - m.handoff[0].expects_artifact = Some("zzz".into()); - let err = check_artifact_schemas(&m, &builtin_set()).unwrap_err(); - assert!(err.contains("zzz"), "err: {err}"); - assert!(err.contains("handoff[0].expects_artifact"), "err: {err}"); - } - - #[test] - fn builtin_schemas_do_not_drift_from_kei_artifact() { - // Structural drift test (no runtime dep on kei-artifact): read the - // primitive's source and confirm its BUILTIN list matches ours. - let primitive = Path::new(env!("CARGO_MANIFEST_DIR")) - .join("..") - .join("_primitives/_rust/kei-artifact/src/schemas.rs"); - if !primitive.exists() { - eprintln!("skip drift test: primitive not at {}", primitive.display()); - return; - } - let src = std::fs::read_to_string(&primitive).unwrap(); - let mut names: Vec = Vec::new(); - for line in src.lines() { - let t = line.trim(); - if let Some(rest) = t.strip_prefix("(\"") { - if let Some(end) = rest.find("\",") { - names.push(rest[..end].to_string()); - } - } - } - let mine: Vec = schemas_export::BUILTIN - .iter() - .map(|s| (*s).to_string()) - .collect(); - assert_eq!( - names, mine, - "kei-artifact BUILTIN and schemas_export::BUILTIN drifted" - ); - } -} +#[path = "validator_tests.rs"] +mod tests; diff --git a/_assembler/src/validator_tests.rs b/_assembler/src/validator_tests.rs new file mode 100644 index 0000000..5765973 --- /dev/null +++ b/_assembler/src/validator_tests.rs @@ -0,0 +1,133 @@ +//! Unit tests for manifest validator. Split per Constructor Pattern (file <200 LOC). +//! Imported by `validator.rs` as `#[cfg(test)] #[path = "validator_tests.rs"] mod tests;` + +use super::{check_artifact_schemas, check_handoff_targets}; +use crate::manifest::{Handoff, Manifest}; +use crate::schemas_export; +use std::collections::BTreeSet; +use std::fs; +use std::path::Path; + +fn base() -> Manifest { + Manifest { + name: "test".into(), + description: "d".into(), + tools: vec!["Read".into()], + model: "opus".into(), + role: "r".into(), + blocks: vec![ + "baseline".into(), + "evidence-grading".into(), + "memory-protocol".into(), + ], + domain_in: vec!["x".into()], + forbidden_domain: vec!["y".into()], + handoff: vec![Handoff { + target: "a".into(), + trigger: "b".into(), + expects_artifact: None, + produces_artifact: None, + }], + output_extra_fields: vec![], + memory_project: None, + project_claudemd: None, + references: None, + produces_artifact: None, + substrate_role: None, + rule_blocks: vec![], + } +} + +fn builtin_set() -> BTreeSet { + schemas_export::BUILTIN.iter().map(|s| (*s).to_string()).collect() +} + +#[test] +fn artifact_schemas_absent_passes() { + let m = base(); + assert!(check_artifact_schemas(&m, &builtin_set()).is_ok()); +} + +#[test] +fn artifact_schemas_known_names_pass() { + let mut m = base(); + m.produces_artifact = Some("spec".into()); + m.handoff[0].expects_artifact = Some("plan".into()); + m.handoff[0].produces_artifact = Some("patch".into()); + assert!(check_artifact_schemas(&m, &builtin_set()).is_ok()); +} + +#[test] +fn artifact_schemas_reject_unknown_produces() { + let mut m = base(); + m.produces_artifact = Some("not-a-schema".into()); + let err = check_artifact_schemas(&m, &builtin_set()).unwrap_err(); + assert!(err.contains("not-a-schema"), "err: {err}"); + assert!(err.contains("produces_artifact"), "err: {err}"); +} + +#[test] +fn artifact_schemas_reject_unknown_expects_in_handoff() { + let mut m = base(); + m.handoff[0].expects_artifact = Some("zzz".into()); + let err = check_artifact_schemas(&m, &builtin_set()).unwrap_err(); + assert!(err.contains("zzz"), "err: {err}"); + assert!(err.contains("handoff[0].expects_artifact"), "err: {err}"); +} + +#[test] +fn handoff_target_present_passes() { + let tmp = tempfile::tempdir().unwrap(); + let blocks = tmp.path().join("project/_blocks"); + let manifests = tmp.path().join("project/_manifests"); + fs::create_dir_all(&blocks).unwrap(); + fs::create_dir_all(&manifests).unwrap(); + fs::write(manifests.join("target-agent.toml"), b"").unwrap(); + let mut m = base(); + m.handoff[0].target = "target-agent".into(); + assert!(check_handoff_targets(&m, &blocks).is_ok()); +} + +#[test] +fn handoff_target_missing_fails() { + let tmp = tempfile::tempdir().unwrap(); + let blocks = tmp.path().join("project/_blocks"); + let manifests = tmp.path().join("project/_manifests"); + fs::create_dir_all(&blocks).unwrap(); + fs::create_dir_all(&manifests).unwrap(); + // Do NOT write target-agent.toml — tests that missing file → error. + let mut m = base(); + m.handoff[0].target = "ghost-agent".into(); + let err = check_handoff_targets(&m, &blocks).unwrap_err(); + assert!(err.contains("ghost-agent"), "err: {err}"); + assert!(err.contains("handoff[0].target"), "err: {err}"); +} + +#[test] +fn builtin_schemas_do_not_drift_from_kei_artifact() { + let primitive = Path::new(env!("CARGO_MANIFEST_DIR")) + .join("..") + .join("_primitives/_rust/kei-artifact/src/schemas.rs"); + if !primitive.exists() { + eprintln!("skip drift test: primitive not at {}", primitive.display()); + return; + } + let src = std::fs::read_to_string(&primitive).unwrap(); + let mut names: Vec = Vec::new(); + for line in src.lines() { + let t = line.trim(); + if let Some(rest) = t.strip_prefix("(\"") { + if let Some(end) = rest.find("\",") { + names.push(rest[..end].to_string()); + } + } + } + let mine: Vec = schemas_export::BUILTIN + .iter() + .map(|s| (*s).to_string()) + .collect(); + assert_eq!( + names, mine, + "kei-artifact BUILTIN and schemas_export::BUILTIN drifted" + ); +} diff --git a/_assembler/tests/fixtures/_manifests/architect.toml b/_assembler/tests/fixtures/_manifests/architect.toml new file mode 100644 index 0000000..58446da --- /dev/null +++ b/_assembler/tests/fixtures/_manifests/architect.toml @@ -0,0 +1,27 @@ +# Fixture stub for handoff-target resolution tests. Minimal valid manifest. +name = "architect" +description = "Architect stub." +tools = ["Read", "Glob", "Grep"] +model = "opus" +substrate_role = "read-only" +role = "Stub architect." +blocks = ["baseline", "evidence-grading", "memory-protocol"] +domain_in = ["architecture review"] +forbidden_domain = ["writing code"] + +[[handoff]] +target = "code-implementer" +trigger = "structural finding implies refactor" + +[taxonomy] +kingdom = "manifest" +mechanism = "compose" +domain = "agent" +layer = "agent-substrate" +stage = "design-time" +stability = "stable" +language = "toml" + +[lineage] +creator = "ag-orchestrator-human" +created = "2026-05-02" diff --git a/_assembler/tests/fixtures/_manifests/code-implementer.toml b/_assembler/tests/fixtures/_manifests/code-implementer.toml index e57520a..8b9a220 100644 --- a/_assembler/tests/fixtures/_manifests/code-implementer.toml +++ b/_assembler/tests/fixtures/_manifests/code-implementer.toml @@ -74,9 +74,7 @@ trigger = "task involves ML training / inference / Modal / experiment runners / target = "infra-implementer" trigger = "task involves deploy / CI/CD / secrets / IaC / credentials / public-surface hosting" -[[handoff]] -target = "physics-deriver" -trigger = "task requires math derivation / theorem writing / theorem .md derivation" +# physics-deriver / patent-compliance / patent-researcher manifests not yet authored — handoffs removed 2026-05-02 per audit [[handoff]] target = "critic" @@ -96,11 +94,11 @@ trigger = "structural decision (new module graph, cross-cutting refactor, contra [references] extra = [ - "~/.claude/rules/code-style.md", - "~/.claude/rules/git-conventions.md", - "~/.claude/rules/dev-workflow.md", - "~/.claude/rules/debugging.md", - "~/.claude/rules/karpathy-behavioral.md", + "path:user-rules/code-style.md", + "path:user-rules/git-conventions.md", + "path:user-rules/dev-workflow.md", + "path:user-rules/debugging.md", + "path:user-rules/karpathy-behavioral.md", "MEMORY.md → Architecture Overlay Incident (model_brain.py 227→354 LOC from \"fixes\" — never patch, fix root formulas)", ] diff --git a/_assembler/tests/fixtures/_manifests/critic.toml b/_assembler/tests/fixtures/_manifests/critic.toml new file mode 100644 index 0000000..233cd62 --- /dev/null +++ b/_assembler/tests/fixtures/_manifests/critic.toml @@ -0,0 +1,27 @@ +# Fixture stub for handoff-target resolution tests. Minimal valid manifest. +name = "critic" +description = "Code critic stub." +tools = ["Read", "Glob", "Grep"] +model = "sonnet" +substrate_role = "read-only" +role = "Stub critic." +blocks = ["baseline", "evidence-grading", "memory-protocol"] +domain_in = ["anti-pattern detection"] +forbidden_domain = ["fixing issues"] + +[[handoff]] +target = "code-implementer" +trigger = "confirmed findings need code edits" + +[taxonomy] +kingdom = "manifest" +mechanism = "compose" +domain = "agent" +layer = "agent-substrate" +stage = "design-time" +stability = "stable" +language = "toml" + +[lineage] +creator = "ag-orchestrator-human" +created = "2026-05-02" diff --git a/_assembler/tests/fixtures/_manifests/infra-implementer.toml b/_assembler/tests/fixtures/_manifests/infra-implementer.toml new file mode 100644 index 0000000..fecc122 --- /dev/null +++ b/_assembler/tests/fixtures/_manifests/infra-implementer.toml @@ -0,0 +1,27 @@ +# Fixture stub for handoff-target resolution tests. Minimal valid manifest. +name = "infra-implementer" +description = "Infra/deploy stub." +tools = ["Read", "Write", "Bash"] +model = "sonnet" +substrate_role = "edit-local" +role = "Stub infra-implementer." +blocks = ["baseline", "evidence-grading", "memory-protocol"] +domain_in = ["deploy", "CI/CD"] +forbidden_domain = ["app code"] + +[[handoff]] +target = "code-implementer" +trigger = "app code change needed" + +[taxonomy] +kingdom = "manifest" +mechanism = "compose" +domain = "agent" +layer = "agent-substrate" +stage = "design-time" +stability = "stable" +language = "toml" + +[lineage] +creator = "ag-orchestrator-human" +created = "2026-05-02" diff --git a/_assembler/tests/fixtures/_manifests/ml-implementer.toml b/_assembler/tests/fixtures/_manifests/ml-implementer.toml new file mode 100644 index 0000000..284f153 --- /dev/null +++ b/_assembler/tests/fixtures/_manifests/ml-implementer.toml @@ -0,0 +1,27 @@ +# Fixture stub for handoff-target resolution tests. Minimal valid manifest. +name = "ml-implementer" +description = "ML training stub." +tools = ["Read", "Write", "Bash"] +model = "opus" +substrate_role = "edit-local" +role = "Stub ml-implementer." +blocks = ["baseline", "evidence-grading", "memory-protocol"] +domain_in = ["ML training"] +forbidden_domain = ["theory writing"] + +[[handoff]] +target = "code-implementer" +trigger = "inference path needs Rust" + +[taxonomy] +kingdom = "manifest" +mechanism = "compose" +domain = "agent" +layer = "agent-substrate" +stage = "design-time" +stability = "stable" +language = "toml" + +[lineage] +creator = "ag-orchestrator-human" +created = "2026-05-02" diff --git a/_assembler/tests/fixtures/_manifests/ml-researcher.toml b/_assembler/tests/fixtures/_manifests/ml-researcher.toml new file mode 100644 index 0000000..fe1f2c4 --- /dev/null +++ b/_assembler/tests/fixtures/_manifests/ml-researcher.toml @@ -0,0 +1,27 @@ +# Fixture stub for handoff-target resolution tests. Minimal valid manifest. +name = "ml-researcher" +description = "ML researcher stub." +tools = ["Read", "WebFetch", "WebSearch"] +model = "opus" +substrate_role = "read-only" +role = "Stub ml-researcher." +blocks = ["baseline", "evidence-grading", "memory-protocol"] +domain_in = ["ML literature review"] +forbidden_domain = ["running experiments"] + +[[handoff]] +target = "ml-implementer" +trigger = "hypothesis ready to run" + +[taxonomy] +kingdom = "manifest" +mechanism = "compose" +domain = "agent" +layer = "agent-substrate" +stage = "design-time" +stability = "stable" +language = "toml" + +[lineage] +creator = "ag-orchestrator-human" +created = "2026-05-02" diff --git a/_assembler/tests/fixtures/_manifests/researcher.toml b/_assembler/tests/fixtures/_manifests/researcher.toml index ea3525b..44a07fd 100644 --- a/_assembler/tests/fixtures/_manifests/researcher.toml +++ b/_assembler/tests/fixtures/_manifests/researcher.toml @@ -67,9 +67,7 @@ trigger = "claim needs hard verification (citation sanity, reproduce-in-tests, R target = "ml-researcher" trigger = "question is ML/RL specialized-node (Math-First + tooling-reuse + synthetic-to-real discipline)" -[[handoff]] -target = "patent-researcher" -trigger = "question touches patent prior art, FTO, or novelty (IP-aware handling required)" +# physics-deriver / patent-compliance / patent-researcher manifests not yet authored — handoffs removed 2026-05-02 per audit [[handoff]] target = "architect" @@ -82,9 +80,8 @@ trigger = "findings suggest anti-pattern sweep or Constructor-Pattern violation # References (extra files beyond auto-included baseline/memory/project) [references] extra = [ - "~/.claude/rules/debugging.md", - "~/.claude/rules/no-downgrade-constructive.md", - "~/.claude/agents/validator.md", + "path:user-rules/debugging.md", + "path:user-rules/no-downgrade-constructive.md", ] [taxonomy] diff --git a/_assembler/tests/fixtures/_manifests/security-auditor.toml b/_assembler/tests/fixtures/_manifests/security-auditor.toml new file mode 100644 index 0000000..d2deb78 --- /dev/null +++ b/_assembler/tests/fixtures/_manifests/security-auditor.toml @@ -0,0 +1,27 @@ +# Fixture stub for handoff-target resolution tests. Minimal valid manifest. +name = "security-auditor" +description = "Security auditor stub." +tools = ["Read", "Glob", "Grep"] +model = "opus" +substrate_role = "read-only" +role = "Stub security-auditor." +blocks = ["baseline", "evidence-grading", "memory-protocol"] +domain_in = ["security review"] +forbidden_domain = ["fixing code"] + +[[handoff]] +target = "code-implementer" +trigger = "confirmed vulnerability needs fix" + +[taxonomy] +kingdom = "manifest" +mechanism = "compose" +domain = "agent" +layer = "agent-substrate" +stage = "design-time" +stability = "stable" +language = "toml" + +[lineage] +creator = "ag-orchestrator-human" +created = "2026-05-02" diff --git a/_assembler/tests/fixtures/_manifests/validator.toml b/_assembler/tests/fixtures/_manifests/validator.toml new file mode 100644 index 0000000..7e39f62 --- /dev/null +++ b/_assembler/tests/fixtures/_manifests/validator.toml @@ -0,0 +1,27 @@ +# Fixture stub for handoff-target resolution tests. Minimal valid manifest. +name = "validator" +description = "Fact-checker stub." +tools = ["Read"] +model = "sonnet" +substrate_role = "read-only" +role = "Stub validator." +blocks = ["baseline", "evidence-grading", "memory-protocol"] +domain_in = ["claim verification"] +forbidden_domain = ["fixing issues"] + +[[handoff]] +target = "code-implementer" +trigger = "FALSE API claim needs fix" + +[taxonomy] +kingdom = "manifest" +mechanism = "compose" +domain = "agent" +layer = "agent-substrate" +stage = "design-time" +stability = "stable" +language = "toml" + +[lineage] +creator = "ag-orchestrator-human" +created = "2026-05-02" diff --git a/_assembler/tests/snapshots/code-implementer.snap b/_assembler/tests/snapshots/code-implementer.snap index a82fd29..eb9f438 100644 --- a/_assembler/tests/snapshots/code-implementer.snap +++ b/_assembler/tests/snapshots/code-implementer.snap @@ -1,5 +1,6 @@ --- source: tests/golden.rs +assertion_line: 47 expression: out --- --- @@ -358,7 +359,6 @@ Counter: each FAILED attempt on the SAME problem = +1. Success = reset. **Out (hand off):** - `ml-implementer` — task involves ML training / inference / Modal / experiment runners / Math-First paradigm - `infra-implementer` — task involves deploy / CI/CD / secrets / IaC / credentials / public-surface hosting -- `physics-deriver` — task requires math derivation / theorem writing / theorem .md derivation - `critic` — anti-pattern sweep / code smell review on large diff (>500 LOC) or long function chains - `security-auditor` — code touches auth, crypto, network protocol, deserialization, FFI, or any HIGH-risk surface (see debugging.md Security Review) - `validator` — pre-commit citation or RULE 0.4 check on docs written alongside code @@ -368,7 +368,6 @@ Counter: each FAILED attempt on the SAME problem = +1. Success = reset. - **ml-implementer** — task involves ML training / inference / Modal / experiment runners / Math-First paradigm - **infra-implementer** — task involves deploy / CI/CD / secrets / IaC / credentials / public-surface hosting -- **physics-deriver** — task requires math derivation / theorem writing / theorem .md derivation - **critic** — anti-pattern sweep / code smell review on large diff (>500 LOC) or long function chains - **security-auditor** — code touches auth, crypto, network protocol, deserialization, FFI, or any HIGH-risk surface (see debugging.md Security Review) - **validator** — pre-commit citation or RULE 0.4 check on docs written alongside code @@ -415,9 +414,9 @@ Blockers / next: - `~/.claude/CLAUDE.md` — baseline umbrella - `~/.claude/memory/MEMORY.md` — memory index (adjust if your Claude Code user-slug path differs) -- `~/.claude/rules/code-style.md` -- `~/.claude/rules/git-conventions.md` -- `~/.claude/rules/dev-workflow.md` -- `~/.claude/rules/debugging.md` -- `~/.claude/rules/karpathy-behavioral.md` +- `path:user-rules/code-style.md` +- `path:user-rules/git-conventions.md` +- `path:user-rules/dev-workflow.md` +- `path:user-rules/debugging.md` +- `path:user-rules/karpathy-behavioral.md` - `MEMORY.md → Architecture Overlay Incident (model_brain.py 227→354 LOC from "fixes" — never patch, fix root formulas)` diff --git a/_assembler/tests/snapshots/researcher.snap b/_assembler/tests/snapshots/researcher.snap index b2b8779..763a607 100644 --- a/_assembler/tests/snapshots/researcher.snap +++ b/_assembler/tests/snapshots/researcher.snap @@ -1,5 +1,6 @@ --- source: tests/golden.rs +assertion_line: 33 expression: out --- --- @@ -188,7 +189,6 @@ Rules: architectural decision → E1-E2. Financial (compute) → ONLY E1. Data > **Out (hand off):** - `validator` — claim needs hard verification (citation sanity, reproduce-in-tests, RULE 0.4 gate before commit) - `ml-researcher` — question is ML/RL specialized-node (Math-First + tooling-reuse + synthetic-to-real discipline) -- `patent-researcher` — question touches patent prior art, FTO, or novelty (IP-aware handling required) - `architect` — question is structural/architectural — dependency graph, pattern inventory, module boundaries - `critic` — findings suggest anti-pattern sweep or Constructor-Pattern violation review @@ -196,7 +196,6 @@ Rules: architectural decision → E1-E2. Financial (compute) → ONLY E1. Data > - **validator** — claim needs hard verification (citation sanity, reproduce-in-tests, RULE 0.4 gate before commit) - **ml-researcher** — question is ML/RL specialized-node (Math-First + tooling-reuse + synthetic-to-real discipline) -- **patent-researcher** — question touches patent prior art, FTO, or novelty (IP-aware handling required) - **architect** — question is structural/architectural — dependency graph, pattern inventory, module boundaries - **critic** — findings suggest anti-pattern sweep or Constructor-Pattern violation review @@ -239,6 +238,5 @@ Blockers / next: - `~/.claude/CLAUDE.md` — baseline umbrella - `~/.claude/memory/MEMORY.md` — memory index (adjust if your Claude Code user-slug path differs) -- `~/.claude/rules/debugging.md` -- `~/.claude/rules/no-downgrade-constructive.md` -- `~/.claude/agents/validator.md` +- `path:user-rules/debugging.md` +- `path:user-rules/no-downgrade-constructive.md` diff --git a/_capabilities/output/report-format/capability.toml b/_capabilities/output/report-format/capability.toml index 1d58c47..2c65cb3 100644 --- a/_capabilities/output/report-format/capability.toml +++ b/_capabilities/output/report-format/capability.toml @@ -30,5 +30,6 @@ stability = "stable" language = "rust" [lineage] +parents = [] creator = "ag-orchestrator-human" created = "2026-04-23" diff --git a/_capabilities/output/severity-grade/capability.toml b/_capabilities/output/severity-grade/capability.toml index 39a96a0..5542978 100644 --- a/_capabilities/output/severity-grade/capability.toml +++ b/_capabilities/output/severity-grade/capability.toml @@ -30,5 +30,6 @@ stability = "stable" language = "rust" [lineage] +parents = [] creator = "ag-orchestrator-human" created = "2026-04-23" diff --git a/_capabilities/policy/no-git-ops/capability.toml b/_capabilities/policy/no-git-ops/capability.toml index bb2421a..64fe5e6 100644 --- a/_capabilities/policy/no-git-ops/capability.toml +++ b/_capabilities/policy/no-git-ops/capability.toml @@ -30,6 +30,7 @@ kingdom = "capability" mechanism = "gate" domain = "policy" layer = "agent-substrate" +stage = "runtime" stability = "stable" language = "rust" diff --git a/_capabilities/quality/cargo-check-green/capability.toml b/_capabilities/quality/cargo-check-green/capability.toml index e78e767..f589bdc 100644 --- a/_capabilities/quality/cargo-check-green/capability.toml +++ b/_capabilities/quality/cargo-check-green/capability.toml @@ -25,6 +25,7 @@ kingdom = "capability" mechanism = "verify" domain = "quality" layer = "agent-substrate" +stage = "runtime" stability = "stable" language = "rust" diff --git a/_capabilities/quality/constructor-pattern/capability.toml b/_capabilities/quality/constructor-pattern/capability.toml index b775440..84a9169 100644 --- a/_capabilities/quality/constructor-pattern/capability.toml +++ b/_capabilities/quality/constructor-pattern/capability.toml @@ -30,5 +30,6 @@ stability = "stable" language = "rust" [lineage] +parents = [] creator = "ag-orchestrator-human" created = "2026-04-23" diff --git a/_capabilities/quality/tests-green/capability.toml b/_capabilities/quality/tests-green/capability.toml index c3abc45..e42998c 100644 --- a/_capabilities/quality/tests-green/capability.toml +++ b/_capabilities/quality/tests-green/capability.toml @@ -30,5 +30,6 @@ stability = "stable" language = "rust" [lineage] +parents = [] creator = "ag-orchestrator-human" created = "2026-04-23" diff --git a/_capabilities/safety/no-dep-bump/capability.toml b/_capabilities/safety/no-dep-bump/capability.toml index 1bdb2b4..bfb157d 100644 --- a/_capabilities/safety/no-dep-bump/capability.toml +++ b/_capabilities/safety/no-dep-bump/capability.toml @@ -35,5 +35,6 @@ stability = "stable" language = "rust" [lineage] +parents = [] creator = "ag-orchestrator-human" created = "2026-04-23" diff --git a/_capabilities/scope/files-denylist/capability.toml b/_capabilities/scope/files-denylist/capability.toml index 1884977..d6bd601 100644 --- a/_capabilities/scope/files-denylist/capability.toml +++ b/_capabilities/scope/files-denylist/capability.toml @@ -35,5 +35,6 @@ stability = "stable" language = "rust" [lineage] +parents = [] creator = "ag-orchestrator-human" created = "2026-04-23" diff --git a/_capabilities/scope/files-whitelist/capability.toml b/_capabilities/scope/files-whitelist/capability.toml index c531808..632d446 100644 --- a/_capabilities/scope/files-whitelist/capability.toml +++ b/_capabilities/scope/files-whitelist/capability.toml @@ -35,5 +35,6 @@ stability = "stable" language = "rust" [lineage] +parents = [] creator = "ag-orchestrator-human" created = "2026-04-23" diff --git a/_capabilities/tools/deny-tools/capability.toml b/_capabilities/tools/deny-tools/capability.toml index e67a189..42cfe06 100644 --- a/_capabilities/tools/deny-tools/capability.toml +++ b/_capabilities/tools/deny-tools/capability.toml @@ -30,5 +30,6 @@ stability = "stable" language = "rust" [lineage] +parents = [] creator = "ag-orchestrator-human" created = "2026-04-23" diff --git a/_manifests/architect.toml b/_manifests/architect.toml index 6d0dea7..2759042 100644 --- a/_manifests/architect.toml +++ b/_manifests/architect.toml @@ -86,9 +86,7 @@ trigger = "system is ML/specialized-node-class and structural review must apply target = "validator" trigger = "architectural claim needs hard reproduction (build graph, import graph, coupling metric)" -[[handoff]] -target = "physics-deriver" -trigger = "structural review asks how a new theorem family fits the existing T1-T68 proof graph" +# physics-deriver / patent-compliance / patent-researcher manifests not yet authored — handoffs removed 2026-05-02 per audit # References (extra files beyond auto-included baseline/memory/project) [references] diff --git a/_manifests/code-implementer-flutter.toml b/_manifests/code-implementer-flutter.toml index 96878f0..7d74826 100644 --- a/_manifests/code-implementer-flutter.toml +++ b/_manifests/code-implementer-flutter.toml @@ -21,9 +21,28 @@ blocks = [ "rule-double-audit", ] -domain_in = ["task scope (verbatim user prompt)", "target paths / files"] -forbidden_domain = ["hardcoded secrets (RULE 0.8)", "cross-language drift (use the matching sibling)"] -output_extra_fields = ["Largest file LOC", "Tests pass count"] +domain_in = [ + "Flutter multi-platform apps — iOS, Android, Web, macOS, Windows (RULE 0.2 exception #2 — existing Flutter app)", + "Riverpod state management — NotifierProvider, AsyncNotifierProvider, @riverpod codegen", + "Clean Architecture + Feature-First directory layout", + "freezed value types + json_serializable for data models", + "Supabase client integration, REST/Realtime subscriptions", + "Constructor Pattern enforcement: file <200 LOC, function <30 LOC", +] +forbidden_domain = [ + "Writing Rust / Swift / Python / Go / TypeScript — hand off to matching sibling", + "Hardcoded secrets (RULE 0.8) — every token by ENV var name, never inline", + "setState in complex state — use Riverpod providers", + "Business logic in Widget build() — extract to Notifier / service layer", + "Writing tests later — tests land with the change or before it (Test-First)", + "Skipping `flutter analyze` + `flutter test` before declaring done", +] +output_extra_fields = [ + "Language: Flutter/Dart (RULE 0.2 exception #2 — existing Flutter app)", + "Plan-Mode used: ", + "Constructor Pattern compliance: largest file , largest function ", + "Tests: — `flutter test`", +] [[handoff]] target = "validator" diff --git a/_manifests/code-implementer-go.toml b/_manifests/code-implementer-go.toml index 23c597d..e5f7277 100644 --- a/_manifests/code-implementer-go.toml +++ b/_manifests/code-implementer-go.toml @@ -21,9 +21,27 @@ blocks = [ "rule-double-audit", ] -domain_in = ["task scope (verbatim user prompt)", "target paths / files"] -forbidden_domain = ["hardcoded secrets (RULE 0.8)", "cross-language drift (use the matching sibling)"] -output_extra_fields = ["Largest file LOC", "Tests pass count"] +domain_in = [ + "Mesh networking nodes — TCP/UDP listeners, peer discovery, connection pools", + "Lightweight CLI tools with cobra or stdlib flag (RULE 0.2 exception #2 — existing Go service)", + "Embedded HTTP servers for sidecar services and health endpoints", + "Go stdlib-first: prefer net/http, sync, encoding/json over heavy frameworks", + "Constructor Pattern enforcement: file <200 LOC, function <30 LOC", +] +forbidden_domain = [ + "Writing Rust / Swift / Python / Flutter / TypeScript — hand off to matching sibling", + "Hardcoded secrets (RULE 0.8) — every token by ENV var name, never inline", + "Starting a new Go project without citing RULE 0.2 exception number", + "Global mutable state — pass deps explicitly via constructor injection", + "Goroutine leak — every goroutine must have a cancel path", + "Writing tests later — tests land with the change or before it (Test-First)", +] +output_extra_fields = [ + "Language: Go (RULE 0.2 exception #2 — existing Go service / mesh)", + "Plan-Mode used: ", + "Constructor Pattern compliance: largest file , largest function ", + "Tests: — `go test ./...`", +] [[handoff]] target = "validator" diff --git a/_manifests/code-implementer-python.toml b/_manifests/code-implementer-python.toml index 66fa174..b2becb7 100644 --- a/_manifests/code-implementer-python.toml +++ b/_manifests/code-implementer-python.toml @@ -21,9 +21,26 @@ blocks = [ "rule-double-audit", ] -domain_in = ["task scope (verbatim user prompt)", "target paths / files"] -forbidden_domain = ["hardcoded secrets (RULE 0.8)", "cross-language drift (use the matching sibling)"] -output_extra_fields = ["Largest file LOC", "Tests pass count"] +domain_in = [ + "ML training scripts for models >10M params (RULE 0.2 exception #1 — PyTorch/JAX; inference stays Rust)", + "Extending existing language-locked Python projects (RULE 0.2 exception #2)", + "One-shot scripts <50 lines that will be deleted within 24h (RULE 0.2 exception #5)", + "External-binding wrappers where Python-only SDK exists (RULE 0.2 exception #6)", + "Constructor Pattern enforcement: file <200 LOC, function <30 LOC", +] +forbidden_domain = [ + "Writing Python without stating a RULE 0.2 exception number (1-7) — refuse and delegate to code-implementer-rust", + "Starting new long-lived Python services — Rust is default for inference, servers, and tools", + "Hardcoded secrets (RULE 0.8) — every token by ENV var name, never inline", + "Global mutable state / singleton patterns outside of ML framework idioms", + "Writing tests later — tests land with the change or before it (Test-First)", +] +output_extra_fields = [ + "Language: Python (RULE 0.2 exception #)", + "Plan-Mode used: ", + "Constructor Pattern compliance: largest file , largest function ", + "Tests: — `pytest`", +] [[handoff]] target = "validator" diff --git a/_manifests/code-implementer-swift.toml b/_manifests/code-implementer-swift.toml index 53976b6..99dbc15 100644 --- a/_manifests/code-implementer-swift.toml +++ b/_manifests/code-implementer-swift.toml @@ -21,9 +21,27 @@ blocks = [ "rule-double-audit", ] -domain_in = ["task scope (verbatim user prompt)", "target paths / files"] -forbidden_domain = ["hardcoded secrets (RULE 0.8)", "cross-language drift (use the matching sibling)"] -output_extra_fields = ["Largest file LOC", "Tests pass count"] +domain_in = [ + "macOS menubar apps — NSStatusItem + popover, switch `.regular` → `.accessory` pattern", + "SwiftUI views + AppKit interop for macOS (RULE 0.2 exception #3 — platform-native UI)", + "iOS apps — SwiftUI lifecycle, NavigationStack, @Observable, SwiftData", + "SPM executables with `-Xlinker -sectcreate` info_plist embed + `codesign --force --sign -`", + "Avoid MenuBarExtra with SPM executables — use NSStatusItem directly (platform known issue)", + "Constructor Pattern enforcement: file <200 LOC, function <30 LOC", +] +forbidden_domain = [ + "Writing Rust / Python / Go / Flutter / TypeScript — hand off to matching sibling", + "Hardcoded secrets (RULE 0.8) — every token by ENV var name, never inline", + "Force-unwrapping optionals without fallback or guard", + "MenuBarExtra with SPM executables (broken — use NSStatusItem)", + "Writing tests later — tests land with the change or before it (Test-First)", +] +output_extra_fields = [ + "Language: Swift (RULE 0.2 exception #3 — platform-native macOS/iOS UI)", + "Plan-Mode used: ", + "Constructor Pattern compliance: largest file , largest function ", + "Tests: — `swift test`", +] [[handoff]] target = "validator" diff --git a/_manifests/code-implementer-typescript.toml b/_manifests/code-implementer-typescript.toml index 9891068..ebdd60c 100644 --- a/_manifests/code-implementer-typescript.toml +++ b/_manifests/code-implementer-typescript.toml @@ -21,9 +21,28 @@ blocks = [ "rule-double-audit", ] -domain_in = ["task scope (verbatim user prompt)", "target paths / files"] -forbidden_domain = ["hardcoded secrets (RULE 0.8)", "cross-language drift (use the matching sibling)"] -output_extra_fields = ["Largest file LOC", "Tests pass count"] +domain_in = [ + "Next.js 16 app-router pages, API routes, server actions", + "Node services with Express / Hono — type-safe with Zod schemas", + "Browser-DOM TypeScript — event handlers, fetch wrappers, Web APIs", + "Drizzle ORM schemas + queries (PostgreSQL / SQLite / MySQL)", + "Zod validation schemas for request/response contracts", + "Constructor Pattern enforcement: file <200 LOC, function <30 LOC", +] +forbidden_domain = [ + "Writing Rust / Swift / Python / Go / Flutter — hand off to matching sibling", + "Hardcoded secrets (RULE 0.8) — every token by ENV var name, never inline", + "any=true / ts-ignore / @ts-expect-error without filed issue comment", + "Raw SQL string-building — use Drizzle query builder or parameterised statements", + "Writing tests later — tests land with the change or before it (Test-First)", +] +output_extra_fields = [ + "Language: TypeScript (RULE 0.2 exception #4 — browser/DOM)", + "Plan-Mode used: ", + "Constructor Pattern compliance: largest file , largest function ", + "Tests: ", + "cargo-check: N/A (TypeScript) | tsc --noEmit: ", +] [[handoff]] target = "validator" diff --git a/_manifests/code-implementer.toml b/_manifests/code-implementer.toml index a964258..8f4a938 100644 --- a/_manifests/code-implementer.toml +++ b/_manifests/code-implementer.toml @@ -74,9 +74,7 @@ trigger = "task involves ML training / inference / Modal / experiment runners / target = "infra-implementer" trigger = "task involves deploy / CI/CD / secrets / IaC / credentials / public-surface hosting" -[[handoff]] -target = "physics-deriver" -trigger = "task requires math derivation / theorem writing / theorem .md derivation" +# physics-deriver / patent-compliance / patent-researcher manifests not yet authored — handoffs removed 2026-05-02 per audit [[handoff]] target = "critic" diff --git a/_manifests/critic.toml b/_manifests/critic.toml index 2427db1..c5260e2 100644 --- a/_manifests/critic.toml +++ b/_manifests/critic.toml @@ -31,7 +31,7 @@ domain_in = [ "Performance — N+1 queries, missing indexes, memory leaks, blocking I/O, hot-path allocations", "Tech debt — duplicated logic, inconsistent naming, missing tests, outdated deps", "Constructor-Pattern violations — files >200 LOC, functions >30 LOC, mixed responsibilities", - "Cross-ref rules DB: `~/.claude/skills/architecture-rules/references/antipatterns.md`, `duplication.md`, `stack-compat.md`", + "Cross-ref rules DB: `path:user-skills/architecture-rules/references/antipatterns.md`, `duplication.md`, `stack-compat.md`", ] forbidden_domain = [ @@ -71,13 +71,14 @@ target = "architect" trigger = "anti-pattern is structural (new family, needs design review)" # References (extra files beyond auto-included baseline/memory/project) +# ~/.claude/ absolute paths stripped — not portable across installs. See audit 2026-05-02. [references] extra = [ "path:user-rules/debugging.md", "path:user-rules/code-style.md", - "~/.claude/skills/architecture-rules/references/antipatterns.md", - "~/.claude/skills/architecture-rules/references/duplication.md", - "~/.claude/skills/architecture-rules/references/stack-compat.md", + "path:user-skills/architecture-rules/references/antipatterns.md", + "path:user-skills/architecture-rules/references/duplication.md", + "path:user-skills/architecture-rules/references/stack-compat.md", ] [taxonomy] diff --git a/_manifests/frontend-validator.toml b/_manifests/frontend-validator.toml index 9beee87..ccfbf7b 100644 --- a/_manifests/frontend-validator.toml +++ b/_manifests/frontend-validator.toml @@ -28,7 +28,7 @@ Your steps in order, each emitting a section of the final report: 6. **A11y quick** — if `package.json` has `a11y-check` script, invoke. Else skip. Severity: WARN. -6. **Verdict block** — summary table: each check, status (PASS / WARN / FAIL), brief evidence pointer. +7. **Verdict block** — summary table: each check, status (PASS / WARN / FAIL), brief evidence pointer. You do NOT autofix. You do NOT spawn other agents. You do NOT commit. You report. """ diff --git a/_manifests/infra-implementer-cicd.toml b/_manifests/infra-implementer-cicd.toml index 9080a5e..46b31f1 100644 --- a/_manifests/infra-implementer-cicd.toml +++ b/_manifests/infra-implementer-cicd.toml @@ -21,9 +21,27 @@ blocks = [ "rule-double-audit", ] -domain_in = ["task scope (verbatim user prompt)", "target paths / files"] -forbidden_domain = ["hardcoded secrets (RULE 0.8)", "cross-language drift (use the matching sibling)"] -output_extra_fields = ["Largest file LOC", "Tests pass count"] +domain_in = [ + "GitHub Actions workflows — build matrices, caching, artifact upload/download", + "GitLab CI pipelines — stages, rules, variables, Docker-in-Docker runners", + "Forgejo / Gitea workflows (subset of GitHub Actions syntax)", + "Build-and-deploy scripts — cargo build --release, docker build+push, npm run build", + "Secret-injection from vault / GitHub Secrets / GitLab CI variables — ENV only, never inline", + "Staged deploys — canary, blue/green, rollback triggers", +] +forbidden_domain = [ + "IaC (Terraform/Pulumi/CDK) — hand off to infra-implementer-iac", + "Dockerfiles or OCI images — hand off to infra-implementer-container", + "Secrets management (Vault, sops, age) — hand off to infra-implementer-secrets", + "Hardcoded secrets in workflow YAML (RULE 0.8) — use `${{ secrets.NAME }}` / ENV refs", + "Skipping build-cache steps — always cache cargo registry + target, node_modules, pip cache", +] +output_extra_fields = [ + "CI platform: GitHub Actions | GitLab CI | Forgejo", + "Plan-Mode used: ", + "Jobs defined: ", + "Secrets used: ", +] [[handoff]] target = "validator" diff --git a/_manifests/infra-implementer-container.toml b/_manifests/infra-implementer-container.toml index 4ed73f1..945e184 100644 --- a/_manifests/infra-implementer-container.toml +++ b/_manifests/infra-implementer-container.toml @@ -21,9 +21,28 @@ blocks = [ "rule-double-audit", ] -domain_in = ["task scope (verbatim user prompt)", "target paths / files"] -forbidden_domain = ["hardcoded secrets (RULE 0.8)", "cross-language drift (use the matching sibling)"] -output_extra_fields = ["Largest file LOC", "Tests pass count"] +domain_in = [ + "Dockerfiles — multi-stage builds with cargo-chef (Rust), distroless final image", + "OCI image labelling — `org.opencontainers.image.*` standard labels", + "docker-compose for local dev + integration tests", + "Helm chart templates for Kubernetes deployments", + "Non-root user (`USER nonroot:nonroot`), layer-pinning with digest locks", + "Build-cache optimisation: COPY Cargo.toml first, then src — avoid rebuilding deps on code changes", +] +forbidden_domain = [ + "App code changes — hand off to matching code-implementer sibling", + "Kubernetes manifests outside Helm chart templates — hand off to infra-implementer-iac", + "Hardcoded secrets in Dockerfile / compose (RULE 0.8) — use build-args + secret mounts only", + "Running as root in final image", + "FROM latest — always pin to a specific digest or version tag", +] +output_extra_fields = [ + "Base image: ", + "Plan-Mode used: ", + "Stages: ", + "Final image size estimate: ", + "Non-root user: ", +] [[handoff]] target = "validator" diff --git a/_manifests/infra-implementer-iac.toml b/_manifests/infra-implementer-iac.toml index a94cbf8..aeff337 100644 --- a/_manifests/infra-implementer-iac.toml +++ b/_manifests/infra-implementer-iac.toml @@ -21,9 +21,27 @@ blocks = [ "rule-double-audit", ] -domain_in = ["task scope (verbatim user prompt)", "target paths / files"] -forbidden_domain = ["hardcoded secrets (RULE 0.8)", "cross-language drift (use the matching sibling)"] -output_extra_fields = ["Largest file LOC", "Tests pass count"] +domain_in = [ + "Terraform HCL modules — resource-per-file, remote backend (S3/GCS/Terraform Cloud), lock file", + "Pulumi (TypeScript or Go) — stack-per-env, explicit outputs, state in Pulumi Cloud or S3", + "OpenTofu (Terraform OSS fork) — drop-in compatible HCL", + "AWS CDK (TypeScript) — construct libraries, stack separation by lifecycle", + "Module-per-resource-type layout: one directory per resource family", + "State-management discipline: remote backend required, local state forbidden in production", +] +forbidden_domain = [ + "CI/CD yaml pipelines — hand off to infra-implementer-cicd", + "Dockerfiles or OCI images — hand off to infra-implementer-container", + "Hardcoded secrets in .tf / .ts / pulumi config (RULE 0.8) — use var + SecretManager refs", + "Monolithic single-file IaC (>200 LOC) — decompose into modules", + "Committing `terraform.tfstate` or `.tfstate.backup` to git — use remote backend only", +] +output_extra_fields = [ + "IaC tool: Terraform | Pulumi | OpenTofu | CDK", + "Plan-Mode used: ", + "Resources defined: ", + "State backend: ", +] [[handoff]] target = "validator" diff --git a/_manifests/infra-implementer-secrets.toml b/_manifests/infra-implementer-secrets.toml index 36ac52e..8331d25 100644 --- a/_manifests/infra-implementer-secrets.toml +++ b/_manifests/infra-implementer-secrets.toml @@ -21,9 +21,27 @@ blocks = [ "rule-double-audit", ] -domain_in = ["task scope (verbatim user prompt)", "target paths / files"] -forbidden_domain = ["hardcoded secrets (RULE 0.8)", "cross-language drift (use the matching sibling)"] -output_extra_fields = ["Largest file LOC", "Tests pass count"] +domain_in = [ + "sops encryption — `.sops.yaml` key rules, `sops --encrypt` / `--decrypt` workflow", + "age key generation + encryption for file-at-rest secrets", + "HashiCorp Vault — dynamic secrets, AppRole auth, KV v2, lease renewal", + "Cloudflare Secret / AWS Secrets Manager / GCP Secret Manager integration patterns", + "ENV-var injection patterns: `.env` files gitignored, referenced via `$VAR` only (RULE 0.8)", + "Rotation playbooks — how to rotate a token without downtime", +] +forbidden_domain = [ + "App code changes — hand off to matching code-implementer sibling", + "CI/CD pipeline YAML — hand off to infra-implementer-cicd", + "Hardcoded secret values anywhere (RULE 0.8 hard ban)", + "Committing `.env` files with real values to git", + "Storing secrets in IaC state files — use Secrets Manager + data source", +] +output_extra_fields = [ + "Secrets tool: sops | age | Vault | CF Secret | AWS SM | GCP SM", + "Plan-Mode used: ", + "Secrets catalogued: ", + "RULE 0.8 compliance: ", +] [[handoff]] target = "validator" diff --git a/_manifests/ml-implementer.toml b/_manifests/ml-implementer.toml index bbaf34f..94851b2 100644 --- a/_manifests/ml-implementer.toml +++ b/_manifests/ml-implementer.toml @@ -78,9 +78,7 @@ output_extra_fields = [ ] # Handoffs MUST come after all top-level keys (TOML array-of-tables scope rule) -[[handoff]] -target = "physics-deriver" -trigger = "numerical result implies a new theorem / refutation / observable classification (write to `theory/**/*.md`)" +# physics-deriver / patent-compliance / patent-researcher manifests not yet authored — handoffs removed 2026-05-02 per audit [[handoff]] target = "ml-researcher" @@ -104,7 +102,7 @@ trigger = "anti-pattern sweep on training script (coefficient creep, E1-E11 chec [[handoff]] target = "architect" -trigger = "multi-node multi-node composition design, experiment matrix layout, benchmark/baseline integration" +trigger = "multi-node composition design, experiment matrix layout, benchmark/baseline integration" [references] extra = [ @@ -114,7 +112,7 @@ extra = [ "path:user-rules/observable-classification.md", "path:user-rules/manifold-tangent-sanity.md", "path:user-rules/no-downgrade-constructive.md", - "path:user-memory/wrong-paths-specialized-ml.md", + "path:user-memory/wrong-paths-specialized-ml.md", # TODO verify path:user-memory exists in assembler resolver "MEMORY.md → Compute Cost Incident (2026-02-26): promised $27, spent $98.78 on Modal. NEVER AGAIN.", "MEMORY.md → Architecture Overlay Incident: model_brain.py 227→354 LOC from audit fixes. No Patching.", ] diff --git a/_manifests/ml-researcher.toml b/_manifests/ml-researcher.toml index 59ddd98..b2fb1f6 100644 --- a/_manifests/ml-researcher.toml +++ b/_manifests/ml-researcher.toml @@ -73,9 +73,7 @@ output_extra_fields = [ target = "ml-implementer" trigger = "hypothesis is formulated and experiment must be run (train, benchmark, ablate, Monte Carlo)" -[[handoff]] -target = "physics-deriver" -trigger = "literature finding feeds a theorem / derivation in `~/your-project/theory/`" +# physics-deriver / patent-compliance / patent-researcher manifests not yet authored — handoffs removed 2026-05-02 per audit [[handoff]] target = "validator" @@ -85,10 +83,6 @@ trigger = "citation sanity before commit (RULE 0.4 gate) or reproducibility clai target = "researcher" trigger = "non-ML sub-question surfaces (general library / API / pricing / doc lookup)" -[[handoff]] -target = "patent-researcher" -trigger = "ML finding is patent-relevant (prior art, FTO, novelty for a filable claim)" - [[handoff]] target = "architect" trigger = "question is about ML-system architecture (node graph, data-flow, module boundaries) not algorithm" @@ -101,7 +95,7 @@ extra = [ "path:user-rules/observable-classification.md", "path:user-rules/api-cost-guard.md", "path:user-rules/no-downgrade-constructive.md", - "path:user-memory/wrong-paths-specialized-ml.md", + "path:user-memory/wrong-paths-specialized-ml.md", # TODO verify path:user-memory exists in assembler resolver ] [taxonomy] diff --git a/_manifests/researcher-code.toml b/_manifests/researcher-code.toml index e76cb75..7835162 100644 --- a/_manifests/researcher-code.toml +++ b/_manifests/researcher-code.toml @@ -17,9 +17,24 @@ blocks = [ "memory-protocol", ] -domain_in = ["task scope (verbatim user prompt)", "target paths / files"] -forbidden_domain = ["hardcoded secrets (RULE 0.8)", "cross-language drift (use the matching sibling)"] -output_extra_fields = ["Largest file LOC", "Tests pass count"] +domain_in = [ + "Symbol discovery — Grep for function/type/constant definitions across the repo", + "Dependency tracing — who imports X, what does X import (caller/callee graph via Grep)", + "Ownership mapping — identify the canonical SSoT file for a type or route", + "Analogue search — find existing implementations before proposing new code", + "Constructor-Pattern audit — identify files >200 LOC or functions >30 LOC", +] +forbidden_domain = [ + "Web research — hand off to researcher-web", + "Editing or writing code (read-only agent — no Edit / Write)", + "Whole-file dumps when Grep + targeted Read suffices", + "Fabricating file paths, function names, or line numbers", +] +output_extra_fields = [ + "Sources cited (≥2 for load-bearing)", + "Evidence grade per claim", + "Gaps section present", +] [[handoff]] target = "validator" diff --git a/_manifests/researcher-web.toml b/_manifests/researcher-web.toml index afa612f..36706f2 100644 --- a/_manifests/researcher-web.toml +++ b/_manifests/researcher-web.toml @@ -17,9 +17,25 @@ blocks = [ "memory-protocol", ] -domain_in = ["task scope (verbatim user prompt)", "target paths / files"] -forbidden_domain = ["hardcoded secrets (RULE 0.8)", "cross-language drift (use the matching sibling)"] -output_extra_fields = ["Largest file LOC", "Tests pass count"] +domain_in = [ + "Official documentation — vendor docs, RFC, spec, changelog, pricing page", + "GitHub repositories — README, CHANGELOG, open issues, PR descriptions", + "Academic and technical papers — arXiv, ACM DL, IEEE (cite with [VERIFIED: url] per RULE 0.4)", + "Pricing and SLA pages — E1 only (primary source from vendor, not third-party comparison)", + "Blog posts and tutorials — max E4; flag recency and single-source limit", +] +forbidden_domain = [ + "Local filesystem reads — hand off to researcher-code", + "Hardcoded or paraphrased secret values anywhere", + "Fabricating URLs, DOIs, authors, or version numbers (RULE 0.4 hard ban)", + "Quoting Stack Overflow / Reddit / random blogs above E4", + "Pricing claims from anything other than the vendor's own pricing page", +] +output_extra_fields = [ + "Sources cited (≥2 for load-bearing)", + "Evidence grade per claim", + "Gaps section present", +] [[handoff]] target = "validator" diff --git a/_manifests/researcher.toml b/_manifests/researcher.toml index 0ef1eea..d00ffa1 100644 --- a/_manifests/researcher.toml +++ b/_manifests/researcher.toml @@ -67,9 +67,7 @@ trigger = "claim needs hard verification (citation sanity, reproduce-in-tests, R target = "ml-researcher" trigger = "question is ML/RL specialized-node (Math-First + tooling-reuse + synthetic-to-real discipline)" -[[handoff]] -target = "patent-researcher" -trigger = "question touches patent prior art, FTO, or novelty (IP-aware handling required)" +# physics-deriver / patent-compliance / patent-researcher manifests not yet authored — handoffs removed 2026-05-02 per audit [[handoff]] target = "architect" @@ -80,11 +78,11 @@ target = "critic" trigger = "findings suggest anti-pattern sweep or Constructor-Pattern violation review" # References (extra files beyond auto-included baseline/memory/project) +# ~/.claude/agents/validator.md stripped — machine-local file, not portable. See audit 2026-05-02. [references] extra = [ "path:user-rules/debugging.md", "path:user-rules/no-downgrade-constructive.md", - "~/.claude/agents/validator.md", ] [taxonomy] diff --git a/_manifests/validator.toml b/_manifests/validator.toml index d98af83..3956409 100644 --- a/_manifests/validator.toml +++ b/_manifests/validator.toml @@ -56,19 +56,13 @@ output_extra_fields = [ "Overall verdict: ALL VERIFIED | PARTIAL (fix list) | BLOCK (FALSE findings present)", ] -# Handoffs MUST come after all top-level keys (TOML array-of-tables scope rule) -[[handoff]] -target = "physics-deriver" -trigger = "theory doc has FALSE or UNVERIFIED citation — rewrite before commit" +# physics-deriver / patent-compliance / patent-researcher manifests not yet authored — handoffs removed 2026-05-02 per audit +# Handoffs MUST come after all top-level keys (TOML array-of-tables scope rule) [[handoff]] target = "ml-researcher" trigger = "claim needs literature/arXiv deep-search to resolve (returns `[VERIFIED: url]`)" -[[handoff]] -target = "patent-compliance" -trigger = "FALSE claim is in patent draft — pre-filing block" - [[handoff]] target = "code-implementer" trigger = "FALSE API/version claim is in code — needs fix before ship" diff --git a/_primitives/_rust/kei-registry/tests/fixtures/atom-sample/.kei-registry-ignore b/_primitives/_rust/kei-registry/tests/fixtures/atom-sample/.kei-registry-ignore new file mode 100644 index 0000000..fe4848d --- /dev/null +++ b/_primitives/_rust/kei-registry/tests/fixtures/atom-sample/.kei-registry-ignore @@ -0,0 +1 @@ +# DNA-INDEX scanner: skip this directory (test fixture) diff --git a/_primitives/_rust/kei-registry/tests/fixtures/fake-kit/.kei-registry-ignore b/_primitives/_rust/kei-registry/tests/fixtures/fake-kit/.kei-registry-ignore new file mode 100644 index 0000000..fe4848d --- /dev/null +++ b/_primitives/_rust/kei-registry/tests/fixtures/fake-kit/.kei-registry-ignore @@ -0,0 +1 @@ +# DNA-INDEX scanner: skip this directory (test fixture) diff --git a/_primitives/_rust/kei-registry/tests/fixtures/mini-kit/.kei-registry-ignore b/_primitives/_rust/kei-registry/tests/fixtures/mini-kit/.kei-registry-ignore new file mode 100644 index 0000000..fe4848d --- /dev/null +++ b/_primitives/_rust/kei-registry/tests/fixtures/mini-kit/.kei-registry-ignore @@ -0,0 +1 @@ +# DNA-INDEX scanner: skip this directory (test fixture) diff --git a/_roles/auditor.toml b/_roles/auditor.toml index 5d7d164..11dc284 100644 --- a/_roles/auditor.toml +++ b/_roles/auditor.toml @@ -26,3 +26,17 @@ language = "toml" [pipeline] handoff = ["merger"] + +[taxonomy] +kingdom = "role" +mechanism = "audit" +domain = "agent" +layer = "agent-substrate" +stage = "runtime" +stability = "stable" +language = "toml" + +[lineage] +parents = [] +creator = "ag-orchestrator-human" +created = "2026-04-23" diff --git a/_roles/explorer.toml b/_roles/explorer.toml index ce54266..7737c76 100644 --- a/_roles/explorer.toml +++ b/_roles/explorer.toml @@ -3,6 +3,7 @@ name = "explorer" display-name = "explorer + cargo-check (read-only analyst with build probe)" description = "Read-only analyst that may run cargo-family commands for build/test introspection. No edits, no git, no non-cargo shell." spawnable = true +# claude-subagent-type values are case-sensitive; "Explore" is the Claude Code built-in claude-subagent-type = "Explore" [capabilities] diff --git a/_roles/merger.toml b/_roles/merger.toml index 330d4c3..9f24a96 100644 --- a/_roles/merger.toml +++ b/_roles/merger.toml @@ -26,3 +26,17 @@ language = "toml" [pipeline] handoff = [] + +[taxonomy] +kingdom = "role" +mechanism = "merge" +domain = "agent" +layer = "agent-substrate" +stage = "runtime" +stability = "stable" +language = "toml" + +[lineage] +parents = [] +creator = "ag-orchestrator-human" +created = "2026-04-23"