import io, os
os.chdir(r"C:\Users\decid\Documents\projects\spt-claude-code")

def rd(p):
    b = io.open(p, "rb").read()
    return b.decode("utf-8").replace("\r\n", "\n"), (b"\r\n" in b)
def wr(p, s, crlf):
    io.open(p, "w", encoding="utf-8", newline=("\r\n" if crlf else "\n")).write(s)
def rep(s, old, new):
    assert s.count(old) == 1, "want 1 got %d: %s" % (s.count(old), old[:80])
    return s.replace(old, new, 1)

# 1) live-relay-int.sh — scope the broad loop by this run's id; recheck the psyche marker pid.
p = "ci/psyche/live-relay-int.sh"; s, crlf = rd(p)
s = rep(s,
'''  pp=$(grep -oE 'PSYCHE_SPAWNED:[^ ]+ pid=[0-9]+' "$LF" 2>/dev/null | grep -oE '[0-9]+' | tail -1)
  [ -n "$pp" ] && taskkill //PID "$pp" //T //F >/dev/null 2>&1
  for p in $(tasklist 2>/dev/null | grep -i claude-spt | awk '{print $2}'); do taskkill //PID "$p" //T //F >/dev/null 2>&1; done''',
'''  pp=$(grep -oE 'PSYCHE_SPAWNED:[^ ]+ pid=[0-9]+' "$LF" 2>/dev/null | grep -oE '[0-9]+' | tail -1)
  # Re-verify the marker pid is still a claude process before a tree-force kill — a remembered pid
  # can have been recycled by the OS (fleet kill-census, 2026-09-07). [impl->REQ-HAZARD-CI-KILL-SCOPING]
  [ -n "$pp" ] && wmic process where "processid=$pp" get name 2>/dev/null | grep -qiE 'claude' \\
    && taskkill //PID "$pp" //T //F >/dev/null 2>&1
  # Reap ONLY this run's claude-spt processes — the daemon-hosted Psyche runner (>=0.8.0 leaves no
  # PSYCHE_SPAWNED marker) plus any adapter child — scoped by this run's unique id in the command
  # line. name-pinned so wmic never matches itself; id-scoped so it never wall-a's a peer agent's
  # live adapter on a shared runner (the old `tasklist | grep claude-spt` killed every agent's
  # adapter on the box). [impl->REQ-HAZARD-CI-KILL-SCOPING]
  for p in $(wmic process where "name like 'claude-spt%' and commandline like '%$ID%'" get processid 2>/dev/null | tr -dc '0-9 \\n' | tr ' ' '\\n' | grep -E '^[0-9]+$'); do
    taskkill //PID "$p" //T //F >/dev/null 2>&1
  done''')
wr(p, s, crlf); print("live-relay ok crlf=", crlf)

# 2) bind-int.sh:47 — recheck RUNPID identity at kill time.
p = "ci/launcher/bind-int.sh"; s, crlf = rd(p)
s = rep(s,
'''  # 1. Kill the broker-spawned claude (the [session.self] target) by its run pid, subtree.
  [ -n "$RUNPID" ] && taskkill //PID "$RUNPID" //T //F >/dev/null 2>&1''',
'''  # 1. Kill the broker-spawned claude (the [session.self] target) by its run pid, subtree.
  #    Re-verify the pid is still a claude process first — a remembered pid can be recycled
  #    (fleet kill-census, 2026-09-07). [impl->REQ-HAZARD-CI-KILL-SCOPING]
  [ -n "$RUNPID" ] && wmic process where "processid=$RUNPID" get name 2>/dev/null | grep -qiE 'claude' \\
    && taskkill //PID "$RUNPID" //T //F >/dev/null 2>&1''')
wr(p, s, crlf); print("bind-int ok crlf=", crlf)

# 3) multi-subnet-bringup-int.sh:114 — recheck RUNPID identity at kill time.
p = "ci/subnet/multi-subnet-bringup-int.sh"; s, crlf = rd(p)
s = rep(s,
'''  for id in $MADE; do spt endpoint purge "$id" --yes --force >/dev/null 2>&1 || true; done
  [ -n "$RUNPID" ] && taskkill //PID "$RUNPID" //T //F >/dev/null 2>&1''',
'''  for id in $MADE; do spt endpoint purge "$id" --yes --force >/dev/null 2>&1 || true; done
  # Re-verify the remembered pid is still a claude process before a tree-force kill — a recycled
  # pid would otherwise take an unrelated tree (fleet kill-census, 2026-09-07). [impl->REQ-HAZARD-CI-KILL-SCOPING]
  [ -n "$RUNPID" ] && wmic process where "processid=$RUNPID" get name 2>/dev/null | grep -qiE 'claude' \\
    && taskkill //PID "$RUNPID" //T //F >/dev/null 2>&1''')
wr(p, s, crlf); print("multi-subnet ok crlf=", crlf)
