cordance-emit 0.1.1

Cordance target emitters: AGENTS.md, CLAUDE.md, .cursor/rules, .codex, axiom harness-target.
Documentation

cordance-emit

Target emitters for the Cordance compiler. Each emitter consumes the same CordancePack IR and writes a deterministic, fence-aware file.

crates.io docs.rs license

Part of the Cordance workspace.

Discoverability

Search terms: Cordance emitters, AGENTS.md generator, CLAUDE.md generator, Cursor rules, Codex AGENTS, MCP context, axiom harness target, symlink-safe writes, fenced regeneration.

What it does

Implements the TargetEmitter trait for every Cordance output target:

Emitter Writes
AgentsMdEmitter AGENTS.md
ClaudeMdEmitter CLAUDE.md
CursorEmitter .cursor/rules/*.mdc
CodexEmitter .codex/AGENTS.md, agents/codex/AGENTS.md
HarnessTargetEmitter pai-axiom-project-harness-target.json
PackJsonEmitter .cordance/pack.json
EvidenceMapEmitter .cordance/evidence-map.json

Every emitter:

  • Refuses to follow symlinks / Windows reparse points via cordance_core::fs::safe_write_with_mkdir (POSIX is_symlink + Windows FILE_ATTRIBUTE_REPARSE_POINT, ancestor walk included).
  • Merges fenced regions (<!-- cordance:begin <key> -->) so hand-edits outside fences survive regeneration.
  • Sanitises target-controlled strings before fence interpolation so a hostile cordance.toml can't inject fake fence markers.
  • Validates authority-bearing structures (AxiomProjectHarnessTargetV1) at construct time, not just on the deserialise path.

Install

[dependencies]
cordance-emit = "0.1"
cordance-core = "0.1"

Quick start

use camino::Utf8PathBuf;
use cordance_emit::{TargetEmitter, agents_md::AgentsMdEmitter};
use cordance_core::pack::{CordancePack, PackTargets, ProjectIdentity};
use cordance_core::lock::SourceLock;
use cordance_core::advise::AdviseReport;
use cordance_core::schema;

let repo_root = Utf8PathBuf::from(".");
let pack = CordancePack {
    schema: schema::CORDANCE_PACK_V1.into(),
    project: ProjectIdentity {
        name: "my-project".into(),
        repo_root: repo_root.clone(),
        kind: "rust-workspace".into(),
        host_os: "linux".into(),
        axiom_pin: None,
    },
    sources: vec![],
    doctrine_pins: vec![],
    targets: PackTargets::all(),
    outputs: vec![],
    source_lock: SourceLock::empty(),
    advise: AdviseReport::empty(),
    residual_risk: vec!["claim_ceiling=candidate".into()],
};

let outputs = AgentsMdEmitter.emit(&pack, &repo_root).expect("emit AGENTS.md");
for out in &outputs {
    println!("wrote {} ({} bytes, sha256={})", out.path, out.bytes, out.sha256);
}

See also

License

Dual-licensed under MIT OR Apache-2.0.