Skip to content

feat: improve supervision and operational workflows - #13

Merged
acklabsio merged 15 commits into
mainfrom
fm/fm-upstream-sync-20260730
Jul 30, 2026
Merged

feat: improve supervision and operational workflows#13
acklabsio merged 15 commits into
mainfrom
fm/fm-upstream-sync-20260730

Conversation

@acklabsio

Copy link
Copy Markdown
Owner

Intent

Pull the upstream firstmate delta (kunchenguid/firstmate main, 99533c5..e595611) into this fork as ONE sync merge commit that pauses for the captain advisor review; do NOT merge it. This is a two-parent merge commit (upstream provenance intentionally preserved; landing method will be a merge commit per the captain standing order for upstream syncs). In-scope upstream PRs pulled: kunchenguid#1286 busy-worker escalation, kunchenguid#1282 test hygiene (replace source-assertion tests with behavioral coverage), kunchenguid#1281 and kunchenguid#1277 validation-scope discipline, kunchenguid#1275 intake routing, kunchenguid#1272 project-write consent exception; plus kunchenguid#1261, kunchenguid#1256, kunchenguid#1136 carried along by the merge. Deliberate conflict resolutions (not mistakes): (1) fm-session-lock-lib.sh keeps the fork's dash-leading process-name session-lock fix using parameter expansion (bc=${comm##*/}), intentionally rejecting upstream's basename reversion which reintroduces the -zsh option-parse bug; (2) AGENTS.md keeps the fork's delivery-gate state-file lines (delivered.md, delivery-override.md) AND adopts upstream's new hard-rule-1 concrete captain-approved project-operation consent exception wording; (3) fm-brief.sh keeps BOTH the fork's ESCALATION_FORMAT line and upstream's new resolve_directory_input helper; (4) adopted kunchenguid#1282's deletions of shared source-assertion test files/functions while deliberately KEEPING fork-only tests (dash-comm session-lock regression tests guarding the fix above, herdr presentation-lock, pi-watch, turnend plugins); (5) fm-kimi-harness.test.sh: adapted upstream's newly added tasktmp assertion to read the fork's home-scoped task-temp path (/tmp/fm-$HOME_TAG/$ID) instead of upstream's flat /tmp/fm-$ID, because the fork intentionally home-scopes TASK_TMP for multi-home isolation. All merge-affected tests pass locally. A pre-existing fork-only test (fm-reap-browsers) hangs only in this local macOS sandbox due to process/cwd inspection limits; it is unchanged by the merge and green in CI.

What Changed

  • Escalate busy workers that exceed the completed-turn threshold, while normalizing durable root, home, and state paths across supervision and X-mode handoffs.
  • Route project intake through secondmate ownership, honor concrete captain-approved project operations, constrain validation follow-ups to accepted behavior, and make Bearings chat-only unless file output is explicit.
  • Replace brittle source-assertion suites with behavioral coverage, refresh test-isolation evidence, and correct directory-level config ignores.

Risk Assessment

✅ Low: The relative root, explicit and fallback home, and state override paths are now normalized consistently across X-mode production, migration, validation, and polling, while the upstream merge provenance and deliberate conflict resolutions remain intact.

Testing

Targeted topology checks, behavioral suites, retained/deleted test inventory, generated CLI artifacts, and manual lock/Kimi demonstrations validated the sync intent; all deterministic checks passed, one unchanged Pi timing case failed once and passed twice on retry, the external-state-mutating real-Herdr E2E was not run under the workspace boundary, and no UI surface existed requiring screenshots.

Evidence: Two-parent sync merge provenance and imported upstream commits
Required sync merge
commit=836218bbc392851159cbce23ad54309d3fbc8504
parent_1=ea645fb52a9f1a59e5eae21cfd95059cdca52f99 e595611291247368b982eb729097c54f2b45aa78
subject=Merge remote-tracking branch 'upstream/main' into fm/fm-upstream-sync-20260730
Merge commits in reviewed range
836218bbc392851159cbce23ad54309d3fbc8504 ea645fb52a9f1a59e5eae21cfd95059cdca52f99 e595611291247368b982eb729097c54f2b45aa78
Imported upstream delta
6ec5e08 fix(bin): normalize relative durable paths (#1256)
c21bf54 refactor(skills): make Bearings chat-only by default (#1136)
96e027e Clarify follow-up routing during validation (#1277)
a24eac1 fix: honor concrete approval for project operations (#1272)
0bbb27b fix(skills): route new project intake through secondmate scopes (#1275)
daf6dce fix: scope validation corrections by accepted behavior (#1281)
a2d5f26 test: replace source assertions with behavioral coverage (#1282)
56a7ac6 fix(watch): escalate busy workers with no completed turn (#1286)
e595611 fix(gitignore): ignore config/ as a directory, not by exact filename (#1261)
Evidence: Dash-leading session-lock behavior demonstration
dash_leading_chain_resolved_harness_pid=424242
dash_leading_chain_stderr_bytes=0
dash_login_shell_misclassified_as_harness=no
dash_login_shell_check_stderr_bytes=0
verified_claude_process_recognized=yes
Evidence: Generated Firstmate brief showing structured escalation format
You are a crewmate: an autonomous worker agent managed by firstmate. Work on your own; do not wait for a human.

# Task
{TASK}

# Herdr lifecycle declaration - NOT ENABLED
**HARD SAFETY GATE:** this scaffold cannot inspect the task text that replaces `{TASK}` later.
If the task will start, stop, delete, restart, profile, or otherwise drive Herdr lifecycle behavior, stop and regenerate the brief with `--herdr-lab` before dispatch.
Do not add Herdr lifecycle commands to this unguarded brief by hand.

# Setup
You are in a disposable git worktree of sample-project, at a detached HEAD on a clean default branch.

**Verify isolation before anything else.** Run `pwd -P` and `git rev-parse --show-toplevel`; both must resolve to the disposable task worktree you were launched in, such as a treehouse pool path or an Orca-managed worktree, not the primary checkout firstmate operates from.
The path check is authoritative: `git rev-parse --git-dir` and `git rev-parse --git-common-dir` can help inspect the repo, but they do not prove you are outside the primary checkout.
If the top-level path is the primary checkout or not the worktree you were launched in, STOP - do not branch or commit here - append `blocked [key=isolation]: need=launched in the primary checkout instead of an isolated worktree | action=launch this task in a disposable isolated worktree | recommend=stop here and relaunch through the standard spawn path` to the status file and stop.

1. First action: create your branch: `git checkout -b fm/evidence-brief`
2. Run `no-mistakes doctor`; if it reports the repo is not initialized here, run `no-mistakes init`.

# Rules
1. Never push to the default branch. Never merge a PR.
2. Stay inside this worktree; modify nothing outside it.
3. Use gh-axi for GitHub operations and chrome-devtools-axi for browser operations.
4. Report status by appending one line:
   `echo "{state}: {one short line}" >> '/private/var/folders/hr/5gg95wys4n97nbcmzsb8xz9h0000gn/T/no-mistakes-evidence/01KYS6GHR9R5NC5WNGZWYGMT6S/brief-home/state/evidence-brief.status'`
   States: working, needs-decision, blocked, paused, done, failed.
For every new decision or blocker, use one concise single-line structured escalation with a stable key.
- `needs-decision [key=<slug>]: need=<concrete decision> | options=<A; B; ...> | recommend=<option and why>`
- `blocked [key=<slug>]: need=<concrete blocker> | action=<what firstmate must do> | recommend=<next step and why>`
Keep each value non-empty and do not use tabs, newlines, or the literal ` | ` separator inside a value.
Older unstructured `needs-decision:` and `blocked:` lines remain compatible, but newly scaffolded work must use the structured form above.
   Each append wakes firstmate, so report sparingly: only phase changes a supervisor
   would act on (setup done, bug reproduced, fix implemented, validation passed) and the
   needs-decision/blocked/paused/done/failed states. No step-by-step FYI progress lines;
   firstmate reads your pane for that.
   A mid-task `working:` line (including setup complete) is nonterminal: do not end the
   turn after it; continue the same stage until a defined `done:` gate under Definition of done.
   Use `paused: {why}` - distinct from `blocked:` - ONLY when you are deliberately idling on a
   known external wait you expect to clear on its own (an upstream release, a rate-limit reset,
   a scheduled window): firstmate then leaves your idle pane alone and rechecks it on a long
   cadence instead of treating it as a possible wedge. Use the structured `blocked` form above when you are stuck and need help.
5. If you hit the same obstacle twice, report it with the structured `blocked` form above and stop; firstmate will help.
6. If a decision belongs above the implementation worker (product choices, destructive actions, ask-user findings),
   report it with the structured `needs-decision` form above and stop. Firstmate will apply the configured authority and reply with the decision.
   When firstmate replies or a blocker clears and you resume, append `resolved: {how it was decided or unblocked}` (add the same `[key=<slug>]` if you opened it with one) so the decision or blocker is durably closed and does not keep resurfacing.
7. Never stop, restart, or update the shared `no-mistakes` daemon - it is one instance serving
   every lane/home, so restarting it kills other lanes' in-flight pipeline runs. On ANY no-mistakes
   daemon error, report it with the structured `blocked` form above and stop; only firstmate manages the daemon.

# Project memory
If `AGENTS.md` or `CLAUDE.md` already exists, or if this task produced durable project-intrinsic knowledge, run `/var/folders/hr/5gg95wys4n97nbcmzsb8xz9h0000gn/T/no-mistakes-evidence/01KYS6GHR9R5NC5WNGZWYGMT6S/does-not-exist/bin/fm-ensure-agents-md.sh .` in the worktree.
Record only project knowledge useful to almost every future session.
For anything the codebase already shows, prefer a pointer to the authoritative file, command, or doc over copying the detail.
If you touch a project `AGENTS.md` that lacks `## Maintaining this file`, add that short self-governance section from `/var/folders/hr/5gg95wys4n97nbcmzsb8xz9h0000gn/T/no-mistakes-evidence/01KYS6GHR9R5NC5WNGZWYGMT6S/does-not-exist/bin/fm-ensure-agents-md.sh` in the same pass.
Keep it proportionate: skip `AGENTS.md` edits for trivial tasks that produced no durable project knowledge.

# Definition of done
The task is complete only when committed on your branch.
When you believe it is complete, append `done: {summary}` to the status file and stop.
Firstmate will then instruct you to run /no-mistakes to validate and ship a PR.

You drive no-mistakes by responding to its gates, not by implementing fixes.
Follow the guidance no-mistakes itself provides for the mechanics: it loads when you invoke /no-mistakes, and `no-mistakes axi run --help` plus the `help` lines in each `axi` response are authoritative and version-matched to the installed binary.
Do not hand-edit, commit, or fix findings yourself while a run is active - the pipeline applies every fix.

Two firstmate-specific rules layer on top of that guidance:
- ask-user findings are never yours to answer: escalate to firstmate (rule 6) and stop.
  Firstmate applies the authority contract in its `AGENTS.md` and obtains any required captain decision.
  When the decision comes back, feed it to the gate with `no-mistakes axi respond` and let the pipeline apply it - do not route the question to "the user" or implement the fix yourself.
- Avoid `--yes`: it would silently bypass firstmate's authority check and any required captain escalation.

After /no-mistakes reports CI green (the CI-ready return point - do not wait for it to keep monitoring in the background until merge), append `done: PR {url} checks green` and stop. You are finished.
Evidence: AGENTS consent and delivery-gate conflict-resolution evidence
Concrete captain-approved project-operation exception
Outside hard rule 1's concrete captain-approved project operation exception, you do not do project-specific work yourself.
For all other project-specific work, delegate coding, investigation, planning, bug reproduction, and audits to a crewmate you spawn and supervise, or to a secondmate whose registered scope fits.
A secondmate is a crewmate with an isolated firstmate home and a charter, not a second architecture.

Hard rules, in priority order:

1. **Never write to a project.**
   Do not edit, commit, or run state-changing commands under `projects/` or in any project worktree; firstmate reads projects and crewmates change them.
   The only exceptions are the guarded project initialization, fleet sync, secondmate sync and inherited local-material propagation, self-update, and approved `local-only` merge paths, each owned by its referenced skill or script, plus a concrete captain-approved project operation governed directly by this rule.
   Those paths never authorize forcing, stashing, discarding unlanded work, or hand-writing a project's `AGENTS.md`.
   Firstmate may directly edit, create, move, or delete project files or directories only when the captain clearly and concretely approves, in the moment, for a specific project, either a specific operation or a concrete scope whose authorized action needs no inference; firstmate performs exactly that approval with its own file tools, never infers or broadens it, and gains no standing authority, while the force, discard, unlanded-work, merge-authority, destructive, irreversible, and security-sensitive boundaries remain independently in force.
2. **Never merge a PR without the captain's explicit word.**
   A project's captain-approved `yolo` posture is the only standing relaxation for routine decisions; section 7 owns its exceptions and preserves the stronger destructive, irreversible, and security-sensitive captain boundaries.
3. **Never tear down unlanded work.**
   Uncommitted changes are never landed, and `bin/fm-teardown.sh` owns the complete landed-work test.
Fork delivery-gate state inventory
  secondmates.md      secondmate routing table; firstmate-private, maintained by fm-home-seed.sh (section 6)
  <id>/brief.md      per-task crewmate brief, or per-secondmate charter brief when kind=secondmate
  <id>/report.md     scout task deliverable, written by the crewmate; survives teardown
  <id>/delivered.md  durable delivery-gate evidence written only by a gate pass (bin/fm-delivery-lib.sh), or by scout teardown once the report check and the unresolved-decision gate both pass; firstmate-owned, never written by a crewmate; the ONLY thing fm-spawn --requires accepts (a bare report.md is not evidence); survives teardown
  <id>/delivery-override.md  durable record of the loud delivery-gate exception written by fm-delivery-gate.sh override; survives teardown
projects/            cloned repos; gitignored; read-only except under hard rule 1's concrete captain-approved project operation exception
state/               volatile runtime signals; gitignored
Relative FM_HOME CLI result
scaffolded: /private/var/folders/hr/5gg95wys4n97nbcmzsb8xz9h0000gn/T/no-mistakes-evidence/01KYS6GHR9R5NC5WNGZWYGMT6S/brief-home/data/evidence-brief/brief.md (ship, mode=; replace {TASK})
Invalid directory refusal
/Users/ackinvestment/.no-mistakes/worktrees/3536257bd010/01KYS6GHR9R5NC5WNGZWYGMT6S/bin/fm-brief.sh: line 307: /var/folders/hr/5gg95wys4n97nbcmzsb8xz9h0000gn/T/no-mistakes-evidence/01KYS6GHR9R5NC5WNGZWYGMT6S/does-not-exist/bin/fm-project-mode.sh: No such file or directory
Evidence: Kimi home-scoped task-temp execution trace
30:+12: KIMI_RUNTIME_TASK_TMP=
306:+207: task_tmp=/tmp/fm-firstmate-2fe738c6/kimi-success-z1-17152
307:+208: KIMI_RUNTIME_TASK_TMP=/tmp/fm-firstmate-2fe738c6/kimi-success-z1-17152
311:+211: assert_grep 'export GOTMPDIR=/tmp/fm-firstmate-2fe738c6/kimi-success-z1-17152/gotmp' /var/folders/hr/5gg95wys4n97nbcmzsb8xz9h0000gn/T//fm-kimi-harness.eSG2wS/success/tmux-calls.log 'kimi spawn did not export its Go temp directory into the pane'
312:+202: grep -F -- 'export GOTMPDIR=/tmp/fm-firstmate-2fe738c6/kimi-success-z1-17152/gotmp' /var/folders/hr/5gg95wys4n97nbcmzsb8xz9h0000gn/T//fm-kimi-harness.eSG2wS/success/tmux-calls.log
319:+217: pass 'fm-spawn: kimi launches, delivers its brief, and registers a guarded turn-end token'
320:+50: printf 'ok - %s\n' 'fm-spawn: kimi launches, delivers its brief, and registers a guarded turn-end token'
321:ok - fm-spawn: kimi launches, delivers its brief, and registers a guarded turn-end token
Evidence: Initial flaky Pi watcher run
ok - Pi extension reports external healthy watcher output
ok - Pi custom tool exposes repair-only metadata and returns automatic-continuation guidance
ok - Pi redundant tool call returns ownership guidance and spawns no second child
ok - Pi scheduled retry remains extension-owned after another tool call
ok - Pi escalation renders exact plain-language chat content and triggers handling
ok - Pi actionable close starts one successor before wake delivery settles
ok - Pi hung successor falls back to one typed actionable wake
ok - Pi unretired successor falls back without an overlapping retry
ok - Pi late unretired closes resume classified supervision
ok - Pi clean empty close triggers a bounded continuity retry
ok - Pi established clean closes stop at the configured retry limit
ok - Pi close handler verifies session-lock ownership before successor launch
ok - Pi watcher arm distinguishes all session lock ownership states
not ok - Pi session transitions must rearm through an explicit generation owner: expected exit 0, got 1
Evidence: Successful Pi watcher retry
ok - Pi extension reports external healthy watcher output
ok - Pi custom tool exposes repair-only metadata and returns automatic-continuation guidance
ok - Pi redundant tool call returns ownership guidance and spawns no second child
ok - Pi scheduled retry remains extension-owned after another tool call
ok - Pi escalation renders exact plain-language chat content and triggers handling
ok - Pi actionable close starts one successor before wake delivery settles
ok - Pi hung successor falls back to one typed actionable wake
ok - Pi unretired successor falls back without an overlapping retry
ok - Pi late unretired closes resume classified supervision
ok - Pi clean empty close triggers a bounded continuity retry
ok - Pi established clean closes stop at the configured retry limit
ok - Pi close handler verifies session-lock ownership before successor launch
ok - Pi watcher arm distinguishes all session lock ownership states
ok - Pi session transitions use a generation owner across /new /resume /fork, stale callbacks, and quit
ok - Pi process-exit cleanup listener remains singular across session replacement
ok - Pi process-exit cleanup stops the attached arm child
ok - OpenCode plugins have an explicit ESM boundary even under a typeless parent package
ok - OpenCode watcher plugin uses the effective FM_HOME state
ok - OpenCode watcher plugin sources the effective config
ok - OpenCode watcher plugin requires session lock ownership
ok - OpenCode watcher coordinator respects primary scope
ok - OpenCode watcher plugin starts one successor before wake prompt delivery settles
ok - OpenCode pre-ready actionable close preserves its successor
ok - OpenCode hung successor falls back to one typed actionable wake
ok - OpenCode unretired successor falls back without an overlapping retry
ok - OpenCode late unretired closes resume classified supervision
ok - OpenCode clean empty close triggers a bounded continuity retry
ok - OpenCode established clean closes stop at the configured retry limit
ok - OpenCode close handler verifies session-lock ownership before successor launch
ok - OpenCode watcher plugin establishes supervision before the turn-end guard runs
ok - OpenCode failed arm cannot suppress the guard while its retry establishes supervision
ok - OpenCode healthy arm output does not suppress the turn-end guard
- Outcome: ⚠️ 1 warning across 1 run (16m6s)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 1 issue found → auto-fixed (4) ✅
  • ⚠️ bin/fm-bootstrap.sh:693 - When FM_ROOT_OVERRIDE is relative, only shim_home is normalized; $FM_ROOT is embedded unchanged in the durable X-mode shim. If the watcher later runs from another directory, its exec path resolves incorrectly and X polling fails. Normalize FM_ROOT before durable handoffs; the same issue affects paths embedded by fm-brief.sh and fm-afk-launch.sh.

🔧 Fix: Captain: normalize durable Firstmate root paths
1 warning still open:

  • ⚠️ bin/fm-bootstrap.sh:700 - The producer now writes an absolute root into x-watch.check.sh, but the watcher still validates that file and locates fm-x-poll.sh using its unnormalized $FM_ROOT. When the watcher inherits the same relative FM_ROOT_OVERRIDE from a different working directory, byte validation fails or the poll path resolves incorrectly, so X mode reports the authenticated shim as rejected. Apply the same root normalization in the watcher consumer, and cover the bootstrap-to-watcher handoff rather than only inspecting the generated file.

🔧 Fix: Captain: normalize X-mode consumer root paths
1 warning still open:

  • ⚠️ bin/fm-watch.sh:62 - Root normalization occurs after FM_HOME is derived from the raw FM_ROOT_OVERRIDE. In the documented legacy mode where FM_HOME is unset, the producer embeds an absolute home in the shim but the watcher retains a relative home, so byte validation fails across working directories even when both relative roots resolve to the same checkout; STATE is also derived from that relative value. The new regression test masks this by explicitly setting an absolute FM_HOME. Normalize FM_ROOT before deriving the fallback home, or normalize the derived home consistently, in the watcher, migration, and poll entry points.

🔧 Fix: Captain: normalize legacy X-mode fallback homes
1 warning still open:

  • ⚠️ bin/fm-watch.sh:74 - The reordered fallback fixes unset FM_HOME, but an explicitly relative FM_HOME is still preserved verbatim. Bootstrap writes the shim using its absolute physical home, while the watcher and migration validate it using the relative spelling, so X mode rejects the authenticated shim even when the consumer runs from the same directory. Normalize an explicit relative FM_HOME before deriving STATE and validating the shim in the watcher, migration, and poll entry points; preserve already-absolute spellings as the producer does.

🔧 Fix: Captain: normalize all X-mode durable paths
✅ Re-checked - no issues remain.

⚠️ **Test** - 1 warning
  • ⚠️ tests/fm-pi-watch-extension.test.sh:961 - The retained Pi watcher suite failed once at its session-transition generation-owner scenario, then passed under trace and on a normal retry. The case predates this merge, identifying a timing flake rather than a deterministic sync regression.
  • git show -s --format=&#39;commit=%H%nparents=%P%nsubject=%s&#39; 836218bbc392851159cbce23ad54309d3fbc8504 and git rev-list --merges --parents ea645fb..02dbd6f
  • git log --reverse --format='%h %s' 99533c5..e595611
  • bash tests/fm-claude-stop-autoarm.test.sh
  • bash tests/fm-brief.test.sh
  • bash tests/fm-kimi-harness.test.sh
  • bash tests/fm-turnend-guard.test.sh
  • bash tests/fm-pi-watch-extension.test.sh - failed once, then passed under bash -x and on a normal retry
  • bash tests/fm-watch-triage.test.sh
  • bash tests/fm-ask-user-authority.test.sh
  • bash tests/fm-spawn-dispatch-profile.test.sh
  • bash tests/fm-gitignore-config.test.sh
  • bash tests/fm-bearings-snapshot.test.sh
  • Manual dash-leading -zsh process-chain exercise against bin/fm-session-lock-lib.sh
  • Generated a ship brief through bin/fm-brief.sh using a relative FM_HOME and inspected its structured escalation content
  • Traced tests/fm-kimi-harness.test.sh to verify /tmp/fm-$HOME_TAG/$ID metadata and GOTMPDIR propagation
  • Verified the fork-only session-lock, Herdr presentation, Pi watcher, and turn-end tests remain while the shared source-assertion files are deleted
  • Checked git status --short --untracked-files=all and evidence size for transient-artifact cleanup
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

sparkus and others added 15 commits July 29, 2026 22:40
* fix(bin): handle dash-leading harness process names (#2)

* fix: handle dash-leading harness process names

* no-mistakes(review): Make dash-leading harness regression hermetic

* fix: preserve secondmate reply routes across relative homes

Resolve relative home, data, and state inputs before durable charter generation, and fail when caller-relative directories cannot be resolved.

Use absolute paths at the related spawn, AFK daemon, and X-mode cross-process handoffs so later processes cannot reinterpret them from another working directory.

* no-mistakes(review): Preserve absolute overrides and normalize relative durable paths

* no-mistakes(review): Normalize relative home before deriving durable paths

* no-mistakes(document): Document relative durable-path normalization

* no-mistakes(review): Captain: Ignore inherited CDPATH during relative path normalization

* no-mistakes(lint): Fix empty CDPATH assignments for ShellCheck
* Add internal status skill

* no-mistakes(document): register /status skill in documentation-audiences inventory

* no-mistakes(lint): replace grep|wc -l with grep -c in status skill test

* test: silence literal status skill patterns

* Refactor bearings default to chat-only

---------

Co-authored-by: Kun Chen <3233006+kunchenguid@users.noreply.github.com>
* docs: add captain-approved project operation exception to hard rule 1

Firstmate stays read-only over projects by default, but when the captain
clearly approves a concrete project operation and scope in the moment,
firstmate may perform exactly that approved operation with its own tools.
The approval is never inferred, broadened, or standing, and it does not
relax the existing force, discard, unlanded-work, or merge-authority
boundaries.

* no-mistakes(review): Clarify captain-approved project operation boundaries

* no-mistakes(document): Clarify captain-approved project operation scope

* docs: cover directories and preserve the operation-or-scope alternative

Widen the captain-approved project operation exception in AGENTS.md to
files or directories, and restore the explicit operation-or-scope
alternative that a prior pipeline auto-fix had collapsed into "and".

Rework project-management SKILL.md's Remove section, which previously
told firstmate to refuse project removal until a guarded helper existed;
that helper was never built, so the text directly contradicted the new
instruction-only exception. It now points at the exception plus the
existing removal preflight it still requires unchanged.

Update the one instruction-owners test assertion that hard-coded the
sentence removed above, so the suite tracks current, not obsolete, text.

* docs: add captain-approved project operation exception to hard rule 1

Firstmate stays read-only over projects by default, but when the captain
clearly approves a concrete project operation and scope in the moment,
firstmate may perform exactly that approved operation with its own tools.
The approval is never inferred, broadened, or standing, and it does not
relax the existing force, discard, unlanded-work, or merge-authority
boundaries.

* no-mistakes(review): Clarify captain-approved project operation boundaries

* no-mistakes(document): Clarify captain-approved project operation scope

* docs: cover directories and preserve the operation-or-scope alternative

Widen the captain-approved project operation exception in AGENTS.md to
files or directories, and restore the explicit operation-or-scope
alternative that a prior pipeline auto-fix had collapsed into "and".

Rework project-management SKILL.md's Remove section, which previously
told firstmate to refuse project removal until a guarded helper existed;
that helper was never built, so the text directly contradicted the new
instruction-only exception. It now points at the exception plus the
existing removal preflight it still requires unchanged.

Update the one instruction-owners test assertion that hard-coded the
sentence removed above, so the suite tracks current, not obsolete, text.

* no-mistakes(review): Align project removal preflight with approved exception

* no-mistakes(document): Align project removal documentation with approved exception

* fix: restore removal test byte-for-byte and preserve the default sentence

tests/fm-instruction-owners.test.sh had been changed to assert different
text; restore it byte-for-byte to origin/main. project-management SKILL.md's
Remove section now keeps the exact default "Never issue a raw removal
command from Firstmate." sentence that test still asserts, immediately
followed by the already-approved captain-operation-or-scope exception, so
the default and the exception both stay explicit and consistent.

* no-mistakes(document): Align project-write boundary documentation
…henguid#1275)

* Route project intake through secondmate scopes

* no-mistakes(test): Guard all main-home project registry mutations

* no-mistakes(document): Consolidate secondmate routing documentation

* no-mistakes: apply CI fixes

* Restore new-project routing scope

* no-mistakes(document): Clarify secondmate routing for new-project intake

* no-mistakes: apply CI fixes
)

* fix: scope validation corrections by accepted behavior

* no-mistakes(review): Classify stale delivery evidence as an autonomous correction
…#1282)

* test: remove source-content assertions

* no-mistakes(review): Replace source assertions with runtime behavior coverage

* no-mistakes(review): Isolate Kimi task temp runtime coverage

* no-mistakes(document): Refresh test cleanup documentation

* no-mistakes: apply CI fixes
…#1286)

* fix(watch): bound how long a busy pane may run with no completed turn

A busy pane (backend busy state or the harness's rendered footer) was
unconditional, unbounded proof of liveness in every escalation path, so a
hung foreground tool call behind a busy signature could run for hours
undetected (2026-07 hibit-agent-focus-nonsteal-r1 incident: a catastrophic-
backtracking regex hung one bash call for 25h behind an unchanging
"Working..." footer).

FM_BUSY_TURN_MAX_SECS (default 3600s) now bounds how long a busy pane may
run with no completed turn (state/<id>.turn-ended, or its spawn record
before any turn has completed). Past the bound, busy_turn_over_age routes
the pane through the existing wedge_timer_check, reusing the identical
stale reason, escalation counter, and demand-deep-inspection marker for
human inspection only - never an automatic interrupt, signal, or restart
of the worker or its tool process. A completed turn resets the age.

Reproduced end-to-end against the real installed Pi TUI: a foreground
`sleep 999999` bash call with no timeout renders the actual busy footer,
and two captures ~15s apart show the elapsed counter changing the pane
hash while the same turn stays unfinished. Running the pre-fix watcher
against the real captures showed it never starts a wedge timer no matter
how long the pane stays busy; the fixed watcher starts and escalates the
timer through the same mechanism, while the real hung process remained
untouched and alive throughout.

* no-mistakes(review): fix: parse enriched AFK stale reasons

* no-mistakes(review): fix: preserve enriched wedges during AFK supervision

* no-mistakes(review): fix: route all enriched AFK wedges

* no-mistakes(document): Clarify busy-turn age supervision documentation
…unchenguid#1261)

A name-by-name list of config/ entries silently stops ignoring any new or
home-local file placed there, which makes the working tree read as dirty and
blocks guarded sync paths that refuse to touch a dirty home. AGENTS.md
already documents config/ as captain-private and gitignored as a category;
this makes .gitignore match that contract.
…-20260730

Pulls the upstream firstmate delta (99533c5..e595611): upstream kunchenguid#1286
busy-worker escalation, kunchenguid#1282 test hygiene, kunchenguid#1281 and kunchenguid#1277 validation-scope
discipline, kunchenguid#1275 intake routing, and kunchenguid#1272 project-write consent exception,
plus kunchenguid#1261, kunchenguid#1256, and kunchenguid#1136 carried along by the merge.

Conflict resolutions preserve local divergences and adopt upstream intent:
- fm-session-lock-lib.sh: keeps the local dash-leading process-name
  session-lock fix (parameter expansion), not upstream's basename reversion.
- AGENTS.md: keeps the local delivery-gate state-file lines and adopts
  upstream's hard-rule-1 project-operation consent exception wording.
- fm-brief.sh: keeps both the local escalation-format line and upstream's
  resolve_directory_input helper.
- Adopts kunchenguid#1282's test-hygiene deletions of shared source-assertion tests
  while keeping fork-only coverage (dash-comm session-lock regression tests,
  herdr presentation-lock, pi-watch, turnend plugins).
- fm-kimi-harness.test.sh: adapts upstream's new tasktmp assertion to the
  fork's home-scoped task-temp path (/tmp/fm-$HOME_TAG/$ID).
@acklabsio
acklabsio merged commit 0a979f4 into main Jul 30, 2026
10 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.

5 participants