refactor: standardize --agent option usage, improve YAML registry fallback, and fix layout falsy-zero trap (J-1)
- In stop_session.sh and update_yaml_resumed.sh: standardize explicit --agent option and use resolve_agent_type_from_registry to read agent type from YAML/DB state rather than brittle suffix-only regex inference. - Update multi-agent-mux-stop/SKILL.md, multi-agent-mux-resume/SKILL.md, multi-agent-mux-create/SKILL.md, and deploy/INSTALL.md to standardize passing --agent explicitly. - Fix J-1 in layout.py: refactor _env_int(*names, default=None) to take an explicit default parameter, eliminating the falsy-zero trap so MAM_MIN_PANE_COLS=0 is respected. - Add regression and contract tests: test_j1_env_zero_min_cols_matches_flag_zero, test_j1_env_zero_min_rows_matches_flag_zero, test_comp_stop_agent_fallback_*, test_comp_docs_stop_examples_pass_agent. - Verified 100% UNANIMOUS PASS from Planner claude and Reviewers claude and cline.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import json
|
||||
import sqlite3
|
||||
@@ -293,7 +294,7 @@ d['herdr_sessions'] = [{
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
# FEATURE 3: Stop Session (4 Test Cases)
|
||||
# FEATURE 3: Stop Session (7 Test Cases)
|
||||
# ==============================================================================
|
||||
|
||||
def test_comp_stop_sqlite_state_update(mam_sandbox):
|
||||
@@ -411,6 +412,70 @@ d['herdr_sessions'] = [{
|
||||
assert any(("send" in call or "prompt" in call) and "/exit" in call for call in calls)
|
||||
|
||||
|
||||
def test_comp_stop_agent_fallback_reads_pane_cmd(mam_sandbox):
|
||||
"""B-21: --agent 생략 시 세션명에 에이전트 접미사가 없어도 레지스트리 행의
|
||||
pane.cmd 로 해석된다 (라이브 `agy-creator-01` 형태)."""
|
||||
mutation = """
|
||||
d['herdr_sessions'] = [{
|
||||
'name': 'agy-creator-01',
|
||||
'status': 'running',
|
||||
'pane': {'cwd': 'WS_PLACEHOLDER', 'cmd': 'agy'}
|
||||
}]
|
||||
""".replace("WS_PLACEHOLDER", str(mam_sandbox))
|
||||
run_mutation(mam_sandbox, mutation)
|
||||
script = mam_sandbox / ".agents" / "skills" / "multi-agent-mux-stop" / "scripts" / "stop_session.sh"
|
||||
res = subprocess.run(["bash", str(script), "--session", "agy-creator-01"],
|
||||
capture_output=True, text=True)
|
||||
assert res.returncode == 0, res.stderr
|
||||
assert re.search(r"^\s*agent:\s+agy\s*$", res.stdout, re.M), res.stdout
|
||||
|
||||
|
||||
def test_comp_stop_agent_fallback_prefers_explicit_agent_field(mam_sandbox):
|
||||
"""우선순위 계약: 명시 `agent` 필드가 세션명 접미사와 pane.cmd 를 모두 이긴다."""
|
||||
mutation = """
|
||||
d['herdr_sessions'] = [{
|
||||
'name': 'x-creator-claude',
|
||||
'status': 'running',
|
||||
'agent': 'hermes',
|
||||
'pane': {'cwd': 'WS_PLACEHOLDER', 'cmd': 'claude'}
|
||||
}]
|
||||
""".replace("WS_PLACEHOLDER", str(mam_sandbox))
|
||||
run_mutation(mam_sandbox, mutation)
|
||||
script = mam_sandbox / ".agents" / "skills" / "multi-agent-mux-stop" / "scripts" / "stop_session.sh"
|
||||
res = subprocess.run(["bash", str(script), "--session", "x-creator-claude"],
|
||||
capture_output=True, text=True)
|
||||
assert res.returncode == 0, res.stderr
|
||||
assert re.search(r"^\s*agent:\s+hermes\s*$", res.stdout, re.M), res.stdout
|
||||
|
||||
|
||||
# 코드 펜스 안의 stop_session.sh 호출을 '명령 단위'로 잘라낸다.
|
||||
# - 펜스 스코프: 산문 속 `stop_session.sh` 언급을 명령으로 오인하지 않는다
|
||||
# (Pitfalls / When-NOT-to-use 절은 성격상 스크립트를 산문으로 언급한다).
|
||||
# - 명령 단위: 한 펜스에 여러 호출이 들어 있어도 각각을 따로 검증한다
|
||||
# (블록 단위로 보면 그중 하나만 --agent 를 가져도 통과해 버린다).
|
||||
_FENCE_RE = re.compile(r"```(?:bash|sh)\n(.*?)```", re.S)
|
||||
_STOP_CALL_RE = re.compile(r"(?:bash\s+)?\S*stop_session\.sh[^\n\\]*(?:\\\n[^\n\\]*)*")
|
||||
|
||||
|
||||
def test_comp_docs_stop_examples_pass_agent():
|
||||
"""B-21 문서 계약: 문서의 모든 stop_session.sh 예제는 --agent 를 넘긴다.
|
||||
문서 변경은 뮤테이션 감도가 없으므로 이 가드가 표준의 유일한 집행 장치다."""
|
||||
repo = Path(__file__).resolve().parent.parent
|
||||
expected = { # 문서별 최소 예제 수 — 예제를 지워 가드를 무력화하는 것을 막는다
|
||||
repo / ".agents/skills/multi-agent-mux-stop/SKILL.md": 3,
|
||||
repo / "deploy/INSTALL.md": 2,
|
||||
}
|
||||
for doc, floor in expected.items():
|
||||
seen = 0
|
||||
for block in _FENCE_RE.findall(doc.read_text()):
|
||||
for m in _STOP_CALL_RE.finditer(block):
|
||||
snippet = m.group(0)
|
||||
seen += 1
|
||||
assert "--agent" in snippet, \
|
||||
f"{doc.name}: stop_session.sh example without --agent:\n{snippet}"
|
||||
assert seen >= floor, f"{doc.name}: expected >= {floor} examples, saw {seen}"
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
# FEATURE 4: Status Query (5 Test Cases)
|
||||
# ==============================================================================
|
||||
|
||||
Reference in New Issue
Block a user