Skip to content

Commit ba0a7e4

Browse files
feat: require exact Claude residency resume
agent-identity: mbp2025.direct.omp.bn5hrz39 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.1.7 agent-runtime: OMP 18.1.7 tooling-profile: dotfiles@4816a7a
1 parent bad93d3 commit ba0a7e4

6 files changed

Lines changed: 1220 additions & 25 deletions

File tree

docs/vrs/spec.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,29 @@ native session, and becomes active. A mismatch, unsupported driver capability,
681681
indeterminate presence, malformed ledger, or foreign ownership becomes a
682682
fail-closed refusal. No path substitutes a fresh session.
683683

684+
For Claude, the provider binding owns the exact native UUID, wrapper incarnation,
685+
canonical workspace, transcript path, and optional resume generation. Checkpointing
686+
first resolves the UUID to exactly one file in the active managed Claude
687+
transcript store, rejects a matching Codex transcript, opens the file with
688+
`O_NOFOLLOW`, requires a regular `<uuid>.jsonl` file, validates every recorded
689+
`sessionId`, derives one rooted workspace lineage, and stores the SHA-256 of
690+
the exact bytes. Resume revalidates that lineage and digest before any provider
691+
child starts, rejects authored
692+
session selectors, and lowers to `claude <options> --resume <uuid> -- <prompt>`.
693+
Ordinary launches also use the option terminator and explicitly remove inherited
694+
residency fence variables.
695+
696+
The synchronous `SessionStart` observer is Claude's native identity proof.
697+
Ordinary observation remains fail-open. During mandatory resume, observer setup,
698+
payload validation, transcript validation, and durable candidate publication
699+
propagate failure. The hook stores the candidate under the new wrapper
700+
incarnation and resume generation without replacing the checkpoint binding.
701+
After complete-group presence establishes the current wrapper incarnation,
702+
exact native-session verification promotes only that incarnation's candidate.
703+
A failed start therefore leaves the checkpoint
704+
retryable. A later explicit in-process session switch becomes the next
705+
authoritative binding and does not inherit the consumed resume fence.
706+
684707
`st2 tasks --json` uses schema `st2.task-inventory.v3`. Each task row appends
685708
`residencyPolicy` and nullable `runtimeResidency` beside the existing process
686709
`runtime` observation. A missing ledger is `null`, never inferred as active or

hooks/claude-observe.sh

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/env bash
22
# st2 Claude observe hook: forward one hook event (name in $1, payload on stdin) to the agent's
3-
# observed-harness-state record. Fail-open; observation must never wedge or slow the harness.
3+
# observed-harness-state record. Ordinary observation fails open. A residency SessionStart
4+
# propagates failure because its native-session binding is launch authority, not telemetry.
45

56
set -u
67

@@ -11,11 +12,21 @@ identity="${ST_AGENT:-}"
1112
# with a custom bus root (ST_ROOT != CATALOG) declaration resolution under ST_ROOT finds nothing
1213
# and every transition would silently drop.
1314
root="${CATALOG:-${ST_ROOT:-}}"
15+
mandatory_binding=""
16+
if [[ "$event" == "SessionStart" ]]; then
17+
mandatory_binding="${ST2_CLAUDE_RESUME_GENERATION:-}${ST2_CLAUDE_EXPECTED_NATIVE_SESSION:-}"
18+
fi
1419
runtime_id="${ST2_CLAUDE_RUNTIME_ID:-$identity}"
1520
if [[ -z "$event" || -z "$identity" || -z "$root" ]] || ! command -v st2 >/dev/null 2>&1; then
21+
[[ -n "$mandatory_binding" ]] && exit 1
1622
exit 0
1723
fi
1824

25+
if [[ -n "$mandatory_binding" ]]; then
26+
exec st2 --catalog "$root" driver claude-observe --identity "$identity" --runtime-id "$runtime_id" \
27+
--event "$event" >/dev/null 2>&1
28+
fi
29+
1930
st2 --catalog "$root" driver claude-observe --identity "$identity" --runtime-id "$runtime_id" \
2031
--event "$event" >/dev/null 2>&1 || true
2132
exit 0

0 commit comments

Comments
 (0)