refactor(skills): cleanup dead code + full workflow A→B→C→D integration

Cleanup:
- Remove unused validate_yaml() helper from lib.sh
- Remove USER_MANUAL.html + mqtt-broker-setup.html (no refs found)

Workflow A (create_session ↔ delegate-job):
- Add --submit-job <prompt> option to create_session.sh
- Auto-register session in delegate-job registry, store delegate_job_id in YAML

Workflow B (push-based monitor):
- Migrate reconcile.sh to MQTT subscriber mode (polling fallback preserved)

Workflow C (unified status):
- status.sh now shows session + delegate-job state in single column

Workflow D (audit log + perms):
- JSON job files chmod 600
- create/delete/resume now publish lifecycle events to delegate-job
This commit is contained in:
2026-06-19 14:27:29 +00:00
parent 97f649a3e1
commit 0eb1d94a9c
15 changed files with 335 additions and 3688 deletions
+45 -6
View File
@@ -60,11 +60,49 @@ def resume_on_disk(s):
return '?'
def get_job_status(s):
jid = s.get('delegate_job_id')
if not jid:
return ('-', '-')
# Try workspace relative
path = os.path.join('.hermes', 'jobs', f"{jid}.json")
if os.path.exists(path):
try:
with open(path) as jf:
job_data = json.load(jf)
return (jid, job_data.get('status', 'unknown'))
except Exception:
pass
# Try fixed absolute path of registry
path_fixed = os.path.join('/home/godopu16/PuKi/laa/canary_projects/advanced_multi_agent', '.hermes', 'jobs', f"{jid}.json")
if os.path.exists(path_fixed):
try:
with open(path_fixed) as jf:
job_data = json.load(jf)
return (jid, job_data.get('status', 'unknown'))
except Exception:
pass
# Try audit log status.json
path_audit = os.path.join('/home/godopu16/PuKi/laa/canary_projects/advanced_multi_agent', '.hermes', 'delegate_job_logs', jid, 'status.json')
if os.path.exists(path_audit):
try:
with open(path_audit) as jf:
job_data = json.load(jf)
return (jid, job_data.get('status', 'unknown'))
except Exception:
pass
return (jid, 'unknown')
sessions = d.get('tmux_sessions', [])
print(f"agent-sessions status — {drift['timestamp']} (tmux_confirmed={drift['tmux_confirmed']})")
print("=" * 116)
print(f"{'NAME':<44} {'SERVER':<12} {'YAML':<10} {'TMUX':<6} {'CMD':<6} {'RESUME':<8} DRIFT")
print("-" * 116)
print("=" * 136)
print(f"{'NAME':<44} {'SERVER':<12} {'YAML':<10} {'TMUX':<6} {'CMD':<6} {'RESUME':<8} {'JOB_ID':<10} {'JOB_STATUS':<12} DRIFT")
print("-" * 136)
if not sessions:
print("(no sessions registered)")
for s in sessions:
@@ -74,15 +112,16 @@ for s in sessions:
tmux = 'alive' if f"{name}|{server}" in alive else 'dead'
cmd = (s.get('pane') or {}).get('cmd', '?')
res = resume_on_disk(s)
jid, jstatus = get_job_status(s)
drs = ','.join(drift_by_name.get(name, [])) or '-'
print(f"{name:<44} {server:<12} {status:<10} {tmux:<6} {cmd:<6} {res:<8} {drs}")
print(f"{name:<44} {server:<12} {status:<10} {tmux:<6} {cmd:<6} {res:<8} {jid:<10} {jstatus:<12} {drs}")
# drifts not tied to a registered row (e.g. class B unregistered, class D cache)
known = {s.get('name') for s in sessions}
extra = [dr for dr in drift.get('drifts', []) if dr['name'] not in known]
if extra:
print("-" * 116)
print("-" * 136)
for dr in extra:
print(f" [{dr['class']}] {dr['msg']}")
print("=" * 116)
print("=" * 136)
print(f"alive tmux: {sorted(alive)}")
PYEOF