p = 'd2/rig-d2/run-d2.sh'
s = open(p, encoding='utf-8', newline='').read()

s = s.replace('CASE="${1:?usage: run-d2.sh A|B|C|D|E|F|G|H1|H2|I|J|K|L|all}"',
              'CASE="${1:?usage: run-d2.sh A|B|C|D|E|F|G|H1|H2|I|J|K|L|R2|R3|R4|R5|residual|all}"')

# --- knobs: the process model replaces the old residue-string knob
old = "  local op_setup=accept op_teardown=clean residue=none"
new = ("  # PROCESS MODEL AT CLEANUP TIME. Default 'none' (the tracked processes are gone) so that\n"
       "  # every other case tests ITS OWN variable; the residual arms below set it deliberately.\n"
       "  local op_setup=accept op_teardown=clean procmodel=none identmode=live")
assert s.count(old) == 1, 'knob decl'
s = s.replace(old, new)

old2 = "    J) residue=some ;;"
new2 = ("    # THE RESIDUAL ARMS. Their command lines are r10's real ones and contain NO reference to\n"
        "    # the isolated home, which is what defeats a command-line predicate.\n"
        "    J)  procmodel=both ;;        # supervisor AND brain still live\n"
        "    R2) procmodel=brainonly ;;   # supervisor gone, ORPHANED BRAIN surviving\n"
        "    R3) procmodel=none ;;        # both measured gone -- the only path to VERIFIED\n"
        "    R4) procmodel=unreadable ;;  # the table cannot be read at cleanup: UNREADABLE, not clean\n"
        "    R5) procmodel=reused ;;      # the pid answers, but it is a stranger's process")
assert s.count(old2) == 1, 'J knob'
s = s.replace(old2, new2)

old3 = '           FP_ELEVATED=False FP_EXE="$SPEXE" FP_RESIDUE_MODE="$residue" \\'
new3 = '           FP_ELEVATED=False FP_EXE="$SPEXE" FP_PROC_MODEL="$procmodel" FP_IDENT_MODE="$identmode" \\'
assert s.count(old3) == 1, 'env'
s = s.replace(old3, new3)

# --- the operator writes the pid file the product would write, so identity capture has a subject
old4 = """              : > "$RIGLOG/pair-present"
              printf 'owner=%s\\n' "$SPSP/fp-home" > "$RIGLOG/listener-bound-29470\""""
new4 = """              : > "$RIGLOG/pair-present"
              printf 'owner=%s\\n' "$SPSP/fp-home" > "$RIGLOG/listener-bound-29470"
              # The elevated leg starts the daemon, and the product writes its pid file. The rig
              # writes it here for the same reason: identity capture has to have a subject.
              mkdir -p "$SPSP/fp-home"
              printf '%s' "${FP_SUP_PID:-4001}" > "$SPSP/fp-home/daemon.pid\""""
assert s.count(old4) == 1, 'pid file'
s = s.replace(old4, new4)

# --- assertions for the residual arms, and A/J re-pointed at the new evidence
old5 = '''    J)
      has   "teardown itself verified (rules absent)" "$F" 'TEARDOWN_VERIFIED' 1'''
new5 = '''    J)
      # SUPERVISOR AND BRAIN BOTH LIVE, with r10's real command lines. Rules and listener are
      # ABSENT here, so nothing but the tracked identities can refuse the verdict -- which is
      # exactly the false-clean path the old command-line predicate left open.
      has   "the tracked supervisor is reported LIVE"  "$F" 'RESIDUE role=supervisor .* state=LIVE' 1
      has   "the tracked brain is reported LIVE"       "$F" 'RESIDUE role=brain .* state=LIVE' 1
      has   "neither command line contains the home"   "$F" 'cmd=\\[.*daemon run --detached\\]' 1
      check "no residual is claimed by a home-string match" 0 "$(grep -c 'fp-home.*state=LIVE' "$F")"
      has   "live and unreadable are summarised apart"  "$F" 'RESIDUE_SUMMARY live=2 gone=0 unreadable=0' 1
      has   "teardown itself verified (rules absent)" "$F" 'TEARDOWN_VERIFIED' 1'''
assert s.count(old5) == 1, 'J asserts'
s = s.replace(old5, new5)

# R-case assertions, inserted before the K helper
anchor = "# ---- K: the VALIDATOR's own arms"
radd = '''    R2)
      # THE ORPHANED BRAIN. The supervisor is gone; a check that stopped at the pid file would
      # call this clean, and the brain is the process that holds the executable open.
      has   "the supervisor is measured GONE"       "$F" 'RECHECK role=supervisor .* state=GONE' 1
      has   "the ORPHANED BRAIN is reported LIVE"   "$F" 'RESIDUE role=brain .* state=LIVE' 1
      has   "summary keeps the two apart"           "$F" 'RESIDUE_SUMMARY live=1 gone=1 unreadable=0' 1
      has   "CLEANUP=PENDING"                       "$LED" 'CLEANUP=PENDING' 1
      has   "residual_state=LIVE"                   "$LED" 'residual_state=LIVE' 1
      check "driver exit 6"                         6 "$rc"
      check "nothing was killed"                    0 "$(grep -c 'Stop-Process' "$F")" ;;
    R3)
      # BOTH GONE. The only path on which this driver may say the box is tidy.
      has   "both tracked identities measured GONE" "$F" 'RESIDUE_SUMMARY live=0 gone=2 unreadable=0' 1
      has   "residual_state=CLEAR"                  "$LED" 'residual_state=CLEAR' 1
      has   "CLEANUP=VERIFIED"                      "$LED" 'CLEANUP=VERIFIED' 1
      check "driver exit 0"                         0 "$rc"
      has   "the refused stop's exit is still preserved" "$F" 'RIG_DAEMON_STOP native_exit=1' 1 ;;
    R4)
      # UNREADABLE. Distinct from LIVE in the evidence, and equally refusing.
      has   "the re-query is UNREADABLE"            "$F" 'state=UNREADABLE' 1
      has   "summary counts it as unreadable, not live" "$F" 'RESIDUE_SUMMARY live=0 gone=0 unreadable=2' 1
      has   "residual_state=UNREADABLE"             "$LED" 'residual_state=UNREADABLE' 1
      check "it is NOT reported as CLEAR"           0 "$(grep -c 'residual_state=CLEAR' "$LED")"
      has   "CLEANUP=PENDING"                       "$LED" 'CLEANUP=PENDING' 1
      check "driver exit 6"                         6 "$rc" ;;
    R5)
      # PID REUSE. The pid answers and the identity does not match: OUR process is gone, and a
      # bare pid match would have manufactured residue out of a stranger.
      has   "the reused pid is called GONE, not residue" "$F" 'state=GONE-PID-REUSED' 1
      check "no LIVE residual is claimed"           0 "$(grep -c 'state=LIVE' "$F")"
      has   "residual_state=CLEAR"                  "$LED" 'residual_state=CLEAR' 1
      check "driver exit 0"                         0 "$rc" ;;
'''
i = s.index(anchor)
# insert before the closing of run_case's case statement: find "  esac\n  echo \"=== CASE"
marker = '  esac\n  echo "=== CASE $c tally'
j = s.index(marker)
s = s[:j] + radd + s[j:]

s = s.replace('for c in A B C D E F G H1 H2 I J L; do run_case "$c"; echo; done',
              'for c in A B C D E F G H1 H2 I J L R2 R3 R4 R5; do run_case "$c"; echo; done')
# a focused entry point for the residual arms alone
s = s.replace('''elif [ "$CASE" = K ]; then''',
              '''elif [ "$CASE" = residual ]; then
  for c in J R2 R3 R4 R5; do run_case "$c"; echo; done
  echo "TOTAL pass=$pass fail=$fail"
elif [ "$CASE" = K ]; then''')
open(p, 'w', encoding='utf-8', newline='').write(s)
print('residual arms J/R2/R3/R4/R5 added, with a focused entry point')
