feat(cli): 0106 task 10 — aura process verb family (validate/introspect/register)

New research_docs.rs module: role-addressed process verbs with house-style
fault prose (Display-free enums phrased at the seam), the introspect
exactly-one-of usage guard (exit 2), and content-addressed registration.
Seven binary seam tests pin intrinsic-ok/refusal prose, vocabulary/block/
unwired/content-id introspection, exit codes, and the stored file's
location under the runs root.

Quality-gate finding folded in (and back into the plan): register no
longer re-derives the store path from runs_root — aura-registry now
exposes process_path/campaign_path, the same single mapping its put/get
pair routes through, so the printed path cannot drift from the store
layout.

Verification: research_docs seam tests 7/0, registry 49/0, clippy clean.

refs #189
This commit is contained in:
2026-07-03 15:36:47 +02:00
parent ef3bec5844
commit db09e5de52
5 changed files with 403 additions and 6 deletions
@@ -1560,6 +1560,18 @@ The shipped store idiom (read lib.rs:98-134 first): `?` on fs calls
pub fn get_campaign(&self, content_id: &str) -> Result<Option<String>, RegistryError> {
self.get_doc("campaigns", content_id)
}
/// The store path a process document with this content id lives at —
/// the same single mapping the put/get pair routes through, exposed so
/// consumers never re-derive the layout.
pub fn process_path(&self, content_id: &str) -> PathBuf {
self.doc_path("processes", content_id)
}
/// The store path a campaign document with this content id lives at.
pub fn campaign_path(&self, content_id: &str) -> PathBuf {
self.doc_path("campaigns", content_id)
}
```
If the shipped `put_blueprint`/`get_blueprint` map errors differently than
@@ -2054,9 +2066,12 @@ fn register_process(file: &PathBuf, env: &Env) -> Result<(), String> {
let doc = parse_valid_process(file)
.map_err(|m| format!("refusing to register: {m}"))?;
let canonical = process_to_json(&doc);
let id = env.registry().put_process(&canonical).map_err(|e| e.to_string())?;
let path = env.runs_root().join("processes").join(format!("{id}.json"));
println!("registered process content:{id} ({})", path.display());
let registry = env.registry();
let id = registry.put_process(&canonical).map_err(|e| e.to_string())?;
println!(
"registered process content:{id} ({})",
registry.process_path(&id).display()
);
Ok(())
}
@@ -2382,9 +2397,12 @@ fn register_campaign(file: &PathBuf, env: &Env) -> Result<(), String> {
let doc = parse_valid_campaign(file)
.map_err(|m| format!("refusing to register: {m}"))?;
let canonical = campaign_to_json(&doc);
let id = env.registry().put_campaign(&canonical).map_err(|e| e.to_string())?;
let path = env.runs_root().join("campaigns").join(format!("{id}.json"));
println!("registered campaign content:{id} ({})", path.display());
let registry = env.registry();
let id = registry.put_campaign(&canonical).map_err(|e| e.to_string())?;
println!(
"registered campaign content:{id} ({})",
registry.campaign_path(&id).display()
);
Ok(())
}