import io

p = 'crates/spt-store/src/perch.rs'
s = io.open(p, encoding='utf-8').read()

old = '''/// The echo-commune gate sentinel filename (`.more-done`-equiv; the idle
/// transition arms it). spt-core-owned.
pub const ECHO_GATE_SENTINEL: &str = ".more-done";'''
new = '''/// The **edge** echo-gate sentinel filename — an ATTENTION-CHANGE fire: the
/// attach arm's detach, the registry arm's attention shift, `spt suspend`, or an
/// explicit `api echo-gate set`. Armed rarely and fired UNGATED, because a fire
/// at detachment risk wants timeliness and an age gate over this arm would drop
/// exactly the one that matters. spt-core-owned.
pub const EDGE_ECHO_SENTINEL: &str = ".echo-edge";
/// The **work-driven** echo-gate sentinel filename, armed by every `api state
/// idle` — the adapter's turn-end report — and fired only once it is old enough
/// (the 15-minute window in [`spt_live::pulse`], releases#113 fork 1). It keeps
/// the `.more-done` name because that is exactly what it means and what the
/// sister project's turn-end sentinel was called.
///
/// **It is a SEPARATE FILE from [`EDGE_ECHO_SENTINEL`], not a flag inside one**,
/// and the separation is the property: one writer class per file, so an idle
/// write can never overwrite an armed edge — no last-writer-wins downgrade of an
/// urgent fire into an aged one — read-and-clear stays per-file, and the
/// fire-time distinction is STRUCTURAL rather than parsed out of a byte someone
/// has to remember to write.
// [impl->REQ-ECHO-IDLE-AGE-GATE]
pub const TURN_ECHO_SENTINEL: &str = ".more-done";'''
assert s.count(old) == 1
s = s.replace(old, new)

old = '''/// `<resolved_perch>/.more-done` — the echo-commune gate sentinel. The single
/// path source (6.1) shared by the `api` surface (which arms it) and the M2b
/// pulse (which reads + clears it).
pub fn resolve_echo_gate_file(child_id: &str, hint: ParentHint<'_>) -> PathBuf {
    resolve_perch_path(child_id, hint).join(ECHO_GATE_SENTINEL)
}'''
new = '''/// `<resolved_perch>/.echo-edge` — the EDGE echo-gate sentinel. The single path
/// source (6.1) shared by the surfaces that arm it (the daemon's transition
/// host, `api echo-gate set`) and the pulse that reads + clears it.
pub fn resolve_edge_echo_file(child_id: &str, hint: ParentHint<'_>) -> PathBuf {
    resolve_perch_path(child_id, hint).join(EDGE_ECHO_SENTINEL)
}

/// `<resolved_perch>/.more-done` — the WORK-DRIVEN echo-gate sentinel, armed by
/// `api state idle` and age-gated at the pulse. Single path source (6.1), same
/// as its edge sibling.
// [impl->REQ-ECHO-IDLE-AGE-GATE]
pub fn resolve_turn_echo_file(child_id: &str, hint: ParentHint<'_>) -> PathBuf {
    resolve_perch_path(child_id, hint).join(TURN_ECHO_SENTINEL)
}'''
assert s.count(old) == 1
s = s.replace(old, new)

io.open(p, 'w', encoding='utf-8', newline='\n').write(s)
print('perch.rs ok')

# ── rename every reader of the old spelling ──
import glob, os
renames = [('resolve_echo_gate_file', 'resolve_edge_echo_file'),
           ('ECHO_GATE_SENTINEL', 'EDGE_ECHO_SENTINEL')]
touched = []
for root in ('crates',):
    for dirpath, _dirs, files in os.walk(root):
        if os.sep + 'target' in dirpath:
            continue
        for f in files:
            if not f.endswith('.rs'):
                continue
            fp = os.path.join(dirpath, f)
            if fp.replace('\\', '/') == p:
                continue
            body = io.open(fp, encoding='utf-8').read()
            new_body = body
            for a, b in renames:
                new_body = new_body.replace(a, b)
            if new_body != body:
                io.open(fp, 'w', encoding='utf-8', newline='\n').write(new_body)
                touched.append(fp)
for t in touched:
    print('renamed in', t)
