feat(create/monitor): implement automatic UUID materialization, auto-pinning, and drift-C2 resolution (13/13 PASS)
This commit is contained in:
+123
-33
@@ -796,6 +796,52 @@ derive_workspace_slug() {
|
||||
printf 'mam-%s' "$slug"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# mam_gen_uuid
|
||||
# ---------------------------------------------------------------------------
|
||||
mam_gen_uuid() {
|
||||
if command -v uuidgen >/dev/null 2>&1; then
|
||||
uuidgen | tr 'A-Z' 'a-z'
|
||||
else
|
||||
python3 -c 'import uuid; print(uuid.uuid4())'
|
||||
fi
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# mam_abs_workspace <path>
|
||||
# ---------------------------------------------------------------------------
|
||||
mam_abs_workspace() {
|
||||
local p="${1:-}"
|
||||
( cd -P "$p" 2>/dev/null && pwd -P ) || printf '%s' "$p"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# mam_workspace_key <workspace>
|
||||
# ---------------------------------------------------------------------------
|
||||
mam_workspace_key() {
|
||||
printf '%s' "$(mam_abs_workspace "$1")" | tr '/_' '--'
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# mam_session_iso_root <session_name>
|
||||
# ---------------------------------------------------------------------------
|
||||
mam_session_iso_root() {
|
||||
MAM_STATE_JSON="$(load_state_json)" MAM_ISO_SESSION="$1" env_python "$AGENT_SESSIONS_YAML" <<'PYEOF'
|
||||
import json, os
|
||||
name = os.environ.get('MAM_ISO_SESSION', '')
|
||||
try:
|
||||
d = json.loads(os.environ.get('MAM_STATE_JSON', '{}'))
|
||||
except Exception:
|
||||
d = {}
|
||||
for s in (d.get('herdr_sessions') or []):
|
||||
if s.get('name') == name:
|
||||
iso = s.get('isolation')
|
||||
if isinstance(iso, dict) and iso.get('root'):
|
||||
print(iso['root'])
|
||||
break
|
||||
PYEOF
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# derive_session_name <workspace> <agent>
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -1126,13 +1172,21 @@ PYEOF
|
||||
# ---------------------------------------------------------------------------
|
||||
VERIFY_SESSION_PYTHON='
|
||||
def workspace_key(path):
|
||||
return path.replace("/", "-").replace("_", "-")
|
||||
import os
|
||||
try:
|
||||
p = os.path.realpath(path)
|
||||
except Exception:
|
||||
p = path
|
||||
return p.replace("/", "-").replace("_", "-")
|
||||
|
||||
def verify_session_uuid(ws, agent, uuid, row=None, home_dir=None, claude_dir=None, mode="discover"):
|
||||
import os, json, sqlite3
|
||||
home = home_dir or os.environ.get("HOME_DIR", "")
|
||||
c_dir = claude_dir or os.environ.get("CLAUDE_PROJECT_DIR", f"{home}/.claude/projects")
|
||||
row = row or {}
|
||||
_iso = row.get("isolation")
|
||||
iso_root = _iso.get("root") if isinstance(_iso, dict) and _iso.get("root") else None
|
||||
|
||||
# The floor answers "could this transcript belong to a PREVIOUS incarnation
|
||||
# of this session?", which only matters while picking an unknown uuid off
|
||||
# disk. In "revalidate" the uuid is one this row already recorded, and a
|
||||
@@ -1142,11 +1196,20 @@ def verify_session_uuid(ws, agent, uuid, row=None, home_dir=None, claude_dir=Non
|
||||
epoch = row.get("herdr_session_epoch", 0) if mode == "discover" else 0
|
||||
cwd = row.get("pane", {}).get("cwd", "") or ws
|
||||
|
||||
# ORDERING INVARIANT: the workspace check below MUST run before the
|
||||
# assigned-id shortcut. Moving the shortcut above it would return True for a
|
||||
# row belonging to a different workspace purely because it is assigned and
|
||||
# unverified, breaking the one guarantee find_workspace_uuid exists to give
|
||||
# -- never hand back an id that belongs to a different workspace. (T-12)
|
||||
if workspace_key(cwd) != workspace_key(ws):
|
||||
return False
|
||||
|
||||
|
||||
if (mode == "revalidate" and row.get("session_id_source") == "assigned"
|
||||
and not row.get("session_id_verified")):
|
||||
return True
|
||||
|
||||
if agent == "claude":
|
||||
base = c_dir
|
||||
base = (iso_root + "/projects") if iso_root else c_dir
|
||||
key = workspace_key(ws)
|
||||
path = f"{base}/{key}/{uuid}.jsonl"
|
||||
if not os.path.exists(path):
|
||||
@@ -1154,27 +1217,41 @@ def verify_session_uuid(ws, agent, uuid, row=None, home_dir=None, claude_dir=Non
|
||||
if epoch and os.path.getmtime(path) < epoch:
|
||||
return False
|
||||
try:
|
||||
valid_session = False
|
||||
found_cwd = None
|
||||
with open(path) as f:
|
||||
first = f.readline().strip()
|
||||
if not first:
|
||||
for _ in range(50):
|
||||
line = f.readline()
|
||||
if not line:
|
||||
break
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
try:
|
||||
payload = json.loads(line)
|
||||
if payload.get("sessionId") == uuid:
|
||||
valid_session = True
|
||||
if payload.get("cwd"):
|
||||
found_cwd = payload.get("cwd")
|
||||
break
|
||||
except Exception:
|
||||
pass
|
||||
if not valid_session:
|
||||
return False
|
||||
payload = json.loads(first)
|
||||
if payload.get("sessionId") != uuid:
|
||||
return False
|
||||
if payload.get("cwd") and payload.get("cwd") != cwd:
|
||||
if found_cwd and found_cwd != cwd:
|
||||
return False
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
elif agent == "agy":
|
||||
base = f"{home}/.gemini/antigravity-cli/conversations"
|
||||
base = f"{iso_root or home}/.gemini/antigravity-cli/conversations"
|
||||
path = f"{base}/{uuid}.db"
|
||||
if not os.path.exists(path):
|
||||
return False
|
||||
if epoch and os.path.getmtime(path) < epoch:
|
||||
return False
|
||||
if mode == "discover":
|
||||
lc = f"{home}/.gemini/antigravity-cli/cache/last_conversations.json"
|
||||
lc = f"{iso_root or home}/.gemini/antigravity-cli/cache/last_conversations.json"
|
||||
cache_match = False
|
||||
if os.path.exists(lc):
|
||||
try:
|
||||
@@ -1196,7 +1273,7 @@ def verify_session_uuid(ws, agent, uuid, row=None, home_dir=None, claude_dir=Non
|
||||
return False
|
||||
|
||||
elif agent == "hermes":
|
||||
hdb = f"{home}/.hermes/state.db"
|
||||
hdb = f"{iso_root or home}/.hermes/state.db"
|
||||
if not os.path.exists(hdb):
|
||||
return False
|
||||
if epoch and os.path.getmtime(hdb) < epoch:
|
||||
@@ -1211,7 +1288,7 @@ def verify_session_uuid(ws, agent, uuid, row=None, home_dir=None, claude_dir=Non
|
||||
return False
|
||||
|
||||
elif agent == "cline":
|
||||
base = f"{home}/.cline/data/sessions"
|
||||
base = (iso_root + "/sessions") if iso_root else f"{home}/.cline/data/sessions"
|
||||
path = f"{base}/{uuid}/{uuid}.json"
|
||||
if not os.path.exists(path):
|
||||
return False
|
||||
@@ -1260,7 +1337,7 @@ PYEOF
|
||||
# 2 = check not possible (capture failed, session gone)
|
||||
verify_tui_viewport() {
|
||||
local session_name="$1" agent="$2" workspace="$3"
|
||||
local abs; abs="$(cd "$workspace" 2>/dev/null && pwd)" || abs="$workspace"
|
||||
local abs; abs="$(mam_abs_workspace "$workspace")"
|
||||
local base; base="$(basename "$abs")"
|
||||
|
||||
if ! _herdr has-session -t "$session_name" >/dev/null 2>&1; then
|
||||
@@ -1273,23 +1350,16 @@ verify_tui_viewport() {
|
||||
return 2
|
||||
fi
|
||||
|
||||
case "$agent" in
|
||||
claude)
|
||||
if printf '%s\n' "$pane_content" | grep -q "$base"; then
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
;;
|
||||
agy|hermes|cline)
|
||||
if printf '%s\n' "$pane_content" | grep -q "$base"; then
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
;;
|
||||
*)
|
||||
return 2
|
||||
;;
|
||||
esac
|
||||
local flat base_flat
|
||||
flat=$(printf '%s' "$pane_content" | tr -d '[:space:]')
|
||||
base_flat=$(printf '%s' "$base" | tr -d '[:space:]')
|
||||
if printf '%s' "$flat" | grep -Fq "$base_flat"; then
|
||||
return 0
|
||||
fi
|
||||
if printf '%s\n' "$pane_content" | grep -Eq '(^|[^[:alnum:]])/[A-Za-z0-9._-]+/[A-Za-z0-9._/-]+'; then
|
||||
return 1
|
||||
fi
|
||||
return 2
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -1308,7 +1378,7 @@ verify_tui_viewport() {
|
||||
# ---------------------------------------------------------------------------
|
||||
find_workspace_uuid() {
|
||||
local workspace="$1" agent="$2" session_name="${3:-}"
|
||||
local abs; abs="$(cd "$workspace" 2>/dev/null && pwd)" || abs="$workspace"
|
||||
local abs; abs="$(mam_abs_workspace "$workspace")"
|
||||
MAM_STATE_JSON="$(load_state_json)" WS_ABS="$abs" AGENT="$agent" TARGET_SESSION="$session_name" MAM_VERIFY_PY="$VERIFY_SESSION_PYTHON" env_python "$AGENT_SESSIONS_YAML" <<'PYEOF'
|
||||
import os, sys, json, glob, sqlite3
|
||||
|
||||
@@ -1791,7 +1861,27 @@ _sks_herdr() {
|
||||
mam_herdr "$@"
|
||||
}
|
||||
|
||||
_pane_capture() { _sks_herdr capture-pane -p -t "$1" 2>/dev/null || echo ""; }
|
||||
_pane_capture() {
|
||||
local raw
|
||||
raw="$(_sks_herdr capture-pane -p -t "$1" 2>/dev/null || echo "")"
|
||||
if [ -z "$raw" ]; then
|
||||
echo ""
|
||||
return 0
|
||||
fi
|
||||
python3 -c '
|
||||
import sys, json
|
||||
raw = sys.stdin.read()
|
||||
try:
|
||||
data = json.loads(raw)
|
||||
text = data.get("result", {}).get("read", {}).get("text")
|
||||
if text is not None:
|
||||
print(text, end="")
|
||||
else:
|
||||
print(raw, end="")
|
||||
except Exception:
|
||||
print(raw, end="")
|
||||
' <<< "$raw"
|
||||
}
|
||||
|
||||
# Bottom-N *content* lines: capture-pane -p pads the viewport with trailing
|
||||
# blank rows; window on non-blank lines or top-anchored dialogs are invisible.
|
||||
|
||||
Reference in New Issue
Block a user