test: back Herdr live-duplicate agent registrations with a running process - #21
Merged
Merged
Conversation
The duplicate-live-label case in tests/fm-backend-herdr-smoke.test.sh registered an agent with `herdr pane report-agent` on a pane idling at its top shell, then expected create_task to refuse the same label. Herdr 0.9.3 releases such a registration within about a second once the pane's foreground is its own top shell (a nested shell or any other foreground process keeps it), so the case raced that release and failed whenever create_task read the pane after it: agent_not_found classifies the pane as an agent-free husk and create_task correctly replaces it. The stale side is the test, not the backend. A pane whose only registration sits over its bare top shell is not a live agent, and the backend's husk classification is right to close and replace it; a real agent holds the pane's foreground, so Herdr keeps its registration and the backend still classifies it live and refuses. Older Herdr kept the report, so the case only passed by reading it as a stale registration, which the husk check also refuses. The case now starts an agent-named foreground process (a `claude` symlink to `sleep`, the fixture tests/fm-control-herdr-smoke.test.sh already uses) before reporting, and asserts the pane classifies live before the refusal check, so it proves the live-agent refusal rather than passing on a stale or unreadable registration. The 0.9.3 measurement is recorded in docs/verification/runtime-backends.md.
cloud-practitioner
force-pushed
the
fm/fm-herdr-smoke-dup-label
branch
from
October 1, 2026 01:40
7905eae to
7eac44d
Compare
…g process tests/fm-backend-herdr-respawn-idem-e2e.test.sh made the same stale assumption as the smoke suite's live-duplicate case: it registered an agent with `herdr pane report-agent` on a pane idling at its top shell and expected create_task to refuse the duplicate label. Herdr 0.9.3 releases that registration within about a second, so the case raced the release and failed 2 of 6 runs against the installed Herdr 0.9.3. Apply the same test-side fix: start an agent-named foreground process (a `claude` symlink to `sleep`) before reporting, and assert the pane classifies live before the refusal check. The backend's classification is unchanged and correct.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Fix test failures found along the way: the duplicate-live-label case in tests/fm-backend-herdr-smoke.test.sh fails against the installed Herdr 0.9.x, on main as well as on branches, apparently because Herdr 0.9.x ignores the agent report call (report-agent). Make that case pass against the installed Herdr 0.9.x: first establish whether Herdr 0.9.x changed report-agent behaviour in a way firstmate's Herdr backend must handle (a real product bug) or whether only the test's assumption is stale, and fix the right side.
What Changed
tests/fm-backend-herdr-smoke.test.shandtests/fm-backend-herdr-respawn-idem-e2e.test.sh: in the live-duplicate case, the test now starts aclaudesymlink tosleepin the pane and waits untilfm_backend_herdr_pane_process_statereadsagentbefore it callspane report-agent. Herdr 0.9.3 drops a registration within about a second when the pane's foreground is its own top shell, so before this change the registration was gone before the duplicate check ran. The smoke test also removes its new scratch dir on exit.fm_backend_herdr_pane_agent_statereturnslivebefore testing thatcreate_taskrefuses the duplicate label. Without that check, the case could pass on a stale or unreadable registration, which the husk check also refuses.docs/verification/runtime-backends.md: added a measurement from Herdr 0.9.3 with the probe commands and their output. A registration on a pane idling at its top shell is released, while a nested foreground shell keeps it. This confirms the backend's release handling still matches Herdr and that only the tests' assumption was out of date, so no product code changed.🤖 Generated with Claude Code
Risk Assessment
✅ Low: The change only touches tests and docs. Each live-duplicate fixture now runs an agent-named foreground process (a
claudesymlink tosleep). It waits untilfm_backend_herdr_pane_process_statereadsagent, then registers, then assertsfm_backend_herdr_pane_agent_statereadslivebefore checking the refusal. I traced this against the classifier and the agent-state logic and it is correct. The new doc measurement backs the conclusion that only the test's assumption was stale: a real crew pane keeps its agent in the foreground, so it is not a product bug. The respawn-idem change matches a finding the pipeline declined earlier, but the author committed it themselves, so it does not conflict with a recorded decision.Testing
I ran the two changed real-Herdr tests (smoke and respawn-idem) against the installed Herdr 0.9.3 on both the branch and a copy of base. Both passed on base by winning a race, so I added a 2s delay after report-agent in throwaway copies. With the delay, base fails exactly as reported and the branch still passes. A guarded fm-herdr-lab probe showed the cause: Herdr releases the registration within about 280ms on an idle top shell, but keeps it under a nested shell or a
claude-named process. Firstmate's classifier reads these three shapes as no-agent, stale-agent and live, which is the correct product behaviour, so only the test assumption needed fixing. Everything passed; the lab session and temp copies are torn down.Evidence: Herdr 0.9.3 report-agent registration lifetime probe (idle shell vs nested shell vs claude-named process)
Source: Herdr 0.9.3 report-agent registration lifetime probe (idle shell vs nested shell vs claude-named process)
Evidence: Firstmate backend classification of the probe panes
Source: Firstmate backend classification of the probe panes
w2:p1 process_state=shell agent_state=no-agent w3:p1 process_state=shell agent_state=stale-agent w4:p1 process_state=agent agent_state=liveEvidence: Smoke test on branch
Source: Smoke test on branch
Evidence: Respawn-idem e2e on branch
Source: Respawn-idem e2e on branch
Evidence: Smoke test at base with 2s delay (reproduces the reported failure)
Source: Smoke test at base with 2s delay (reproduces the reported failure)
not ok - REGRESSION: create_task should refuse a duplicate label whose pane hosts a genuinely live registered agent (idle counts as live) exit=1Evidence: Smoke test on branch with the same 2s delay
Source: Smoke test on branch with the same 2s delay
Evidence: Respawn-idem at base with 2s delay (fails)
Source: Respawn-idem at base with 2s delay (fails)
Evidence: Respawn-idem on branch with 2s delay (passes)
Source: Respawn-idem on branch with 2s delay (passes)
Evidence: Smoke test at base, no delay (passes by winning the race)
Source: Smoke test at base, no delay (passes by winning the race)
Evidence: Respawn-idem at base, no delay (passes by winning the race)
Source: Respawn-idem at base, no delay (passes by winning the race)
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
✅ **Review** - passed
✅ No issues found.
✅ **Test** - passed
✅ No issues found.
bash tests/fm-backend-herdr-smoke.test.shon the branch (real Herdr 0.9.3, own fm-lab-* session): exit 0, live-duplicate refusal okbash tests/fm-backend-herdr-respawn-idem-e2e.test.shon the branch: exit 0, live-duplicate refusal okBoth tests from agit archive bbc8d9acopy of base: both passed, so the base failure is a timing raceBase and branch copies withsleep 2added afterherdr pane report-agent: base smoke and base respawn-idem both fail withnot ok - REGRESSION: create_task should refuse ...; branch smoke and branch respawn-idem both passLab probe viabin/fm-herdr-lab.sh name/provision/run/teardown:pane report-agentthenagent getpolled every 250ms on (A) an idle top shell, (B) a nested bash in the foreground, (C) aclaude->sleepsymlink in the foregroundfm_backend_herdr_pane_process_state/fm_backend_herdr_pane_agent_staterun on the three probe panes in the labbin/fm-herdr-lab.sh teardown, then confirmed only the default session remains and the worktree is clean✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.