11 KiB
Cross-Code Review Report — Job 14187d43
- Reviewer: cline (session:
herdr:canary-projects-multi-agent-mux-creator-cline) - Commit under review:
14b9de1—fix(herdr): ensure unique agent name via sha1 truncation and align mock errors - Cumulative diff vs base: clean working tree (
(no changes since base commit)per brief) - Scope: SHA-1 hash truncation for Herdr 0.8.0 name uniqueness (
.agents/skills/lib_py/agents/sanitize.py,.agents/skills/lib.sh), Mock Herdr error output alignment (tests/conftest.py), early-abort regex updates (lib.sh), and test updates (tests/test_sanitize_and_mock_errors.py,tests/test_sanity.py).
1. Methodology
Cross-code review performed across three axes, with Bash↔Python parity as a first-class concern because the sanitize contract is implemented twice:
- Lint / static correctness — syntax, shell quoting, regex anchoring, duplicate-definition consistency, import resolution.
- Functionality — collision-freedom, byte-for-byte Bash↔Python parity, error-class coverage vs. the early-abort regex, lookup-path correctness.
- Loss / regression — whether removed assertions reduced coverage, whether the new truncation breaks existing contracts, orphaned code.
Verification combined (a) direct file reads of all 5 changed files, (b) manual parity/collision computation in both Bash and Python, and (c) execution of the test suite (see §5).
2. Per-File Findings
2.1 .agents/skills/lib_py/agents/sanitize.py
- The legacy
s[:16]-s[-15:]truncation is replaced withf"{s[:23]}-{h}"whereh = sha1(s)[:8](23 + 1 + 8 = 32). Hashing the full pre-truncation string (not the prefix) is the correct choice: it guarantees that two names sharing both prefix and suffix — exactly the sibling-workspace collision case — still differ. - Empty-string handling returns
"agent"(line 13), which now matches the Bash copy (line 32). This closes the prior Bash↔Python divergence documented in jobc30845cb(Bash"x-"vs Python"agent"). - Minor: the module-level docstring was dropped (replaced by a bare
import hashlib). A docstring is not required, but its removal is a (cosmetic) loss of inline documentation. Not blocking.
2.2 .agents/skills/lib.sh (two copies: lines 29–52 and 216–239)
-
Both copies of
_sanitize_herdr_agent_namewere updated identically (verified by reading both ranges). Consistency between the library section and the shim section is preserved. -
The hash is computed with a tool cascade
shasum → sha1sum → openssl → python3, andprintf '%s' "$s"(no trailing newline) is used as the hash input — matching Python'ss.encode('utf-8'). Parity verified empirically (§5.2). -
agent getlookup (lines 286–307): the legacy prefix/suffix heuristican.startswith(tn[:14]) and an.endswith(tn[-12:])is correctly replaced withan == tn or an == stnwherestn = sanitize_herdr_agent_name(tn). The inline Python importssanitize_herdr_agent_namefromlib_py.agents.sanitize, which resolves because lib.sh exportsPYTHONPATH="$SKILL_DIR"(line 25). Correct. -
Early-abort regex (line 528):
"^usage:|unknown option|unknown flag|missing required|invalid_agent_name|^error:". The two new alternatives (missing required,invalid_agent_name) align with the mock's new error strings (missing required --pane, JSONinvalid_agent_name). Anchoring semantics are correct undergrep -E:^usage:and^error:bind only to their alternatives;invalid_agent_nameis an unanchored substring match that catches the JSON error payload. Correct. -
Observation (non-blocking): the Bash fallback (
else h=$(python3 ... || echo "00000000")) would, in the degenerate case where all ofshasum/sha1sum/openssl/python3are unavailable, emit a constant00000000suffix for every long name — reintroducing the very collisions this commit fixes. In practice this path is unreachable (python3is a hard dependency of lib.sh itself, andshasumis always present on macOS /sha1sumon Linux), so it is a theoretical robustness note only. A future improvement could hash a disambiguating fallback (e.g. a counter or${#s}), but it is not a defect for this review.
2.3 tests/conftest.py (mock Herdr agent start handler)
- Unknown-flag rejection (lines 425–427):
sys.stderr.write("unknown option: " + ... + "\n"); sys.exit(1). Matches real Herdr 0.8.0unknown option: --envformat. - Required-arg validation (lines 429–432):
missing required --pane/missing required --kind. Matches the abort-regex alternativemissing required. - Name validation (lines 434–446): emits a JSON error payload with
error.code == "invalid_agent_name", which the abort-regex catches via theinvalid_agent_namesubstring. Aligned with real 0.8.0 output and with the lib.sh abort gate. - Validation ordering (unknown flags → required args → name) is sound: each early test in
test_mock_herdr_error_formatting_and_aborthits the intended branch.
2.4 tests/test_sanitize_and_mock_errors.py (new)
test_sanitize_sibling_workspace_non_collision: asserts the 4 real sibling workspaces (allcanary-projects-*-creator-claude) sanitize to 4 distinct 32-char names. This is a direct regression test for the collision bug the legacys[:16]-s[-15:]rule caused. Verified manually (§5.2): the 4 outputs are distinct with differing SHA-1 suffixes.test_sanitize_bash_python_parity: 11 edge cases (incl. empty, digit-leading, underscore-leading, 32- and 33-char boundaries) assert byte-for-byte Bash↔Python equality. Strong contract test. All pass.test_mock_herdr_error_formatting_and_abort: exercises all three new error classes and asserts both the exact stderr substring and that it matches the abort regex. Correct and complete.
2.5 tests/test_sanity.py
- The old
assert session_name.endswith("-creator-claude")(herdr-registered name) was removed and replaced with:assert len(session_name) <= 32assert session_name == sanitize_herdr_agent_name(sessions[0]["name"])
- Not a coverage loss. The old
endswith("-creator-claude")on the herdr-registered name is incompatible with the new (correct) truncation — a long workspace name truncates tocanary-projects-multi-a-039bb460, which legitimately no longer ends with-creator-claude. The replacement assertion is stronger: it verifies the herdr agent key equals the sanitized form of the yaml session name, i.e. it pins the sanitize contract across the two stores. The unsanitized yaml name is still checked forendswith("-creator-claude")on line 72, so the semantic suffix check is retained where it is actually valid.
3. Cross-Cutting Consistency Checks
| Check | Result |
|---|---|
Bash _sanitize_herdr_agent_name == Python sanitize_herdr_agent_name (11 cases incl. empty, digit/underscore leading, 32/33-char boundaries) |
✅ Identical (verified by test_sanitize_bash_python_parity + manual run) |
Empty-string divergence (job c30845cb) resolved |
✅ Both return "agent" |
| Sibling-workspace collision (the root cause) eliminated | ✅ 4/4 unique 32-char names |
| Mock error strings ⊆ lib.sh abort regex | ✅ unknown option, missing required, invalid_agent_name all match |
agent get lookup uses sanitized name (no legacy heuristic) |
✅ an == tn or an == stn |
| Two Bash copies of the function are identical | ✅ Lines 29–52 == 216–239 |
Removed endswith assertion compensated by stronger contract assertion |
✅ |
PYTHONPATH for inline from lib_py.agents.sanitize import ... |
✅ Set at lib.sh:25 |
4. Issues Identified
Blocking issues: none.
Non-blocking observations:
- (Robustness, theoretical) The Bash hash fallback
echo "00000000"would collapse all long names to the same suffix if every hash tool were unavailable. Unreachable in any supported environment (macOS hasshasum; Linux hassha1sum;python3is itself a lib.sh dependency), so not a defect — but a future hardening could disambiguate the fallback. - (Maintainability, pre-existing)
_sanitize_herdr_agent_nameis duplicated in lib.sh (library section + shim section). Both copies are consistent after this commit, so no action is required here, but the duplication remains a drift risk. - (Cosmetic)
sanitize.pylost its module docstring; behavior is unaffected.
None of these rise to the level of requiring a fix, and none warrant replanning.
5. Test Verification
5.1 Directly-affected code paths (regression baseline + new tests)
tests/test_herdr_shim_contract.py
tests/test_tier1_unit.py
tests/test_sanity.py
tests/test_sanitize_and_mock_errors.py
=> 39 passed in 19.54s
This covers the documented regression baseline (36, per prior jobs cdd44bb3/1c80f10e) plus the 3 new tests introduced by this commit.
5.2 Manual parity / collision verification (Bash + Python)
canary-projects-educative-export-tools-creator-claude -> canary-projects-educati-9da57e6e (32)
canary-projects-getting-started-a2a-creator-claude -> canary-projects-getting-48a65fbb (32)
canary-projects-multi-agent-mux-creator-claude -> canary-projects-multi-a-039bb460 (32)
canary-projects-pu-riverpod-cookbook-creator-claude -> canary-projects-pu-rive-5e30d500 (32)
unique: True (collision eliminated)
"" -> "agent" (both Bash and Python; divergence resolved)
"exact-32-chars-long-name-1234567" -> unchanged (32, not truncated; both)
"123_starts_digit" -> "x-123_starts_digit" (both)
Bash and Python outputs are byte-for-byte identical across all cases.
5.3 Remaining (non-e2e) test files
tests/test_deploy_freshness.py test_deploy_layout.py test_deploy_registry_merge.py
tests/test_a4_adapter_contract.py test_b4_session_created.py test_b7_diff_untracked.py
tests/test_uuid_target.py test_workspace_scope.py test_o1_rebuttal.py
tests/test_o3_scoped_guard.py test_orc_onboard.py test_b8_send_keys_verification.py
tests/test_o2_race_free_lock.py
=> 181 passed in 172.03s
5.4 e2e / integration suites (tier2/3/4)
tests/test_tier2_component.py test_tier3_integration.py test_tier4_e2e.py
=> 36 passed in 192.70s (0:03:12)
These suites spawn reconcile.sh --subscribe --idle-timeout 0 loops and are inherently long-running (~3 min). All 36 pass with 0 failures / 0 errors. These suites exercise the monitor/reconcile/e2e subsystems, none of which are touched by commit 14b9de1; their clean pass confirms no collateral regression.
5.5 Aggregate
- Full suite: 256 tests pass (39 + 181 + 36), with 0 failures, 0 errors — matching the commit message's "256/256 passed" claim.
- Coverage spans every module, including all changed code paths (sanitize truncation, mock errors, abort regex,
agent getlookup) and all unaffected subsystems (deploy, adapters, reconcile, e2e). - All assertions in the new
test_sanitize_and_mock_errors.pypass.
6. Verdict
The commit correctly replaces the collision-prone legacy truncation with a collision-free SHA-1 suffix scheme, keeps the Bash and Python implementations byte-for-byte identical (including the previously-divergent empty-string case), aligns the mock Herdr error output with real Herdr 0.8.0 and with the lib.sh early-abort regex, and simplifies the agent get lookup to use the sanitized name. Test changes replace a now-invalid endswith assertion with a stronger sanitize-contract assertion rather than weakening coverage. No blocking issues were found; the only notes are theoretical/non-blocking.
[VERDICT: PASS]