import io, sys

P = "crates/spt-live/src/echo.rs"
with io.open(P, "r", encoding="utf-8", newline="") as f:
    src = f.read()

NL = "\r\n" if "\r\n" in src else "\n"


def sub(old, new, label):
    global src
    n = src.count(old)
    if n != 1:
        sys.exit("ANCHOR %s matched %d times (need exactly 1)" % (label, n))
    src = src.replace(old, new, 1)


def L(*lines):
    return NL.join(lines)


# ---------------------------------------------------------------- module doc
sub(
    L(
        "//! feeding it the normalized **history** (T1) on stdin. Its stdout is written",
        "//! as a **commune drop-file** (`<id>-commune.md`) that the drop-file ingest (T4)",
        "//! later folds into the perch's context.",
        "//!",
    ),
    L(
        "//! feeding it the normalized **history** (T1) on stdin. Its stdout is stamped",
        "//! with the echo's provenance header and RETURNED to the caller, which routes it",
        "//! straight into the two-tier context store (`ingest_body`). The brief never",
        "//! transits a file.",
        "//!",
        "//! ## The agent's drop path is not ours (KNOWN-HAZARDS 6.12, releases#276)",
        "//! `<id>-commune.md` is the **agent's** channel: the Self writes its boundary",
        "//! commune there and the daemon ingests and deletes it (6.4). This seam used to",
        "//! write its brief to that same path with no arbitration between the two writers,",
        "//! so a Self commune authored at a `/clear` and not yet ingested was overwritten",
        "//! UNREAD — two of three lost inside one hour, measured. Routing direct is what",
        "//! keeps that path single-writer.",
        "//!",
    ),
    "module-doc-drop-file",
)

sub(
    "//! signal, few/no live edits. Every commune the echo writes is tagged",
    "//! signal, few/no live edits. Every brief the echo produces is tagged",
    "module-doc-writes",
)

sub(
    L(
        "// Clean-room over the M2a bounded seam; spt-core writes the drop file (it is the",
        "// single writer — KNOWN-HAZARDS 6.4), the mind never does.",
        "// [impl->REQ-SEAM-HISTORY]",
        "// [impl->REQ-HAZARD-DROP-FILE-SINGLE-WRITER]",
    ),
    L(
        "// Clean-room over the M2a bounded seam. This seam writes NOTHING: the brief is",
        "// returned and the caller routes it into the tiers (KNOWN-HAZARDS 6.12).",
        "// [impl->REQ-SEAM-HISTORY]",
        "// [impl->REQ-ECHO-BRIEF-DIRECT-ROUTE]",
        "// [impl->REQ-HAZARD-ECHO-NEVER-WRITES-AGENT-DROP]",
    ),
    "header-tags",
)

# ------------------------------------------------------------------- imports
sub(
    L(
        "use spt_runtime::{AgentRuntime, RuntimeError};",
        "use spt_store::atomic::atomic_write_string;",
        "use std::collections::BTreeMap;",
        "use std::path::{Path, PathBuf};",
        "use std::time::Duration;",
    ),
    L(
        "use spt_runtime::{AgentRuntime, RuntimeError};",
        "use std::collections::BTreeMap;",
        "use std::time::Duration;",
    ),
    "imports",
)

# ---------------------------------------------------------------- EchoResult
sub(
    L(
        "/// Outcome of an echo run: the written drop-file path and the brief body.",
        "#[derive(Debug, Clone)]",
        "pub struct EchoResult {",
        "    pub drop_path: PathBuf,",
        "    pub body: String,",
        "}",
    ),
    L(
        "/// Outcome of an echo run: the provenance-stamped brief, ready to route.",
        "///",
        "/// There is deliberately no path here. The brief is routed, not filed — a drop",
        "/// path in this struct is what let the echo overwrite the agent's own commune",
        "/// (KNOWN-HAZARDS 6.12).",
        "#[derive(Debug, Clone)]",
        "pub struct EchoResult {",
        "    pub body: String,",
        "}",
    ),
    "EchoResult",
)

# ----------------------------------------------------------------- EchoError
sub(
    L(
        "    /// Writing the commune drop-file failed.",
        "    Write(std::io::Error),",
    ),
    L(
        "    /// Routing the brief into the two-tier context store failed.",
        "    Ingest(std::io::Error),",
    ),
    "EchoError-variant",
)

sub(
    L(
        "    /// A non-zero exit and a failed drop-file write are the summarizer's own",
        "    /// failures and are hard; only the runtime's bound kill is a load signal.",
    ),
    L(
        "    /// A non-zero exit and a failed route into the store are our own failures and",
        "    /// are hard; only the runtime's bound kill is a load signal.",
    ),
    "is_timeout-doc",
)

sub(
    "            EchoError::NonZero { .. } | EchoError::Write(_) => false,",
    "            EchoError::NonZero { .. } | EchoError::Ingest(_) => false,",
    "is_timeout-arm",
)

sub(
    '            EchoError::Write(e) => write!(f, "writing the commune drop-file failed: {e}"),',
    "            EchoError::Ingest(e) => {"
    + NL
    + '                write!(f, "routing the echo brief into the context store failed: {e}")'
    + NL
    + "            }",
    "Display-arm",
)

# -------------------------------------------------- retry helper + constants
start = src.index("/// Attempts for the access-denied drop-write retry")
end = src.index("/// Run the echo-commune:")
src = src[:start] + src[end:]

# ------------------------------------------------------------ run_echo_commune
sub(
    L(
        "/// Run the echo-commune: feed `history` to the `[session.echo_commune]`",
        "/// summarizer (bounded), then write its brief as the `<id>-commune.md` drop-file",
        "/// under `commune_dir`, tagged `Source: echo-commune`. spt-core is the **single",
        "/// writer** of that file (6.4).",
        "pub fn run_echo_commune(",
        "    runtime: &dyn AgentRuntime,",
        "    id: &str,",
        "    keys: &BTreeMap<String, String>,",
        "    history: &[HistoryRecord],",
        "    commune_dir: &Path,",
        "    timeout: Duration,",
        ") -> Result<EchoResult, EchoError> {",
    ),
    L(
        "/// Run the echo-commune: feed `history` to the `[session.echo_commune]`",
        "/// summarizer (bounded) and return its brief, stamped `Source: echo-commune`.",
        "///",
        "/// The caller routes that body straight into the two-tier store. This seam takes",
        "/// no directory and writes no file: `<id>-commune.md` belongs to the agent, and a",
        "/// second writer on it overwrites Self communes unread (KNOWN-HAZARDS 6.12).",
        "// [impl->REQ-ECHO-BRIEF-DIRECT-ROUTE]",
        "// [impl->REQ-HAZARD-ECHO-NEVER-WRITES-AGENT-DROP]",
        "pub fn run_echo_commune(",
        "    runtime: &dyn AgentRuntime,",
        "    id: &str,",
        "    keys: &BTreeMap<String, String>,",
        "    history: &[HistoryRecord],",
        "    timeout: Duration,",
        ") -> Result<EchoResult, EchoError> {",
    ),
    "run_echo_commune-sig",
)

# the write block itself
start = src.index("    let content = stamp_provenance(SOURCE_ECHO_COMMUNE, &out.stdout);")
end = src.index("    // Two-origin digest tap (REQ-TERM-7)")
src = src[:start] + src[end:]

sub(
    L(
        "    // It is not mirrored into the running context and never was — the brief goes",
        "    // to the drop file written above, whose ingest routes it into the durable",
        "    // context tiers a later session resumes from. The comment that used to stand",
    ),
    L(
        "    // It is not mirrored into the running context and never was — the brief is",
        "    // RETURNED to the caller, which routes it into the durable context tiers a",
        "    // later session resumes from. The comment that used to stand",
    ),
    "digest-tap-comment",
)

sub(
    L(
        "    Ok(EchoResult {",
        "        drop_path,",
        "        body: out.stdout,",
        "    })",
    ),
    L(
        "    Ok(EchoResult {",
        "        body: stamp_provenance(SOURCE_ECHO_COMMUNE, &out.stdout),",
        "    })",
    ),
    "EchoResult-construct",
)

with io.open(P, "w", encoding="utf-8", newline="") as f:
    f.write(src)

print("echo.rs: all anchors applied (newline=%r)" % NL)
