Conversation
Teardown refused any record whose endpoint was already cleared, so a lane could never be retired once its window was gone and it kept occupying an in-flight row. Accept an explicit endpoint_cleared stamp as stronger agent-less evidence than a dead window, with no flag and no --force, while keeping the unlanded-work refusal unchanged. A projected Herdr teardown confirmed only the task pane was gone, so a workspace whose recorded pane vanished before its close survived for a restart to restore as a live agent in the primary clone. Remove the workspace's remaining panes through the same focus-preserving pane close and require the workspace gone before retiring the journal. A dead pane whose display redrew re-alarmed on every new hash, a supervision tax that grew with each dead lane. Absorb a redrawn dead display against the existing once-record, while a relaunched agent re-arms the incarnation and its own death still reports in full.
|
Speaking as Kun's firstmate: First look on HEAD Contract-class: restore. Independent tip-vs-main on the unconfigured path:
CI/NM: tip was action_required. Fork workflows approved this pass after diff review (no .github/workflows edits; teardown still refuse-unlanded; no credential surface): CI 35483475080, Require no-mistakes 35483475076 — queued. MERGEABLE/UNSTABLE. no-mistakes blocking; missing attestation keeps NM red until rebound. VISION.md (each rule)
Decision: waiting-author — add matching pipeline attestation for this HEAD. Restore + safe review → auto-merge candidate once attestation MATCH and CI+NM green. No Firstmate flag. Security: clean. No Closes/Fixes issue claims verified. |
What
Two lane-accounting leaks, shipped as one coherent fix.
1. A lane whose endpoint was cleared can now be retired
bin/fm-backend.sh's endpoint validator required awindow=line, so a recordcarrying an explicit
endpoint_cleared=<reason>stamp and no window refused onevery teardown path, including
--legacy-record. Five live records with mergedPRs and absent worktrees read as in flight for weeks.
fm_backend_validate_task_endpointgains--allow-cleared: a record with nowindow but one explicit, non-empty
endpoint_clearedstamp is accepted as anagent-less cleared endpoint (target empty,
FM_BACKEND_VALIDATED_ENDPOINT_CLEAREDset). Teardown consumes that contract: it skips the Herdr preflight, pane close,
confirmed-gone gate, and transition clear, and never issues an endpoint command.
The cleared stamp also satisfies the incarnation gate for a record that predates
spawn_gen, so no--legacy-recordis needed. The unlanded-work refusal isuntouched, and
--forceremains the only way to discard work.2. A projected workspace is removed, not just its pane
Teardown confirmed only the recorded task pane was gone, so a projected Herdr
workspace whose pane had already vanished before its close survived for a
restart to restore as a live agent with its working directory set to the primary
clone.
New
fm_backend_herdr_projection_workspace_remove_focus_preservingcloses anypanes the disposable workspace still holds through the existing
focus-preserving pane close (refusing a live or unknown agent), and teardown
retires the journal only once the workspace itself is confirmed gone. It never
calls
workspace close.3. A dead pane stops waking once its record is known dead
wedge_dead_recordreports a dead endpoint once, but only from the wedge timer,which runs on a stable hash. A husk whose display redrew re-entered the
first-sight surface path on every new hash. A new
dead_endpoint_absorbconsultsthe once-record and absorbs a changed dead display while the pane reads idle and
the marker's incarnation still matches, so a relaunched agent re-arms the
incarnation and its own death still reports in full.
Tests
tests/fm-teardown.test.sh: cleared endpoint tears down with no flag or--force; cleared endpoint still refuses unlanded work; a missing windowwithout a stamp still refuses; a projected workspace left by the task-pane
close is removed without
workspace close; a surviving workspace refuses andretains every record.
tests/fm-watch-triage.test.sh: a reported-dead window absorbs a redrawndisplay under the same incarnation and re-reports a successor's death.
Portable and driven through each script's own CLI; no implementation-source
assertions.
bin/fm-lint.sh,bin/fm-doc-audience-check.sh,tests/fm-teardown.test.sh,tests/fm-watch-triage.test.sh,tests/fm-teardown-endpoint-safety.test.sh,tests/fm-herdr-session-cleanup.test.sh,and
tests/fm-backend-herdr.test.shall pass.