Clean up all tmux occurrences from dev skills and integrate herdr wrapper translation shim with dynamic env and workspace ID parsing
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
---
|
||||
name: multi-agent-mux-monitor
|
||||
description: "Run a long-lived Kanban worker that polls .mam/agent-sessions.yaml against the actual tmux/agent runtime state and reconciles them. Use when you want live visibility into which agent sessions are running, which are dead, which have stale YAML entries, and which have new session ids that haven't been recorded yet. Designed to be dispatched as a Kanban goal_mode task (--goal) so it keeps running until the user stops it."
|
||||
description: "Run a long-lived Kanban worker that polls .mam/agent-sessions.yaml against the actual herdr/agent runtime state and reconciles them. Use when you want live visibility into which agent sessions are running, which are dead, which have stale YAML entries, and which have new session ids that haven't been recorded yet. Designed to be dispatched as a Kanban goal_mode task (--goal) so it keeps running until the user stops it."
|
||||
version: 1.0.0
|
||||
author: godopu
|
||||
license: MIT
|
||||
platforms: [linux, macos]
|
||||
environments: [kanban, terminal, tmux]
|
||||
environments: [kanban, terminal, herdr]
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [agent, tmux, claude, antigravity, agy, monitor, kanban, observation, reconciliation]
|
||||
tags: [agent, herdr, claude, antigravity, agy, monitor, kanban, observation, reconciliation]
|
||||
related_skills: [multi-agent-mux-create, multi-agent-mux-resume, multi-agent-mux-stop, kanban-orchestrator]
|
||||
prereq_skills: [kanban-worker, multi-agent-mux-create]
|
||||
---
|
||||
@@ -23,16 +23,16 @@ metadata:
|
||||
Dispatch a **Kanban worker** (in `goal_mode`) that:
|
||||
|
||||
1. Every ~30s polls the actual state of:
|
||||
- `tmux ls` (which sessions are alive)
|
||||
- `tmux list-panes -t <session> ...` (pane cmd, cwd, pid)
|
||||
- `herdr ls` (which sessions are alive)
|
||||
- `herdr list-panes -t <session> ...` (pane cmd, cwd, pid)
|
||||
- `~/.claude/projects/<workspace-key>/*.jsonl` mtime + first-line sessionId
|
||||
- `~/.gemini/antigravity-cli/cache/last_conversations.json` (agy workspace → conversation mapping)
|
||||
- `~/.gemini/antigravity-cli/conversations/<uuid>.db` mtime (agy)
|
||||
2. Compares the live state to `agent-sessions.yaml`
|
||||
3. Detects 4 classes of drift:
|
||||
- **yaml-only terminated/archived/stopped**: tmux dead, YAML says `terminated`, `archived`, or `stopped` → OK, left untouched (deliberate end states)
|
||||
- **yaml-only running, tmux dead**: YAML says `running`, tmux is gone → mark `terminated` with timestamp
|
||||
- **tmux-only running, not in YAML**: tmux session exists with `<workspace>-creator-*` naming but YAML doesn't know about it → register as a new entry
|
||||
- **yaml-only terminated/archived/stopped**: herdr dead, YAML says `terminated`, `archived`, or `stopped` → OK, left untouched (deliberate end states)
|
||||
- **yaml-only running, herdr dead**: YAML says `running`, herdr is gone → mark `terminated` with timestamp
|
||||
- **herdr-only running, not in YAML**: herdr session exists with `<workspace>-creator-*` naming but YAML doesn't know about it → register as a new entry
|
||||
- **stale UUID**: YAML has a UUID, but the on-disk artifact is gone → flag in comment
|
||||
4. Writes a Kanban `kanban_comment` on every drift event with diff details
|
||||
5. Heartbeat every 5 minutes
|
||||
@@ -40,14 +40,14 @@ Dispatch a **Kanban worker** (in `goal_mode`) that:
|
||||
|
||||
## When to use
|
||||
|
||||
- You have multiple workspaces with tmux agent sessions and want a single source of truth
|
||||
- You have multiple workspaces with herdr agent sessions and want a single source of truth
|
||||
- You suspect YAML drift after a host reboot / crash
|
||||
- You want a notification when a session id was just created (so you can record it before next restart)
|
||||
- You're running multi-day work and want to know "what's actually running right now"
|
||||
|
||||
## When NOT to use
|
||||
|
||||
- One-off interactive session — just check `tmux ls` and read the YAML
|
||||
- One-off interactive session — just check `herdr ls` and read the YAML
|
||||
- A single, short session — overhead > benefit
|
||||
- You don't have a Kanban dispatcher running
|
||||
|
||||
@@ -69,9 +69,9 @@ hermes kanban create \
|
||||
You are the agent-sessions monitor. Every 30 seconds, do:
|
||||
|
||||
1. Read .mam/agent-sessions.yaml
|
||||
2. Run `tmux ls` and `tmux list-panes -F 'session=#{session_name} pid=#{pane_pid} cmd=#{pane_current_command} cwd=#{pane_current_path}'`
|
||||
3. For each session in the YAML, check the corresponding tmux state
|
||||
4. For each tmux session matching `*-creator-claude` or `*-creator-agy` that's not in the YAML, register it
|
||||
2. Run `herdr ls` and `herdr list-panes -F 'session=#{session_name} pid=#{pane_pid} cmd=#{pane_current_command} cwd=#{pane_current_path}'`
|
||||
3. For each session in the YAML, check the corresponding herdr state
|
||||
4. For each herdr session matching `*-creator-claude` or `*-creator-agy` that's not in the YAML, register it
|
||||
5. For any drift, call `kanban_comment` with the diff
|
||||
6. Sleep 30 seconds, then repeat
|
||||
|
||||
@@ -88,7 +88,7 @@ EOF
|
||||
|
||||
The worker calls this script every 30s. It:
|
||||
|
||||
1. Diffs YAML ↔ tmux ↔ disk artifacts
|
||||
1. Diffs YAML ↔ herdr ↔ disk artifacts
|
||||
2. Updates YAML if needed (only when changes are real, not on every poll — avoids spamming)
|
||||
3. Emits a JSON diff to stdout that the worker turns into a `kanban_comment`
|
||||
|
||||
@@ -115,13 +115,13 @@ Flags: `--once` (single pass), `--emit-diff` (print JSON), `--dry-run` (P1-E —
|
||||
The `status` and `last_visible_status` fields MUST be one of the following exact strings: `running`, `stopped`, `terminated`, `archived`.
|
||||
Any unstructured comments or reasons for the status change should be placed in `last_visible_note` or `termination_mode`.
|
||||
|
||||
### A. tmux dead, YAML says running → auto-terminate
|
||||
### A. herdr dead, YAML says running → auto-terminate
|
||||
|
||||
```
|
||||
YAML: status=running, pane.pid=201132, cmd=claude
|
||||
tmux: no session
|
||||
herdr: no session
|
||||
→ set status=terminated, terminated_at=<now>, termination_mode=auto-detected
|
||||
→ comment: "lab-landing-page-creator-claude: tmux gone (was pane 201132, cmd claude). Marked terminated."
|
||||
→ comment: "lab-landing-page-creator-claude: herdr gone (was pane 201132, cmd claude). Marked terminated."
|
||||
```
|
||||
|
||||
**Skip-set**: the auto-terminate only fires for sessions whose status is `running`.
|
||||
@@ -129,16 +129,16 @@ Rows already in a deliberate end state — `terminated`, `archived`, or **`stopp
|
||||
(set by `multi-agent-mux-stop`) — are
|
||||
left untouched. This is critical: a `stopped` row keeps its `resumable: true` and
|
||||
captured `*_session_id_own`, so the monitor must **not** overwrite it with
|
||||
`terminated ("auto-detected")` when its tmux is (expectedly) gone.
|
||||
`terminated ("auto-detected")` when its herdr is (expectedly) gone.
|
||||
|
||||
### B. tmux alive, not in YAML → auto-register
|
||||
### B. herdr alive, not in YAML → auto-register
|
||||
|
||||
```
|
||||
tmux: session=lab-paper-pdf2md-creator-agy, pid=...,
|
||||
herdr: session=lab-paper-pdf2md-creator-agy, pid=...,
|
||||
cmd=agy, cwd=$WORKSPACE_ROOT/paper-pdf2md
|
||||
YAML: no such session
|
||||
→ register as new entry: status=running, last_visible_status=running, last_visible_note=auto-registered
|
||||
→ comment: "lab-paper-pdf2md-creator-agy: tmux found but not in YAML. Auto-registered."
|
||||
→ comment: "lab-paper-pdf2md-creator-agy: herdr found but not in YAML. Auto-registered."
|
||||
```
|
||||
|
||||
### C. New session id materializes (claude first message sent)
|
||||
@@ -166,7 +166,7 @@ disk: ~/.claude/projects/.../87dc548e-...jsonl: missing
|
||||
- **Don't run the monitor without `--goal`** — without goal mode, a single turn will spawn, do one reconcile, and complete. Goal mode keeps the worker alive across many turns.
|
||||
- **The 30s poll is a default** — workers may override if they detect heavy churn. A workspace with 5+ agent sessions should bump to 60s to avoid noise.
|
||||
- **`kanban_comment` rate limits** — Kanban may throttle if you comment too fast. Coalesce: only comment when the diff is *new* (not the same drift on every poll). The script tracks a state file at `.cache/multi-agent-mux-monitor/<workspace>.state` in the workspace root for this (overridable via `AGENT_SESSIONS_STATE_DIR`).
|
||||
- **Don't fight the user's explicit action** — if `multi-agent-mux-stop` is mid-flight and the monitor sees the same session in two states within 5s, prefer the user's most recent action. The monitor should not auto-revert a fresh `terminated` to `running` because of a stale `tmux has-session` check.
|
||||
- **Don't fight the user's explicit action** — if `multi-agent-mux-stop` is mid-flight and the monitor sees the same session in two states within 5s, prefer the user's most recent action. The monitor should not auto-revert a fresh `terminated` to `running` because of a stale `herdr has-session` check.
|
||||
- **The monitor should never modify the conversation artifacts** (jsonl, db) — only the YAML. If you see a stale UUID, comment about it but don't delete the file.
|
||||
- **TUI capture-pane is expensive** — only capture when you need to update `last_visible_status`, not every poll.
|
||||
|
||||
@@ -194,15 +194,15 @@ If `$HERMES_KANBAN_TASK` card has any comment containing "stop" or "stop monitor
|
||||
|
||||
## Drift responses
|
||||
|
||||
- A. tmux dead + YAML running: auto-terminate YAML, comment
|
||||
- B. tmux alive not in YAML: auto-register, comment
|
||||
- A. herdr dead + YAML running: auto-terminate YAML, comment
|
||||
- B. herdr alive not in YAML: auto-register, comment
|
||||
- C. New session id from *.jsonl: update YAML, comment
|
||||
- D. Stale UUID: comment only, no YAML change
|
||||
|
||||
## Hard rules
|
||||
|
||||
- Do NOT modify conversation artifacts (jsonl, db, brain/)
|
||||
- Do NOT spawn/delete tmux sessions — that's the create/delete skills' job
|
||||
- Do NOT spawn/delete herdr sessions — that's the create/delete skills' job
|
||||
- Do NOT call multi-agent-mux-create or multi-agent-mux-stop — only the user initiates those
|
||||
- Do NOT call `git commit` / `git push`
|
||||
```
|
||||
@@ -217,7 +217,7 @@ When using `--subscribe` with the default PoC public broker
|
||||
event from a third party can terminate your agent session.
|
||||
3. **Mitigation**: Use `--subscribe` only on private TLS-enabled brokers
|
||||
(production mode). For PoC, prefer polling-based monitor (`--once` or
|
||||
no `--subscribe`) which reads YAML/tmux state directly without MQTT.
|
||||
no `--subscribe`) which reads YAML/herdr state directly without MQTT.
|
||||
4. **HMAC verification**: Events are now verified via `verify_hmac()` in
|
||||
`mqtt_common.py` (see FW-05). Ensure `auth_token` is set for each job
|
||||
to enable signature validation — unauthenticated events will be dropped.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
# reconcile.sh — multi-agent-mux-monitor 의 부속 스크립트
|
||||
# YAML ↔ tmux ↔ 디스크 artifact 간 drift 감지 (+ YAML 자동 갱신).
|
||||
# YAML ↔ herdr ↔ 디스크 artifact 간 drift 감지 (+ YAML 자동 갱신).
|
||||
#
|
||||
# Usage:
|
||||
# bash reconcile.sh --once --emit-diff # drift 감지 + 갱신
|
||||
@@ -9,7 +9,7 @@
|
||||
# --dry-run: 부수효과 없는 read-only. "지금 뭐 돌고 있지?" 질문에 안전.
|
||||
# multi-agent-mux-status 스킬이 이걸 재사용.
|
||||
#
|
||||
# 출력 (JSON): {timestamp, yaml_path, tmux_sessions_alive, tmux_confirmed, drifts, actions}
|
||||
# 출력 (JSON): {timestamp, yaml_path, herdr_sessions_alive, herdr_confirmed, drifts, actions}
|
||||
#
|
||||
# Exit codes: 0 = ok | 1 = YAML not found | 2 = error
|
||||
set -euo pipefail
|
||||
@@ -106,7 +106,7 @@ import registry
|
||||
|
||||
# Executed INSIDE lib.sh::atomic_dump_yaml (system python3 + PyYAML), under the
|
||||
# YAML flock with schema-validate + .bak (review item 5). Marks matching running
|
||||
# sessions terminated and kills their tmux (review item 3 behaviour preserved),
|
||||
# sessions terminated and kills their herdr (review item 3 behaviour preserved),
|
||||
# or aborts the write entirely when nothing matches. The untrusted MQTT job id /
|
||||
# event arrive via env (MQTT_JID / MQTT_EVENT) — never spliced into source (P1-B).
|
||||
_MUTATION = r'''
|
||||
@@ -116,10 +116,10 @@ _jid = os.environ['MQTT_JID']
|
||||
_event = os.environ['MQTT_EVENT']
|
||||
_now = datetime.now(timezone.utc)
|
||||
_changed = False
|
||||
for s in d.get('tmux_sessions', []):
|
||||
for s in d.get('herdr_sessions', []):
|
||||
if s.get('delegate_job_id') == _jid and s.get('status') == 'running':
|
||||
_name = s.get('name')
|
||||
_srv = s.get('tmux_server') or 'default'
|
||||
_srv = s.get('herdr_server') or 'default'
|
||||
if _event == 'completed':
|
||||
s['delegate_job_id'] = None
|
||||
print('MQTT Monitor: job completed on ' + str(_name) + ' — session kept alive', flush=True)
|
||||
@@ -129,7 +129,7 @@ for s in d.get('tmux_sessions', []):
|
||||
s['terminated_at'] = _now.strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||
s['terminated_at_epoch'] = int(_now.timestamp())
|
||||
s['termination_mode'] = 'auto-detected (MQTT ' + _event + ')'
|
||||
_cmd = ['tmux'] + (['-L', _srv] if _srv != 'default' else []) + ['kill-session', '-t', _name]
|
||||
_cmd = ['herdr'] + (['-L', _srv] if _srv != 'default' else []) + ['kill-session', '-t', _name]
|
||||
subprocess.run(_cmd, capture_output=True)
|
||||
print('MQTT Monitor: terminated + killed ' + str(_name) + ' on ' + str(_srv) + ' due to MQTT ' + _event, flush=True)
|
||||
_changed = True
|
||||
@@ -328,21 +328,21 @@ except NameError:
|
||||
drifts = []
|
||||
actions = []
|
||||
|
||||
# === 현재 tmux 상태 — transient 실패를 'no sessions' 와 구분 (P1-E) ===
|
||||
tmux_sessions = []
|
||||
tmux_confirmed = True
|
||||
# === 현재 herdr 상태 — transient 실패를 'no sessions' 와 구분 (P1-E) ===
|
||||
herdr_sessions = []
|
||||
herdr_confirmed = True
|
||||
|
||||
# YAML 에 등록된 고유한 tmux_server 목록 수집 + 환경변수 TMUX_SERVER_NAME 포함
|
||||
# YAML 에 등록된 고유한 herdr_server 목록 수집 + 환경변수 HERDR_SERVER_NAME 포함
|
||||
unique_servers = {'default'}
|
||||
if 'TMUX_SERVER_NAME' in os.environ:
|
||||
unique_servers.add(os.environ['TMUX_SERVER_NAME'])
|
||||
for s in d.get('tmux_sessions', []):
|
||||
srv = s.get('tmux_server') or 'default'
|
||||
if 'HERDR_SERVER_NAME' in os.environ:
|
||||
unique_servers.add(os.environ['HERDR_SERVER_NAME'])
|
||||
for s in d.get('herdr_sessions', []):
|
||||
srv = s.get('herdr_server') or 'default'
|
||||
unique_servers.add(srv)
|
||||
|
||||
try:
|
||||
for srv in sorted(unique_servers):
|
||||
cmd = ['tmux']
|
||||
cmd = ['herdr']
|
||||
if srv != 'default':
|
||||
cmd += ['-L', srv]
|
||||
cmd += ['ls', '-F', '#{session_name}|#{session_created}']
|
||||
@@ -352,19 +352,19 @@ try:
|
||||
if not line:
|
||||
continue
|
||||
name, created = line.split('|', 1)
|
||||
tmux_sessions.append({'name': name, 'created': int(created), 'server': srv})
|
||||
herdr_sessions.append({'name': name, 'created': int(created), 'server': srv})
|
||||
else:
|
||||
err = (r.stderr or '').lower()
|
||||
is_empty = ('no server running' in err) or ('no sessions' in err) or ('failed to connect' in err)
|
||||
if not is_empty:
|
||||
tmux_confirmed = False
|
||||
herdr_confirmed = False
|
||||
except Exception:
|
||||
tmux_confirmed = False
|
||||
herdr_confirmed = False
|
||||
|
||||
|
||||
def pane_meta(session, srv):
|
||||
try:
|
||||
cmd = ['tmux']
|
||||
cmd = ['herdr']
|
||||
if srv != 'default':
|
||||
cmd += ['-L', srv]
|
||||
cmd += ['list-panes', '-t', session, '-F',
|
||||
@@ -376,35 +376,35 @@ def pane_meta(session, srv):
|
||||
return None
|
||||
|
||||
|
||||
yaml_sessions = d.get('tmux_sessions', [])
|
||||
yaml_sessions = d.get('herdr_sessions', [])
|
||||
yaml_session_names = {s['name'] for s in yaml_sessions if s.get('name')}
|
||||
alive_set = {(t['name'], t.get('server', 'default')) for t in tmux_sessions}
|
||||
alive_set = {(t['name'], t.get('server', 'default')) for t in herdr_sessions}
|
||||
|
||||
# === drift A: tmux dead + YAML running → auto-terminate ===
|
||||
# tmux 응답을 확정했을 때만. transient 실패 시 모두 terminated 로 마크하지 않음 (P1-E)
|
||||
if tmux_confirmed:
|
||||
# === drift A: herdr dead + YAML running → auto-terminate ===
|
||||
# herdr 응답을 확정했을 때만. transient 실패 시 모두 terminated 로 마크하지 않음 (P1-E)
|
||||
if herdr_confirmed:
|
||||
for s in yaml_sessions:
|
||||
name = s.get('name')
|
||||
if not name:
|
||||
continue
|
||||
# 'stopped' 도 deliberate한 종료 상태 — drift 로 보지 않고 그대로 둔다.
|
||||
# (없으면 tmux-dead stopped 세션을 'terminated' 로 덮어써 resumable 플래그가 소실됨)
|
||||
# (없으면 herdr-dead stopped 세션을 'terminated' 로 덮어써 resumable 플래그가 소실됨)
|
||||
if s.get('status') in ('terminated', 'archived', 'stopped'):
|
||||
continue
|
||||
srv = s.get('tmux_server') or 'default'
|
||||
srv = s.get('herdr_server') or 'default'
|
||||
if (name, srv) not in alive_set:
|
||||
s['status'] = 'terminated'
|
||||
s['terminated_at'] = now_iso
|
||||
s['terminated_at_epoch'] = int(datetime.now(timezone.utc).timestamp())
|
||||
s['termination_mode'] = 'auto-detected (tmux gone)'
|
||||
s['termination_mode'] = 'auto-detected (herdr gone)'
|
||||
pane = s.get('pane') or {}
|
||||
drifts.append({'class': 'A', 'name': name,
|
||||
'msg': f"{name}: tmux gone (was pane {pane.get('pid')}, cmd {pane.get('cmd')}). Marked terminated."})
|
||||
'msg': f"{name}: herdr gone (was pane {pane.get('pid')}, cmd {pane.get('cmd')}). Marked terminated."})
|
||||
actions.append(f"terminated: {name}")
|
||||
|
||||
# === drift B: tmux alive + not in YAML → auto-register ===
|
||||
if tmux_confirmed:
|
||||
for t in tmux_sessions:
|
||||
# === drift B: herdr alive + not in YAML → auto-register ===
|
||||
if herdr_confirmed:
|
||||
for t in herdr_sessions:
|
||||
name = t['name']
|
||||
if name in yaml_session_names:
|
||||
continue
|
||||
@@ -434,14 +434,14 @@ if tmux_confirmed:
|
||||
entry = {
|
||||
'name': name,
|
||||
'status': 'running',
|
||||
'tmux_session_created_at': datetime.fromtimestamp(t['created'], tz=timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ'),
|
||||
'tmux_session_epoch': t['created'],
|
||||
'tmux_server': srv,
|
||||
'herdr_session_created_at': datetime.fromtimestamp(t['created'], tz=timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ'),
|
||||
'herdr_session_epoch': t['created'],
|
||||
'herdr_server': srv,
|
||||
'pane': {'index': 0, 'pid': pm['pid'], 'cmd': agent, 'cmd_full': cmd_full, 'cwd': pm['cwd']},
|
||||
# P2: cwd 인용
|
||||
'start_command': f'tmux {server_opt}new-session -d -s "{name}" -x 140 -y 40 -c "{pm["cwd"]}" "{cmd_full}"',
|
||||
'attach_command': f'tmux {server_opt}attach -t {name}',
|
||||
'kill_command': f'tmux {server_opt}kill-session -t {name}',
|
||||
'start_command': f'herdr {server_opt}new-session -d -s "{name}" -x 140 -y 40 -c "{pm["cwd"]}" "{cmd_full}"',
|
||||
'attach_command': f'herdr {server_opt}attach -t {name}',
|
||||
'kill_command': f'herdr {server_opt}kill-session -t {name}',
|
||||
'last_visible_status': 'running',
|
||||
'last_visible_note': 'auto-registered by monitor',
|
||||
}
|
||||
@@ -465,14 +465,14 @@ if tmux_confirmed:
|
||||
elif agent == 'cline':
|
||||
entry['child_pid'] = 0
|
||||
entry['cline_conversation_id_own'] = None
|
||||
d.setdefault('tmux_sessions', []).append(entry)
|
||||
d.setdefault('herdr_sessions', []).append(entry)
|
||||
yaml_session_names.add(name)
|
||||
drifts.append({'class': 'B', 'name': name,
|
||||
'msg': f"{name}: tmux found but not in YAML. Auto-registered (pane {pm['pid']}, cmd {pm['cmd']}, cwd {pm['cwd']})."})
|
||||
'msg': f"{name}: herdr found but not in YAML. Auto-registered (pane {pm['pid']}, cmd {pm['cmd']}, cwd {pm['cwd']})."})
|
||||
actions.append(f"registered: {name}")
|
||||
|
||||
# === drift C: claude 새 session id materialize (per-row own id) ===
|
||||
for s in d.get('tmux_sessions', []):
|
||||
for s in d.get('herdr_sessions', []):
|
||||
if not s.get('name', '').endswith('-creator-claude'):
|
||||
continue
|
||||
if s.get('status') != 'running':
|
||||
@@ -507,7 +507,7 @@ for s in d.get('tmux_sessions', []):
|
||||
actions.append(f"updated session id: {sid}")
|
||||
|
||||
# === drift C (agy): agy 새 session id materialize (per-row own id) ===
|
||||
for s in d.get('tmux_sessions', []):
|
||||
for s in d.get('herdr_sessions', []):
|
||||
if not s.get('name', '').endswith('-creator-agy'):
|
||||
continue
|
||||
if s.get('status') != 'running':
|
||||
@@ -531,7 +531,7 @@ for s in d.get('tmux_sessions', []):
|
||||
pass
|
||||
|
||||
# === drift C (hermes): hermes 새 session id materialize (per-row own id) ===
|
||||
for s in d.get('tmux_sessions', []):
|
||||
for s in d.get('herdr_sessions', []):
|
||||
if not s.get('name', '').endswith('-creator-hermes'):
|
||||
continue
|
||||
if s.get('status') != 'running':
|
||||
@@ -556,7 +556,7 @@ for s in d.get('tmux_sessions', []):
|
||||
pass
|
||||
|
||||
# === drift C (cline): cline 새 session id materialize (per-row own id) ===
|
||||
for s in d.get('tmux_sessions', []):
|
||||
for s in d.get('herdr_sessions', []):
|
||||
if not s.get('name', '').endswith('-creator-cline'):
|
||||
continue
|
||||
if s.get('status') != 'running':
|
||||
@@ -630,8 +630,8 @@ if cn.get('session_id'):
|
||||
result = {
|
||||
'timestamp': now_iso,
|
||||
'yaml_path': yaml_path,
|
||||
'tmux_sessions_alive': sorted(f"{t['name']}|{t.get('server', 'default')}" for t in tmux_sessions),
|
||||
'tmux_confirmed': tmux_confirmed,
|
||||
'herdr_sessions_alive': sorted(f"{t['name']}|{t.get('server', 'default')}" for t in herdr_sessions),
|
||||
'herdr_confirmed': herdr_confirmed,
|
||||
'drifts': drifts,
|
||||
'actions': actions,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user