feat(agent): deprecate and completely remove cline agent support

- Delete adapters/cline.py and unregister from registry.py
- Remove cline branches from lib.sh and all 8 skill scripts (create, resume, stop, status, reconcile, update_yaml_resumed, resolve_session_id, orc_onboard)
- Narrow own-key mapping dictionaries across lib_py core modules to 4 supported agents
- Delete cline-exclusive tests and retarget shared fixtures to grok/hermes/claude
- Update skills documentation and installation guides (439 passed, 0 failures)
- Archive cline deprecation consensus and review reports
This commit is contained in:
2026-08-28 22:38:48 +09:00
parent e0c0c107f5
commit f57cd5cdde
40 changed files with 530 additions and 411 deletions
@@ -467,7 +467,7 @@ def _pin_and_verify_resume(s, agent, cwd, uuid, degraded=False):
else:
s['last_visible_status'] = f"resume dry-run failed: {res.stderr.strip() or res.stdout.strip()}"
id_name = 'session' if agent in ('claude', 'cline') else 'conversation'
id_name = 'session' if agent == 'claude' else 'conversation'
if not degraded:
drifts.append({'class': 'C', 'name': s['name'], 'msg': f"{s['name']}: {id_name} id materialized: {uuid}"})
else:
@@ -518,7 +518,7 @@ if herdr_confirmed:
agent = None
role = 'creator'
for r_name in ('creator', 'planner', 'reviewer'):
for a_name in ('claude', 'agy', 'hermes', 'cline', 'grok'):
for a_name in ('claude', 'agy', 'hermes', 'grok'):
if name.endswith(f"-{r_name}-{a_name}"):
role = r_name
agent = a_name
@@ -537,7 +537,7 @@ if herdr_confirmed:
if tok.startswith('MAM_MANAGED='):
managed_path = tok.split('=', 1)[1]
if os.path.realpath(managed_path) == os.path.realpath(workspace_root):
for a_name in ('claude', 'agy', 'hermes', 'cline', 'grok'):
for a_name in ('claude', 'agy', 'hermes', 'grok'):
if a_name in pm_check.get('cmd', '') or a_name in pm_check.get('cmd_full', ''):
agent = a_name
break
@@ -598,9 +598,6 @@ if herdr_confirmed:
elif agent == 'hermes':
entry['child_pid'] = 0
entry['hermes_conversation_id_own'] = None
elif agent == 'cline':
entry['child_pid'] = 0
entry['cline_conversation_id_own'] = None
d.setdefault('herdr_sessions', []).append(entry)
yaml_session_names.add(name)
drifts.append({'class': 'B', 'name': name,
@@ -611,7 +608,7 @@ def row_agent(s):
return agent_of_row(s)
OWN_KEY_BY_AGENT = {
a: _get_own_key(a) for a in ('claude', 'agy', 'hermes', 'cline', 'grok')
a: _get_own_key(a) for a in ('claude', 'agy', 'hermes', 'grok')
}
# === drift C0: 지정된 ID 는 발견이 아니라 '확인'만 필요하다 ===
@@ -782,51 +779,6 @@ for s in d.get('herdr_sessions', []):
else:
_pin_and_verify_resume(s, 'hermes', cwd, uuid, degraded=True)
# === drift C (cline): cline 새 session id materialize (per-row own id) ===
for s in d.get('herdr_sessions', []):
if row_agent(s) != 'cline':
continue
if s.get('status') != 'running':
continue
if s.get('cline_conversation_id_own'):
continue
cwd = (s.get('pane') or {}).get('cwd', '')
if not cwd:
continue
sessions_dir = f"{home}/.cline/data/sessions"
if not os.path.isdir(sessions_dir):
continue
candidates = []
for session_folder in glob.glob(f"{sessions_dir}/*"):
if os.path.isdir(session_folder):
folder_name = os.path.basename(session_folder)
json_file = f"{session_folder}/{folder_name}.json"
if os.path.exists(json_file):
candidates.append(json_file)
candidates.sort(key=os.path.getmtime, reverse=True)
valid_candidates = []
for j in candidates:
uuid = os.path.basename(j)[:-5]
if verify_session_uuid(cwd, 'cline', uuid, s, mode="discover"):
valid_candidates.append(uuid)
if len(valid_candidates) > 1:
drifts.append({'class': 'C-ambiguous', 'name': s['name'],
'msg': f"{s['name']}: {len(valid_candidates)} candidate transcripts newer than session epoch; not pinning"})
s['last_visible_status'] = f"ambiguous: {len(valid_candidates)} candidates"
actions.append(f"ambiguous candidates: {s['name']}")
if len(valid_candidates) == 1:
uuid = valid_candidates[0]
cmd = ['bash', '-c', f'source "{lib_sh}" && verify_tui_viewport "{s["name"]}" "cline" "{cwd}"']
rc = subprocess.run(cmd).returncode
if rc == 0:
_pin_and_verify_resume(s, 'cline', cwd, uuid, degraded=False)
elif rc == 1:
drifts.append({'class': 'C-warn', 'name': s['name'], 'msg': f"{s['name']}: TUI viewport mismatch for candidate {uuid} — not pinned, will retry next cycle"})
else:
_pin_and_verify_resume(s, 'cline', cwd, uuid, degraded=True)
result = {
'timestamp': now_iso,
'yaml_path': yaml_path,