Skip to content

feat(bin): sync upstream firstmate (jev memory guard, keep-ai-trailers, Herdr and polling fixes) - #13

Merged
zakna merged 8 commits into
mainfrom
fm/fm-upstream-sync-o2
Sep 28, 2026
Merged

zakna merged 8 commits into
mainfrom
fm/fm-upstream-sync-o2

Conversation

@zakna

@zakna zakna commented Sep 27, 2026

Copy link
Copy Markdown
Owner

Intent

Update firstmate to the latest: the fork's own changes plus the original project's new changes.

Context: this firstmate home runs from the fork zakna/firstmate (remote origin), which already runs its latest main. The original project is kunchenguid/firstmate (remote upstream). A first sync (PR #11, fm-upstream-sync-o1) merged upstream earlier on 2026-09-27. Since then upstream's main has 6 new commits the fork lacks (kunchenguid#5886, kunchenguid#5917, kunchenguid#5876, kunchenguid#5859, kunchenguid#5900, kunchenguid#5903). A read-only test merge of upstream/main into origin/main on 2026-09-27 had no conflicts.

What Changed

Risk Assessment

✅ Low: The branch's delta against origin/main is exactly upstream's six commits (kunchenguid#5886, kunchenguid#5917, kunchenguid#5876, kunchenguid#5859, kunchenguid#5900, kunchenguid#5903), with every fork-only change kept and no conflict markers, so it is a clean upstream sync that matches the stated intent.

Testing

The Test agent exceeded its invocation budget before live validation completed; no evidence was gathered for this head.

  • Outcome: ⚠️ 1 warning across 1 run (30m1s)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

✅ **Review** - passed

✅ No issues found.

⚠️ **Test** - 1 warning
  • ⚠️ The Test agent did not finish within its invocation budget. Reported: agent run tests timed out after 30m0s: agent last produced output 1s ago (81 observed); agent reported: claude parse events: context deadline exceeded. This is a budget or provider-slowness cut, not a code failure. Re-running the same request costs another full budget, so no further attempt is made automatically. If this repository's targeted tests or evidence gathering routinely approach the default 30m0s, raise test_agent_timeout in global config. Respond with fix to spend another budget: a repair turn runs only for selected findings other than this budget cut, then validation re-runs. Or abort and retry after raising the budget.
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

RooseveltAdvisors and others added 8 commits September 27, 2026 07:25
…hrashing guard (kunchenguid#5903)

* feat(jev): add the guard framework and the memory RSS/swap thrashing guard

A Jev guard is a bounded read-only host diagnostic that turns one class of
resource pressure into a machine-readable audit record and a one-line verdict.
This lands the framework contract (docs/jev-guards.md) with one representative
family (Pattern 46, memory RSS and swap thrashing) as the pilot: thin bash
wrapper, stdlib-only python engine, and a behavioral test through the CLI.

* no-mistakes(review): fix jev mem guard fail-open unknown and contract

* no-mistakes(review): fix mem guard rss pairing, memfree, tests, docs

* no-mistakes(review): fix inverted UNKNOWN branch in fail-forcing test

* no-mistakes(review): register docs/jev-guards.md in audience inventory

* no-mistakes(review): simplify wrapper, drop dead top_n, single-source thresholds

* no-mistakes(review): assert exact exit code in fail-forcing test leg

* no-mistakes(review): tolerate any stdout encoding in text output

* no-mistakes(document): Fix guard contract dash style and output wording
…enguid#5900)

* fix(bin): stop slow GitHub reads from starving and waking the contributions poll

The poll's fixed budget cut the tail URL's reads short, and any read killed at the bound was recorded as a forge failure, so routine GitHub slowness produced an observation-unavailable wake. A configured FM_CONTRIBUTIONS_BUDGET now rides the generated check shim and is cut down to the watcher's per-check bound with a margin, a read killed at the bound or the deadline is budget refusal that leaves records untouched, and the poll moves to the next URL that still has a full observation reserve instead of ending.

* fix(bin): report the bound when a signal death leaks through fm_run_timed

fm_run_external_timeout trusted the wrapper's recorded status over the runner's own bound verdict, so a read killed by the bound's TERM could surface as 143 and callers such as the contributions poll classified a budget-bound read as a forge failure. When the runner reports the bound, a signal-death status is the bound's own TERM racing the wrapper's bookkeeping and is reported as 124; a natural exit still passes through. The replace-shell probe also moves to the repo's portable BASHPID fallback so the suite runs on the macOS system bash.

* no-mistakes(review): Rotate contribution polling and verify generated budget behavior

* no-mistakes(review): Stabilize contribution rotation across successful observation refreshes

* no-mistakes(review): Exclude settled contributions from live observation rotation

* no-mistakes(document): Document contribution poll rotation and observation reserves

* no-mistakes(ci): Captain, fixed timeout handling with a one-line change preserving natural exit 137. Full session-start and contributions suites, targeted regressions, and lint passed. The timeout suite still fails on the known Bash 3.2 BASHPID issue, left unchanged as instructed. Logs retained in .no-mistakes/ci-evidence/. Remote CI was not rerun

* no-mistakes(ci): Fixed the fixture’s lock-acquisition race with a one-line bounded wait. Forced contention reproduced the CI error before the fix and passed afterward; the ordinary held-lock case, lint, syntax, and diff checks passed. Local Bash 3.2 failures remain: “cleanup lock bound 08 gave up before the marker lock freed” (also reproduced without the fix) and “TERM did not stop a watcher blocked inside a poll”. Remote CI was not rerun
…railers (kunchenguid#5859)

* feat: add keep AI trailers setting

* no-mistakes(document): Drop duplicate keep-ai-trailers line, update Cursor attribution note

* no-mistakes(document): Honor keep-ai-trailers for Devin worker attribution

* no-mistakes(document): Qualify Devin attribution note with keep-ai-trailers flag

* no-mistakes(review): Inherit keep-ai-trailers into secondmate homes
…sh-command popup cannot hide the composer (kunchenguid#5876)

* Fix Herdr composer reads blinded by the slash-command popup

Capture the full visible viewport for every Herdr composer state and content read instead of a bounded tail.
Claude Code renders its slash-command popup between the composer and the pane bottom, which pushes the composer outside a tail window.
The pre-Enter payload proof then read an empty composer, judged a typed command unsent, and cleared it without pressing Enter.
The proof-lines value now bounds only the clear cost, not the capture size.
Growing the window adds rows above the composer only, so bottom-most shape selection and prior verdicts are unchanged.
The suffix refusal is kept, and the shared inbox pending-line read stays a bounded tail.
Portable regressions cover the popup-below-composer layout, and the live submit-confirmation guard gains a third exit scenario.
The runtime-backends verification record documents the Herdr 0.9.0 and Claude Code 2.1.283 run.

Closes kunchenguid#5533

* no-mistakes(document): Clarify composer capture bound ownership

* no-mistakes(review): Drop unrequired bracketed-paste Enter fallback from live guard

* no-mistakes(review): Latch trust prompt, check idle composer arm first
…configurable bound (kunchenguid#5917)

Each per-task endpoint read in the session-start fleet digest runs in its own crash-isolated child under the existing timeout helper with a configurable FM_SESSION_START_ENDPOINT_TIMEOUT bound (default 10s).

A hung or killed read becomes that task's endpoint error while the digest continues, and the wrapper banners any abnormal child exit naming its status.
…nchenguid#5886)

* Keep lab tmux sockets on short private paths

* no-mistakes(review): Fix Linux stat checks and fail-closed lab tmux teardown

* no-mistakes(document): Update lab helper documentation for isolated tmux sockets
Copilot AI lite review requested due to automatic review settings September 27, 2026 21:03

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 39959a05ca

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread bin/fm-spawn.sh
Comment on lines +4713 to +4718
if [ "$KEEP_AI_TRAILERS" = 0 ]; then
"$FM_ROOT/bin/fm-git-strip-ai-trailers.sh" install "$GIT_HOOKS_DIR" "$WT" || {
echo "error: could not install the AI-trailer strip hooks for $ID" >&2
exit 1
}
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve AI-trailer stripping for every worker

When config/keep-ai-trailers is present, this conditional skips the commit-msg hook, while the associated Claude and Devin changes also retain their attribution settings. Any supported runtime that emits attribution can therefore add an agent Co-Authored-By trailer to commits, directly violating this repository's unconditional prohibition on agent commit co-authors; the opt-in must not disable that invariant.

AGENTS.md reference: AGENTS.md:L45-L50

Useful? React with 👍 / 👎.

Comment thread bin/fm-contributions.sh
Comment on lines +103 to +105
CHECK_TIMEOUT=${FM_CHECK_TIMEOUT:-30}
case "$CHECK_TIMEOUT" in ''|*[!0-9]*|0) CHECK_TIMEOUT=30 ;; esac
BUDGET_CAP=$((CHECK_TIMEOUT - 3))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Normalize the watcher timeout before arithmetic

When FM_CHECK_TIMEOUT is a zero-padded numeric value such as 08, the digit-only validation accepts it, but Bash parses it as octal in this arithmetic expansion and exits with value too great for base; because this runs before command dispatch, poll, arm, and even read-only subcommands all fail instead of enforcing the configured bound. Normalize the value to base 10 or reject padded inputs before arithmetic.

Useful? React with 👍 / 👎.

Comment thread bin/fm-jev-mem-guard.py
except Exception:
return []

for entry in entries:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Enforce a deadline while scanning process RSS

On a host with a large process table or slow procfs reads, this loop performs a separate blocking statm read for every PID and often another comm read, without checking elapsed time or applying an outer timeout. Because every invocation, including --check, runs this scan, the guard can exceed its documented sub-500ms budget and block its caller instead of degrading to UNKNOWN; stop scanning at a monotonic deadline or run the scan under an enforced bound.

Useful? React with 👍 / 👎.

Comment thread bin/fm-lab-home.sh
chmod 700 "$socket_dir" || { rmdir "$socket_dir" 2>/dev/null || true; exit 1; }
[ "$(fm_lab_home_mode "$socket_dir")" = 700 ] && [ "$(fm_lab_home_owner "$socket_dir")" = "$(id -u)" ] \
|| { rmdir "$socket_dir" 2>/dev/null || true; fm_lab_home_error "cannot secure tmux directory"; exit 1; }
(umask 077; printf '%s\n' "$socket_dir" > "$record") || { rmdir "$socket_dir" 2>/dev/null || true; exit 1; }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Serialize creation of the lab tmux directory

When two validation processes call tmux-dir for the same lab home concurrently, both can observe the record as absent, create different /tmp/fml.* directories, and overwrite this record; both callers report success, but teardown knows only the last directory. If the losing caller starts tmux, its server and socket remain untracked and cannot be cleaned up through this helper, so publish the record under a lock or atomic create and make losing callers discard their directory.

Useful? React with 👍 / 👎.

Comment thread bin/fm-contributions.sh
Comment on lines +369 to +371
jq -Rnr --argjson bucket "$((EPOCH / 300))" '
[inputs] | if length == 0 then . else ($bucket % length) as $offset | .[$offset:] + .[:$offset] end
| .[]' < "$TMP/live.tsv" > "$TMP/known.tsv"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use a poll-sequence rotation to prevent starvation

When checks run at a cadence whose five-minute bucket step shares a factor with the live URL count, this wall-clock offset never selects some URLs first. For example, with four URLs, a valid 600-second check cadence alternates offsets 0 and 2; if slow forge reads leave room for only the first observation, URLs 1 and 3 are never attempted, recreating the starvation this change is intended to prevent. Advance a durable cursor per completed poll, or otherwise ensure every offset is visited independently of polling cadence.

Useful? React with 👍 / 👎.

@zakna
zakna merged commit 2a0a916 into main Sep 28, 2026
19 checks passed
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.

7 participants