Skip to content

fix(bin): sync upstream main into house (hold reasons, orphan arms, hand-back downtime, polling churn) - #177

Merged
jazz127 merged 6 commits into
housefrom
fm/hf-upstream-main-sync-5
Oct 2, 2026
Merged

jazz127 merged 6 commits into
housefrom
fm/hf-upstream-main-sync-5

Conversation

@jazz127

@jazz127 jazz127 commented Oct 2, 2026 •

Copy link
Copy Markdown
Owner

Intent

you better have a look and bring in upstream main for firstmate and no mistakes

Context for reading that ask. The fork jazz127/firstmate runs house (default branch, merge commits only) as the line the fleet runs from; its main mirrors upstream kunchenguid/firstmate main. Fork house is at 79066a8. Upstream main is at 65e2aa4, five commits past the last sync: 349e189 (Pi 1.0 calm transcript test captures, kunchenguid#6338), 6af8331 (preserve hold reasons and reject invalid completion inventories, kunchenguid#6331), 8690c41 (reclaim orphaned watcher arms on the next park, kunchenguid#6335), 241d461 (restore downtime on supervision-host hand-back when the successor already closed, kunchenguid#6355), 65e2aa4 (reduce remote-job polling process churn, kunchenguid#6363). A read-only trial merge conflicts in bin/fm-remote-job-lib.sh, bin/fm-session-start.sh and tests/fm-supervision-host.test.sh.

Integration

Merge pinned upstream main 65e2aa443a42108689eee260a0d792608ec3540b into fork house from 79066a8692bcf5762abcc532697d36e28574b4ea with a true merge commit.
The fork main mirror step was skipped per steering; no fork main branch was created or pushed.

Preserve house provisioning bounds, ready-session timeout reporting, remote worker lifecycle guards, and per-row supervision receipts while integrating upstream hold-reason decoding, watcher takeover, hand-back downtime restoration, Pi transcript fixtures, and remote polling optimizations.
Restore worker_job_command for the house callers retained after upstream removed it from the polling path.
Dropped house behavior: none.
This PR must land with a merge commit.

All 16 affected test scripts passed, plus the separate provisioning regression.
Synthetic/offline validation is recorded in the task evidence artifact.
The before fixture models the auto-merged worker without its removed helper: the first long provisioning request exits 126 before cloning.
Restoring the helper makes the provisioning suite pass, including command-named timeout diagnostics and recovery after interruption.
No remote host or multi-GiB clone was exercised.
Linux-only remote worker lifecycle and session-start /proc ancestry cases are not exercised on this macOS host.

No-mistakes Test exception: its targeted batch stopped at its time limit after remote-job, delta-read, and 50 passing supervision-host cases; the remaining pipeline suites were not exercised.
Firstmate expressly accepted the inconclusive Test result for this sync.
The separate worker run completed all 16 affected suites successfully.
House CI must be green before merge; its configured scope is house delivery/workflow regressions, lint, and inventory coverage.

Known baseline lint findings: the two SC2031 warnings in house's PIDFD test PATH reads also reproduce on the unmodified house test file; upstream's test file is clean.
These baseline findings were left unchanged.

evidence-artifact: /Users/jarad/.treehouse/firstmate-570371/1/firstmate/data/hf-upstream-main-sync-5/integration-notes.txt
evidence-command: git ls-remote upstream refs/heads/main
evidence-captured: 2026-10-02T10:49:22Z

Evidence classification

The pipeline attestation below is preserved verbatim.
Its live_validation classification of three scenarios refers to Bash CLI probes in disposable fixture homes: worker refusal, full startup digest, and hold-reason readback.
The artifacts show synthetic/offline checks of our code, with no real-account, remote-host, or independent harness validation.
All three probes passed; the pipeline's other four scenarios were not driven through that scenario-validation path.
Git ancestry is confirmed separately by the merge's two parents, and the complete local affected-suite run provides the broader synthetic regression evidence.

kunchenguid and others added 6 commits October 1, 2026 13:58
)

* test(calm): pin Pi's regular TUI mode where pane assertions read scrollback

Pi 1.0.0 defaults its TUI to a fullscreen alternate-screen mode whose
scrollable transcript is application-owned, so rows that leave the viewport
never enter terminal scrollback and tmux capture-pane -S can no longer see
them. The Pi Calm e2e launches now pass --tui-mode regular wherever the flag
exists so the transcript assertions keep reading real scrollback on both the
Pi 1.0.0 line and earlier Pi lines, which have no such flag and render
regular-only anyway.

* no-mistakes(document): Correct Pi TUI documentation and scrollback rationale
…ries (kunchenguid#6331)

* fix(bin): encode captain-hold reasons and reject self-inventory in complete

hold now stores a reason with parentheses, line breaks, or percent signs
through a reversible percent encoding that every reader decodes, instead of
refusing it. hold --origin records the origin on the held task, and complete
refuses the origin as its own inventory entry and an entry held for a
different origin; holds with no recorded origin are accepted and flagged.

* fix(review): Decode marked hold reasons consistently across readers

* fix(review): Remove unnecessary lifecycle test dispatch

* fix(review): Correct hold origin identity and inventory recovery

* fix(review): Record origins before placing backend holds

* fix(document): Clarify captain-hold validation and reason reader documentation

* fix(ci): Fixed both findings: failed backend holds restore the previous origin, and invalid base64/UTF-8 reasons remain verbatim. Added regressions and documented valid-literal ambiguity. Both failures were reproduced before fixes. Verification: 54 lifecycle tests and 9 wrapper tests passed; 7 Beads-specific cases skipped because tasks-axi is markdown-only. Focused lint and diff checks passed. No pipeline or publication actions performed
* fix(bin): take over the watcher cycle a main-only pass-through leaves

An attended main-only pass-through leaves a successor watcher cycle
running through main's handling turn. The session's next park attached
to that cycle instead of owning it, so the successor's arm, orphaned by
its host's exit, kept owning the watcher while the new park's arm polled
it twice a second until the next close or the park boundary, hours later
in a quiet second mate. A second-mate restart hit this every time, since
its persist request is a main-only close.

The host now records the successor it leaves for main, and the next
host's first cycle runs bin/fm-watch-arm.sh --take-over on it: when that
arm still owns the healthy watcher, the new arm stops it, reports a
reason the cycle delivered first, and otherwise owns a fresh cycle. The
stop's own downtime publication is undone over an acknowledged episode
when no wake was appended in between, so the handover wakes nobody.

* no-mistakes(review): Keep left-arm record until the orphaned arm is gone

* no-mistakes(review): Relinquish successor arm only after durably recording it

* no-mistakes(review): Relinquish successor only after its record reads back

* no-mistakes(document): Clarify successor takeover guarantees and authoritative documentation

* no-mistakes(ci): Fixed ci-1: acknowledgement restore now requires the exact taken-over arm/watcher ledger row with signal=TERM, awaited within a short bound. Otherwise takeover proceeds without erasing downtime. Added a self-exit regression confirmed failing before the fix and passing afterward; ordinary takeover tests and the full watcher-arm suite pass. Updated Generation reuse documentation. Syntax, diff checks, and ShellCheck pass with existing SC1091/SC2034 warnings excluded. ci-2 remains unchanged

* no-mistakes(document): Clarify watcher take-over recovery and restart limits
…cessor already closed (kunchenguid#6355)

* fix(bin): restore supervision host hand-back continuity

* no-mistakes(review): Scope host hand-back failure fallback to lost pending:handling

* no-mistakes(review): Remove stray scratch test copy tests/.tmp-rest.test.sh

* no-mistakes(test): Initialise successor globals so early hand-back survives set -u

* no-mistakes(document): Document host hand-back downtime failure and Claude lost-handback notice

* no-mistakes(ci): I fixed the Greptile finding. The rule that must hold: when the supervision host hands back an actionable wake, its rewake is refused, and no watcher is healthy, the hand-back still has to reach main as a delivered notice. That must be true whether the recovery marker is `pending:handling` or `announced:handling`. Only one place applies this check: the lost hand-back fallback in `bin/fm-claude-stop-autoarm.sh`. **Fix:** that check now accepts both `pending:handling:*` and `announced:handling:*` tokens (a one-line change). Nothing else in the fallback changed: - Refusals on any other marker, such as an already acknowledged one, still exit 0 silently and open no failure episode. - The notice is still sent once per episode, and repeats are recorded as `failed-suppressed`. **Tests:** - `tests/fm-claude-stop-autoarm.test.sh`: the lost hand-back test now runs as a shared helper with two variants, one writing a `pending:handling` marker and a new one writing `announced:handling` (`test_host_lost_announced_handback_notifies_once_per_episode`). - `tests/fm-supervision-host.test.sh`: the end-to-end test where downtime restoration fails is now a shared helper too, with a new `announced` variant (`test_claude_stop_hook_notifies_when_closed_announced_successor_downtime_restore_fails`). It moves the handling episode to `announced` before the host hands back. Without the fix the hook would exit 0 here; the test requires exit 2, `outcome=failed` and a delivered failure notice. **Verification (all under nice -n 10):** - The full `tests/fm-claude-stop-autoarm.test.sh` suite passed (rc=0), including both lost hand-back variants and the benign-refusal test. - In `tests/fm-supervision-host.test.sh` I ran only the four hand-back test functions, all passing (rc=0). The suite can't run single functions, so I used a temporary copy with a trimmed test list and deleted it afterwards; `git status` shows only the 3 intended files changed. - shellcheck is clean on all three changed files. I did not run `bin/fm-lint.sh`. - I did not run the new tests against the unfixed code; the claim that they fail without the fix comes from reading the old check
* perf: cut remote-job idle process creation in the three hot loops

Post-update host measurement still attributes most idle churn to three
per-sample loops: result-consumer state reads and date calls, the delta
reader's capture/hash pass on every poll, and the lane preemption scan's
per-field pipelines. This drops each to its minimum without touching the
contracts around them.

* fm_remote_job_read_state gains an optional result-variable form backed
  by fm_remote_job_read_line, a builtin-only bounded record read (regular
  non-symlink file, byte bound, one newline-terminated line, tolerated
  unterminated tail, no carriage returns). fm_remote_job_wait samples
  state and the SECONDS clock with no per-sample children; one date call
  converts the epoch deadline once.
* fm-remote-delta-read stats the log each poll and re-runs the bounded
  capture and hashing only when size, mtime, ctime, inode, or device
  change. The snapshot's own stat writes the comparison key, so a log
  that moves between the gate and the capture is never read as stable.
* worker_preempting_waiter_exists reads state, home, and the staged argv
  head with builtins only. The now-unused worker_job_command goes away.

The bounded reads use -d '' -n, which behaves identically on the macOS
stock bash 3.2 and current bash; -N does not exist on 3.2. Tests cover
the malformed-record corpus, delta identity gating, fork-free lane
scanning through counting PATH shims, and same-home versus cross-home
preemption. No signal traps or sleep contracts change.

* no-mistakes(review): Restore subsecond delta keys and byte-bounded builtin record reads

* no-mistakes(document): Clarify delta snapshot caching and coarse-timestamp fallback

* no-mistakes(lint): Scope UTF-8 regression locales to individual function calls

* no-mistakes(ci): Fixed both lint failures by applying the documented production-library analysis boundary at the two affected test imports. Runtime behavior is unchanged; the library remains independently linted. Canonical full-analysis lint passed for the library and both suites, as did bash syntax checks and git diff --check
Integrate upstream through 65e2aa4 with house provisioning bounds, ready timeout reporting, and per-row supervision receipts preserved. Retain the command helper used by house timeout validation and diagnostics alongside upstream polling optimizations.
@jazz127
jazz127 merged commit 4f0a04d into house Oct 2, 2026
1 check passed
@jazz127
jazz127 deleted the fm/hf-upstream-main-sync-5 branch October 2, 2026 12:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants