17 KiB
Cross-Code Review Report — Job 7e474214
- Reviewer: cline (session: herdr:canary-projects-multi-agent-mux-creator-cline)
- Job ID: 7e474214
- Scope: Cross-code review of the changeset introducing
--herdr-workspaceacross MAM and decoupling legacy fallback chains (14 files, +531/−47 lines). - Date: 2026-08-24
§0. Executive Summary
The changeset introduces a --herdr-workspace CLI option across create/resume/stop scripts, decouples resolve_herdr_session() (socket/daemon name) from resolve_herdr_workspace() (workspace label), removes herdr_workspace from all 6 socket-lookup fallback chains, adds distinct SOCKET/WORKSPACE columns to status.sh, populates herdr_workspace/herdr_server in reconcile drift B auto-registration, and adds 27 new tests (20 unit + 7 component).
Verdict: PASS. All 8 changed shell scripts pass bash -n. All 55 unit tests and all 7 changeset-specific component tests pass. The static guard test confirms no socket lookup falls back to herdr_workspace. One low-severity dead-code observation in reconcile.sh:511 is noted (N-1) but does not block.
§1. Files Reviewed
| # | File | Change Type | bash -n |
|---|---|---|---|
| 1 | .agents/skills/lib.sh |
Core decoupling: resolve_herdr_session / resolve_herdr_workspace split |
✅ PASS |
| 2 | .agents/skills/multi-agent-mux-create/scripts/create_session.sh |
--herdr-workspace parsing, env fallback, YAML serialization |
✅ PASS |
| 3 | .agents/skills/multi-agent-mux-resume/scripts/resume_session.sh |
--herdr-workspace forwarding (both call sites) |
✅ PASS |
| 4 | .agents/skills/multi-agent-mux-resume/scripts/update_yaml_resumed.sh |
--herdr-workspace parsing, conditional overwrite |
✅ PASS |
| 5 | .agents/skills/multi-agent-mux-stop/scripts/stop_session.sh |
--herdr-workspace in usage/parser (CLI symmetry, no-op) |
✅ PASS |
| 6 | .agents/skills/multi-agent-mux-status/scripts/status.sh |
SOCKET/WORKSPACE columns, herdr_workspace in JSON+table |
✅ PASS |
| 7 | .agents/skills/multi-agent-mux-monitor/scripts/reconcile.sh |
Socket lookup decoupling (3 sites), drift B populates ws+server | ✅ PASS |
| 8 | .agents/skills/multi-agent-mux-delegate-job/multi-agent-mux-delegate-job |
resolve_herdr_workspace → resolve_herdr_session rename |
✅ PASS |
| 9 | .agents/skills/multi-agent-mux-create/SKILL.md |
--herdr-workspace documentation |
N/A |
| 10 | .agents/skills/multi-agent-mux-resume/SKILL.md |
resolve_herdr_session rename in docs |
N/A |
| 11 | .agents/skills/multi-agent-mux-stop/SKILL.md |
--herdr-workspace note (no socket effect) |
N/A |
| 12 | tests/conftest.py |
setdefault("calls", []) defensive fix in mock_herdr |
N/A |
| 13 | tests/test_tier1_unit.py |
+92 lines: decoupling, slug parity, static guard tests | N/A |
§2. Legacy Fallback Chain Decoupling (Task Goal 1)
§2.1 Socket Lookup Sites — All 6 Decoupled
The brief required that herdr_session/socket lookup ONLY uses s.get('herdr_session') or s.get('herdr_server') — never herdr_workspace. Verified:
| # | Location | Old Expression | New Expression | Status |
|---|---|---|---|---|
| 1 | lib.sh:1027 (resolve_herdr_session) |
herdr_session or herdr_server or herdr_workspace |
herdr_session or herdr_server |
✅ |
| 2 | reconcile.sh:135 (_srv, MQTT monitor) |
+ or herdr_workspace or 'default' |
herdr_session or herdr_server or 'default' |
✅ |
| 3 | reconcile.sh:399 (unique_servers) |
+ or herdr_workspace or 'default' |
herdr_session or herdr_server or 'default' |
✅ |
| 4 | reconcile.sh:495 (drift A) |
+ or herdr_workspace or 'default' |
herdr_session or herdr_server or 'default' |
✅ |
| 5 | status.sh:145 (JSON) |
+ or herdr_workspace or 'default' |
herdr_session or herdr_server or 'default' |
✅ |
| 6 | status.sh:270 (table) |
+ or herdr_workspace or 'default' |
herdr_session or herdr_server or 'default' |
✅ |
Static guard test (test_no_socket_lookup_falls_back_to_workspace_label): PASS. The test regex-scans lib.sh, reconcile.sh, and status.sh for any line matching herdr_session') or ... herdr_workspace and asserts none exist.
§2.2 resolve_herdr_session vs resolve_herdr_workspace Decoupling
resolve_herdr_session(name, [workspace])— Returns the socket/daemon name. Priority: ① rowherdr_session→ ② rowherdr_server→ ③ envHERDR_SESSION_NAME/HERDR_SERVER_NAME→ ④ workspace slug fallback. Never falls back toherdr_workspace. ✅resolve_herdr_workspace(name, [workspace])— Returns the workspace label. Priority: ① rowherdr_workspace→ ② rowpane.cwdslug → ③ caller workspace arg slug → ④ empty string. Never falls back toherdr_session/herdr_server(D4). ✅
Caller audit — Scripts that need the socket name now call resolve_herdr_session:
create_session.sh:227— ✅ (renamed fromresolve_herdr_workspace)stop_session.sh:113— ✅ (renamed fromresolve_herdr_workspace)multi-agent-mux-delegate-job:466— ✅ (renamed fromresolve_herdr_workspace)resume_session.sh:62— ✅ (renamed fromresolve_herdr_workspace)
resolve_herdr_workspace is now ONLY called by:
update_yaml_resumed.sh:57— Correct: deriving the workspace label (not socket). ✅create_session.sh:147— Comment only; explicitly does NOT call it (D5). ✅
Decoupling tests: test_resolvers_are_decoupled, test_workspace_label_never_resolves_as_socket, test_socket_resolver_fallback_chain — all PASS. ✅
§2.3 D5 — Create Does Not Inherit Stale Labels
create_session.sh correctly does NOT use resolve_herdr_workspace to derive MAM_WS_LABEL. Instead it uses:
MAM_WS_LABEL="${HERDR_WORKSPACE_OPT:-${HERDR_WORKSPACE:-${ws_slug#mam-}}}"
This derives the label afresh from the flag → env → workspace slug, avoiding inheritance of a stale pane.cwd-derived label from a terminated same-name row. Test test_create_does_not_inherit_a_stale_workspace_label confirms: recreating over a terminated row with herdr_workspace: old-stale-label produces a fresh label, not the stale one. ✅
§3. CLI Option Standardization & YAML Metadata (Task Goal 2)
§3.1 create_session.sh
- Usage:
--herdr-workspace NAMEdocumented with clear semantics ("A label only — it never selects a herdr socket"). ✅ - Parser:
--herdr-workspace) HERDR_WORKSPACE_OPT="$2"; shift 2 ;;✅ - Env fallback (C-3):
MAM_WS_LABEL="${HERDR_WORKSPACE_OPT:-${HERDR_WORKSPACE:-${ws_slug#mam-}}}"— flag > env > default slug. Symmetric withHERDR_SESSION_NAME. ✅ - Dry-run output:
herdr_workspace=${MAM_WS_LABEL}included. ✅ - YAML serialization:
herdr_workspaceserialized as distinct field (line 327). Label does NOT leak intostart_command/attach_command/kill_command(test verifies). ✅ - Guard sites (from prior review 40944efc):
HERDR_SESSION_NAMEguard at lines 150-154 and 227-229 still protect explicit values from clobbering.MAM_WS_LABELis independent and does not interfere. ✅
Tests: test_comp_create_herdr_workspace_parsing_and_env_fallback (T4), test_comp_create_herdr_workspace_yaml_propagation (T5) — PASS. ✅
§3.2 resume_session.sh & update_yaml_resumed.sh
- resume_session.sh:
--herdr-workspaceparsed intoHERDR_WORKSPACE_OPT. Both call sites (already-running line 77, post-spawn line 142) forward via${HERDR_WORKSPACE_OPT:+--herdr-workspace "$HERDR_WORKSPACE_OPT"}. The:+expansion correctly omits the flag when the opt is empty. ✅ - update_yaml_resumed.sh:
--herdr-workspaceparsed. When explicit,MAM_WS_LABEL_EXPLICIT=1; when resolved viaresolve_herdr_workspace,MAM_WS_LABEL_EXPLICIT=0. Conditional overwrite logic:if wsl and (ws_explicit or not target.get('herdr_workspace')): target['herdr_workspace'] = wsl- Explicit flag → force overwrite (user intent). ✅
- Resolved label → only fills missing values (preserves existing). ✅
- New row (target is None) →
herdr_workspaceset fromMAM_WS_LABEL. ✅
Tests: test_comp_resume_herdr_workspace_propagation (T6), test_comp_resume_herdr_workspace_new_row_branch (T7) — PASS. ✅
§3.3 stop_session.sh
--herdr-workspaceadded to usage() and parser.HERDR_WORKSPACE_OPTis parsed but intentionally unused — documented as "recorded label only; never selects a socket". This is correct CLI symmetry: stop reads the session's socket from its registry row, not from a workspace flag. ✅- The socket resolution uses
resolve_herdr_session(correctly renamed fromresolve_herdr_workspace). ✅
Test: test_comp_stop_usage_matches_parser now includes --herdr-workspace in the usage/parser parity check — PASS. ✅
§3.4 status.sh & reconcile.sh
- status.sh: Table output now has distinct
SOCKETandWORKSPACEcolumns (width 150, up from 136). JSON output includesherdr_workspacefield. Whenherdr_workspaceis absent, a_slug(pane.cwd)fallback derives the label. ✅ - reconcile.sh: Drift B auto-registration now populates both
herdr_serverandherdr_workspace(via_slug(pm['cwd'])). Also removed debugsys.stderr.write(...)statements (good cleanup). ✅
Tests: test_comp_status_displays_socket_and_workspace_columns (T12), test_comp_reconcile_drift_b_populates_workspace_and_server (T11) — PASS. ✅
§4. Slug Parity (D5 Dependency)
The changeset has three inline Python _slug() implementations (in lib.sh's resolve_herdr_workspace, status.sh, and reconcile.sh) plus the bash derive_workspace_slug(). All Python implementations are byte-identical. The test test_slug_parity_between_bash_and_python verifies derive_workspace_slug(path).removeprefix("mam-") == resolve_herdr_workspace("not-registered", path) for 4 parametrized paths including /tmp, /, /a/My_Proj.v2, /private/var/folders/q_/x — all PASS.
Note: derive_workspace_slug uses cd && pwd (logical path on macOS, confirmed: cd /tmp && pwd → /tmp), while the Python _slug uses os.path.abspath (also no symlink resolution). Both produce identical results. ✅
§5. Test Results
§5.1 Unit Tests (test_tier1_unit.py)
55 passed in 9.62s
Changeset-specific (20 tests):
test_resume_resolve_herdr_session_default— PASStest_resume_resolve_herdr_session_env— PASStest_resolvers_are_decoupled— PASStest_workspace_label_never_resolves_as_socket— PASStest_socket_resolver_fallback_chain— PASStest_workspace_resolver_prefers_the_row_over_the_caller_argument(C-1) — PASStest_workspace_resolver_uses_the_argument_only_when_unregistered— PASStest_slug_parity_between_bash_and_python[/tmp, /, /a/My_Proj.v2, /private/var/folders/q_/x]— 4 PASStest_no_socket_lookup_falls_back_to_workspace_label— PASS- (prior tests renamed from
resolve_herdr_workspace→resolve_herdr_session) — PASS
§5.2 Component Tests (test_tier2_component.py)
Changeset-specific (7 tests, run individually due to slow orphaned reconcile daemons):
test_comp_create_herdr_workspace_parsing_and_env_fallback(T4) — PASS (2.47s)test_comp_create_herdr_workspace_yaml_propagation(T5) — PASS (10.42s)test_create_does_not_inherit_a_stale_workspace_label(T9/D5) — PASS (19.51s)test_comp_resume_herdr_workspace_propagation(T6) — PASS (5.21s)test_comp_resume_herdr_workspace_new_row_branch(T7) — PASS (1.35s)test_comp_status_displays_socket_and_workspace_columns(T12) — PASStest_comp_stop_usage_matches_parser(updated with--herdr-workspace) — PASStest_comp_reconcile_drift_b_populates_workspace_and_server(T11) — PASS (0.94s)
§5.3 Full Suite
The full pytest tests/ -x could not complete within the 30s tool timeout due to slow orphaned reconcile.sh daemons (environmental issue N-3, not code-related). All changeset-specific tests were verified individually and pass.
§6. conftest.py Fix
The change state.setdefault("calls", []).append(sys.argv[1:]) replaces state["calls"].append(sys.argv[1:]) in the mock_herdr mock binary. This fixes a KeyError: 'calls' when the state dict doesn't have a calls key (e.g., on first invocation). Defensive, correct, and minimal. ✅
§7. Observations (Non-Blocking)
N-1: Dead Code in reconcile.sh:511 (Low Severity)
Location: .agents/skills/multi-agent-mux-monitor/scripts/reconcile.sh:511
Issue: The drift B deduplication check was changed from:
# OLD (correct):
if name in yaml_session_names or any(_sanitize(y) == name for y in yaml_session_names):
# NEW (dead first condition):
srv = t.get('server', 'default')
if (name, srv) in yaml_session_names or any(_sanitize(y) == name for y in yaml_session_names):
yaml_session_names is a set of strings ({s['name'] for s in yaml_sessions if s.get('name')}). The expression (name, srv) in yaml_session_names checks tuple membership in a set of strings — this is always False (confirmed: ('creator-claude', 'default') in {'creator-claude'} → False). The previously-working name in yaml_session_names (string-in-set → True) is lost.
Impact: The any(_sanitize(y) == name ...) fallback still handles deduplication for session names where sanitize_herdr_agent_name is a no-op (already lowercase, ≤32 chars, valid chars). For the standard workflow (names like creator-claude), behavior is identical. However, for session names that _sanitize transforms (uppercase, >32 chars, special chars), the old code's exact-match would catch the duplicate, but the new code's dead first condition + sanitize-based second condition would fail → potential duplicate YAML row registration.
Severity: Low. Standard workflow session names are lowercase and short, so this edge case is unlikely in practice. Duplicate rows are cosmetic (first-match lookup is used everywhere) and would be cleaned up by subsequent reconcile cycles.
Recommendation: Fix by creating a set of (name, server) tuples:
yaml_session_keys = {(s['name'], s.get('herdr_session') or s.get('herdr_server') or 'default')
for s in yaml_sessions if s.get('name')}
...
if (name, srv) in yaml_session_keys or any(_sanitize(y) == name for y in yaml_session_names):
Test gap: test_comp_reconcile_drift_b_populates_workspace_and_server uses an empty YAML (d['herdr_sessions'] = []), so the deduplication/skip path is not exercised. A test with a pre-existing same-name row would catch this.
N-2: Documentation Drift (Pre-existing, Out of Scope)
deploy/ docs and README.ko.md still reference old HERDR_SERVER_NAME as the primary name rather than HERDR_SESSION_NAME. Pre-existing, not introduced by this changeset.
N-3: Orphaned reconcile.sh Daemons (Environmental)
Orphaned reconcile.sh background daemons slow independent test execution (some component tests take 10-20s). Does not affect test correctness. Environmental, not code-related.
§8. Design Assessment
The decoupling design is sound:
- Separation of concerns: Socket name (
resolve_herdr_session) and workspace label (resolve_herdr_workspace) are now genuinely independent functions with non-overlapping fallback chains. - Priority consistency: Both resolvers follow the same "registered row fact > caller argument" principle (C-1), matching the existing
agent_of_rowpattern. - D5 exception is principled:
create_session.shbypassesresolve_herdr_workspacebecause it's the fact-establishing side — it shouldn't inherit stale labels from terminated rows it's about to replace. - Conditional overwrite pattern:
MAM_WS_LABEL_EXPLICITmirrors the existingHERDR_SERVER_OPT_EXPLICITpattern, providing symmetric explicit-vs-resolved semantics.
No design-level rework is needed. The N-1 dead code is a localized implementation bug, not a design flaw.
§9. Verdict
All three task goals are met:
- Legacy Fallback Chain Decoupling — All 6 socket lookup sites use only
herdr_session or herdr_server. Resolvers are cleanly decoupled. ✅ - CLI Option Standardization & YAML Metadata —
--herdr-workspaceacross create/resume/stop with correct YAML persistence and conditional overwrite. Status and reconcile display/monitor the label. ✅ - Documentation & Automated Tests — SKILL.md files updated. 27 new tests covering parsing, decoupling, default derivation, YAML propagation, slug parity, and static guard. All pass. ✅
The N-1 dead-code observation in reconcile.sh:511 is low-severity and does not block — it affects only non-lowercase session names (an edge case outside the standard workflow) and the fallback any(...) expression preserves the prior name-based deduplication for the common case.
[VERDICT: PASS]