Skip to content

docs(skills): add the standing upstream-sync skill and two-tier validation cadence - #77

Merged
withally merged 31 commits into
mainfrom
fm/fm-upstream-sync-skill-f2
Aug 27, 2026
Merged

docs(skills): add the standing upstream-sync skill and two-tier validation cadence#77
withally merged 31 commits into
mainfrom
fm/fm-upstream-sync-skill-f2

Conversation

@withally

@withally withally commented Aug 27, 2026

Copy link
Copy Markdown
Owner

Intent

Write the standing upstream-sync skill for withally/firstmate so weekly fork catch-up follows a durable checklist: keep-list decided by rule and reviewed at the PR; two-tier weekly/monthly validation with the next monthly full run on 2026-10-01; unrelated breakage filed as follow-up; docs/upstream-sync.md as the procedural spine; one documented Herdr lab setup; a fixed worker brief template; the AGENTS.md pointer; and the required skill/docs tests and lint. Preserve one sentence per Markdown line, use upstream only as the documented selective source, do not touch the m2 worktree, do not push to upstream, do not merge. Update the existing PR 77 through every no-mistakes gate and CI.

What Changed

  • Adds docs/upstream-sync.md as the procedural spine for the weekly fork catch-up — upstream remote guard with push disabled, branch-at-upstream/main, the chore: snapshot upstream main audit window with its earlier-boundary override, the keep rule, and the catch-up log carrying Next monthly full run: 2026-10-01.
  • Adds the agent-only .agents/skills/upstream-sync skill over that spine: dispatcher intake resolving the five values (UPSTREAM_BASE, SNAPSHOT, SETTLED, TIER, DATE), the worker checklist, the weekly/monthly tier decision, plus references/worker-brief.md (fixed brief template) and references/herdr-lab.md (one documented Herdr lab setup); AGENTS.md gains the load-trigger pointer and docs/documentation-audiences.json registers all four new files.
  • Extends bin/fm-test-run.sh changed-path mapping so non-SKILL.md files under .agents/skills/* resolve through families_for_test_reference and otherwise fall back to pure-contract-unit, with a matching case in tests/fm-test-run.test.sh that commits a skill reference asset and asserts the pure-contract suite is selected.

Risk Assessment

✅ Low: The change is almost entirely procedural documentation whose one executable delta — a single .agents/skills/*) arm in families_for_changed_path — is narrow, correctly ordered, and covered by a behavioral test that fails closed without it; I traced the intake/worker boundary algorithm through a full next-sync cycle against live repo state and found no path that produces a wrong window, a lost keep-list, or a silently green validation.

Testing

Ran the targeted suites the repo's own changed-file map selects for this diff (fm-test-run, fm-documentation-audiences, fm-ensure-agents-md, fm-herdr-lab, fm-lint) — all green — and proved the selector change is a real regression fix by running the new test against the base-commit selector, where it fails with no changed-test mapping for source path: .agents/skills/upstream-sync/references/herdr-lab.md. Because the deliverable is a standing procedure rather than a library, I exercised the procedure itself instead of grepping its prose: the SKILL.md step-1 guard block was extracted verbatim and executed against a read-only clone of the real fork with the live upstream remote, producing every documented blocked: refusal, passing on real values, and leaving git push upstream refused via the DISABLED push URL; the doc's audit-window steps resolved the real snapshot marker to 0 PRs versus 69 from the forbidden range; the tier rule resolved weekly through September and monthly from 2026-10-01; the fixed worker brief rendered through bin/fm-brief.sh into the complete prompt a worker agent actually receives with all five values filled; and bin/fm-herdr-lab.sh's refusals matched the herdr-lab reference. Visual evidence is included as rendered HTML plus Chrome screenshots of the catch-up log table, the monthly-run line, and the skill head. Everything passed and the worktree is clean; no findings.

Evidence: SKILL.md step-1 guard block executed against the real fork and live upstream

Source: SKILL.md step-1 guard block executed against the real fork and live upstream

### scenario: upstream remote points at some other fork blocked: upstream remote does not point at kunchenguid/firstmate -> exit=1 ### scenario: recorded base is not an ancestor of upstream/main blocked: recorded UPSTREAM_BASE is not an ancestor of upstream/main; upstream history was rewritten or the base is not upstream material -> exit=1 ### scenario: valid brief (real values) -> exit=0 === after the valid run, can the worker push to upstream? === fetch url = https://github.com/kunchenguid/firstmate.git
push url = DISABLED fatal: 'DISABLED' does not appear to be a git repository -> git push upstream exit=128

=== upstream-sync SKILL.md step 1 guard block, extracted verbatim and executed against a real read-only clone of withally/firstmate ===
real upstream/main tip (kunchenguid/firstmate) = 10b93b2cc6f4241e87fccaee2e357c33a7347a53
latest 'chore: snapshot upstream main' marker on origin/main = 34d9081e491b98cb7800eb919dbd1bbf47395e72

### scenario: brief missing SNAPSHOT
    blocked: brief is missing UPSTREAM_BASE or SNAPSHOT
    -> exit=1

### scenario: upstream remote points at some other fork
    blocked: upstream remote does not point at kunchenguid/firstmate
    -> exit=1

### scenario: SNAPSHOT is not a commit in this clone
    From https://github.com/kunchenguid/firstmate
    ... (25 remote-tracking branches fetched from upstream)
    fatal: remote error: upload-pack: not our ref deadbeefdeadbeefdeadbeefdeadbeefdeadbeef
    fatal: remote error: upload-pack: not our ref deadbeefdeadbeefdeadbeefdeadbeefdeadbeef
    blocked: SNAPSHOT is not a commit in this clone
    -> exit=1

### scenario: recorded base is not an ancestor of upstream/main
    From https://github.com/kunchenguid/firstmate
    ... (25 remote-tracking branches fetched from upstream)
    blocked: recorded UPSTREAM_BASE is not an ancestor of upstream/main; upstream history was rewritten or the base is not upstream material
    -> exit=1

### scenario: valid brief (real values)
    From https://github.com/kunchenguid/firstmate
    ... (25 remote-tracking branches fetched from upstream)
    -> exit=0

=== after the valid run, can the worker push to upstream? ===
    fetch url = https://github.com/kunchenguid/firstmate.git
    push  url = DISABLED
    fatal: 'DISABLED' does not appear to be a git repository
    fatal: Could not read from remote repository.
    
    Please make sure you have the correct access rights
    and the repository exists.
    -> git push upstream exit=128
Evidence: fm-test-run.sh skill-reference routing, before vs after

Source: fm-test-run.sh skill-reference routing, before vs after

--- BEFORE (selector at base commit): a skill reference asset has no mapping fm-test-run: no changed-test mapping for source path: .agents/skills/upstream-sync/references/herdr-lab.md -> exit=2 --- AFTER (selector on this branch): the same paths select pure-contract coverage -> exit=0 (count=32)

=== bin/fm-test-run.sh changed-file selection for this change's own paths ===
changed paths vs base b0638f6:
    .agents/skills/upstream-sync/SKILL.md
    .agents/skills/upstream-sync/references/herdr-lab.md
    .agents/skills/upstream-sync/references/worker-brief.md
    AGENTS.md
    bin/fm-test-run.sh
    docs/documentation-audiences.json
    docs/upstream-sync.md
    tests/fm-test-run.test.sh

--- BEFORE (selector at base commit): a skill reference asset has no mapping
    fm-test-run: no changed-test mapping for source path: .agents/skills/upstream-sync/references/herdr-lab.md
    -> exit=2

--- AFTER (selector on this branch): the same paths select pure-contract coverage
    tests/fm-arm-pretool-check.test.sh
    tests/fm-ask-user-authority.test.sh
    tests/fm-bearings-board.test.sh
    tests/fm-brief.test.sh
    tests/fm-calm-pi-extension.test.sh
    tests/fm-captain-hold-lifecycle.test.sh
    tests/fm-cd-pretool-check.test.sh
    tests/fm-classify-decision-key.test.sh
    tests/fm-composer-ghost.test.sh
    tests/fm-composer-lib.test.sh
    tests/fm-crew-state.test.sh
    tests/fm-documentation-audiences.test.sh
    tests/fm-ensure-agents-md.test.sh
    tests/fm-grok-harness.test.sh
    tests/fm-herdr-lab.test.sh
    tests/fm-kimi-harness.test.sh
    tests/fm-lint-workflows.test.sh
    tests/fm-lint.test.sh
    tests/fm-muse-harness.test.sh
    tests/fm-operational-input.test.sh
    tests/fm-pi-primary-types.test.sh
    tests/fm-send-popup-settle.test.sh
    tests/fm-send-settle.test.sh
    tests/fm-subagent-pretool-check.test.sh
    tests/fm-supervision-instructions.test.sh
    tests/fm-task-delivery.test.sh
    tests/fm-test-isolation-proof.test.sh
    tests/fm-test-run.test.sh
    tests/fm-tmux-submit-busy.test.sh
    tests/fm-trace-context-lib.test.sh
    tests/fm-transition-lib.test.sh
    tests/fm-vendor-auth-probe.test.sh
    -> exit=0  (count=32)
Evidence: Audit window on the real fork vs the forbidden range

Source: Audit window on the real fork vs the forbidden range

--- step 3: latest first-parent 'chore: snapshot upstream main' marker on origin/main 34d9081e491b98cb7800eb919dbd1bbf47395e72 2026-08-27 chore: snapshot upstream main for 2026-08-27 (#78) --- step 4: fork PRs to audit, i.e. $CATCHUP..origin/main first-parent --- step 5 negative control: the forbidden 'origin/main ^upstream/main' range commit count = 69 (vs 0 from the documented range)

=== docs/upstream-sync.md steps 3-4 executed on the real fork (audit window from the latest catch-up marker) ===

--- step 3: latest first-parent 'chore: snapshot upstream main' marker on origin/main
    34d9081e491b98cb7800eb919dbd1bbf47395e72	2026-08-27	chore: snapshot upstream main for 2026-08-27 (#78)

--- step 4: fork PRs to audit, i.e. $CATCHUP..origin/main first-parent

--- step 5 negative control: the forbidden 'origin/main ^upstream/main' range, for contrast
    commit count = 69  (vs 0 from the documented range)
Evidence: Two-tier cadence resolution across dates

Source: Two-tier cadence resolution across dates

parsed Next monthly full run date : 2026-10-01 catch-up rows recording a full/monthly run on or after 2026-10-01 : none today=2026-08-27 -> TIER=weekly today=2026-09-05 -> TIER=weekly today=2026-09-30 -> TIER=weekly today=2026-10-01 -> TIER=monthly today=2026-10-03 -> TIER=monthly

=== tier resolution, applying the skill step 2 rule to the doc declared state ===
  parsed Next monthly full run date : 2026-10-01
  catch-up log rows and their tiers :
    2026-08-22 -> tier full
    2026-08-27 -> tier full (predates the two-tier rule)

  catch-up rows recording a full/monthly run on or after 2026-10-01 : none

  today=2026-08-27  -> TIER=weekly
  today=2026-09-05  -> TIER=weekly
  today=2026-09-30  -> TIER=weekly
  today=2026-10-01  -> TIER=monthly
  today=2026-10-03  -> TIER=monthly

  September dates stay weekly because the captain skipped September deliberately;
  the first sync on or after 2026-10-01 resolves monthly and runs the full suite with the Herdr gate skip made fatal.
Evidence: Emitted worker brief (the actual prompt a sync worker receives)

Source: Emitted worker brief (the actual prompt a sync worker receives)

You are a crewmate: an autonomous worker agent managed by firstmate. Work on your own; do not wait for a human.

# Task
## Task: monthly upstream sync of withally/firstmate onto kunchenguid/firstmate

This is SHARED TRACKED firstmate material: load `firstmate-coding-guidelines` before editing anything.
Then load `upstream-sync` and follow its "Worker checklist" step by step; it owns every command.
`docs/upstream-sync.md` owns the rules those commands implement.

Recorded values:

- UPSTREAM_BASE: `10b93b2cc6f4`
- SNAPSHOT: `34d9081`
- SETTLED: `b0638f6`
- TIER: `monthly`
- DATE: `2026-10-03`

Fixed rules:

- Bind UPSTREAM_BASE, SNAPSHOT, and SETTLED as shell variables from the recorded values above before running any checklist command, and stop if UPSTREAM_BASE or SNAPSHOT is empty.
- Branch at UPSTREAM_BASE; never merge origin/main into it.
- Audit only the first-parent commits in SNAPSHOT..WINDOW_END, where the skill's step 4 pins WINDOW_END from `origin/main` at listing time; never re-read `origin/main` for it later.
- Decide every keep by the doc's keep rule yourself; no mid-flight approval.
- Cherry-pick kept PRs with `-x`; upstream wins every conflict.
- Run only the TIER's validation from the skill; CI's portable shards and its required Herdr lane on the PR are the weekly full gate.
- Append the catch-up log row before shipping, recording that pinned WINDOW_END as the row's `Window end commit`, and commit it with `git add docs/upstream-sync.md && git commit -m 'docs: record the 2026-10-03 catch-up'`, advancing the `Next monthly full run` line on a monthly tier; a row that is uncommitted or added after the PR is open is never validated and never reaches `origin/main`.
- Ship the PR with `no-mistakes axi run --skip rebase --intent "monthly upstream sync of withally/firstmate onto kunchenguid/firstmate at 10b93b2cc6f4"`; `--intent` is required to start a run, and a cutover branch is cut from `upstream/main`, so rebasing it onto the fork's `origin/main` would replay the divergent fork history back onto the new base and undo the adoption.
- Unrelated breakage is a `Follow-ups` entry in the PR, never a fix on this branch.
- If the kept diff selects the `real-herdr-gated` family per the skill's `comm -12` check against `bin/fm-test-run.sh --list`, and this brief was not scaffolded with `--herdr-lab`, stop with `blocked: sync touches Herdr, brief needs --herdr-lab` and wait.
- If that check selects the family and this brief does carry the lab contract, run the family locally per the skill's step 10; do not block a second time.
- PR title: `chore: snapshot upstream main for 2026-10-03`; PR body carries the verdict table, `Tier: monthly`, the validation commands run, and `Follow-ups`.
- Never push to `upstream`; never merge.

# Herdr isolation - HARD SAFETY CONTRACT
This brief was explicitly scaffolded with `--herdr-lab` because the task will drive Herdr lifecycle behavior.
On Herdr 0.7.3 the API socket is not relocatable by `HERDR_CONFIG_PATH`, `XDG_CONFIG_HOME`, or `HOME`.
A named non-`default` session plus a trailing `--session <name>` on every call is the only viable local isolation.

1. Set `HERDR_LAB_HELPER='/Users/ivan/.no-mistakes/worktrees/37852af5566c/01M11P1851NKH9TZRYN1BRXKH5/bin/fm-herdr-lab.sh'` and generate the session name with `HERDR_LAB_SESSION=$("$HERDR_LAB_HELPER" name fm-upstream-sync-2026-10-03)`.
   Install `trap '"$HERDR_LAB_HELPER" teardown "$HERDR_LAB_SESSION"' EXIT` before provisioning, then provision only with `"$HERDR_LAB_HELPER" provision "$HERDR_LAB_SESSION"`.
2. Run every task-specific non-lifecycle Herdr command through `"$HERDR_LAB_HELPER" run "$HERDR_LAB_SESSION" <arguments...>`.
   The helper appends the required trailing `--session "$HERDR_LAB_SESSION"`; `HERDR_SESSION` alone is never accepted as isolation.
3. Teardown only through `"$HERDR_LAB_HELPER" teardown "$HERDR_LAB_SESSION"`.
   It re-checks refuse-default immediately before stop and again immediately before delete, and fails closed on ambiguity.
4. If an experiment requires a deliberate mid-run session stop, use only `"$HERDR_LAB_HELPER" stop "$HERDR_LAB_SESSION"`; it performs the same immediate refuse-default check.
5. Forbidden commands: direct `herdr server stop`, every other server-global operation such as `herdr server live-handoff` or reload/update operations, direct `herdr session stop`, direct `herdr session delete`, and any Herdr call scoped only by ambient or inline `HERDR_SESSION`.
6. The helper records the live default session before provisioning and verifies the identical fleet state after teardown.
   A missing, stopped, or changed default session is a hard tripwire failure, never a cleanup warning to ignore.

Never bypass the helper, even for a read-only lifecycle probe or cleanup after failure.
The captain fleet uses the running `default` session.

# Setup
You are in a disposable git worktree of firstmate, 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: launched in primary checkout, not an isolated worktree` to the status file and stop.

1. First action: create your branch: `git checkout -b fm/fm-upstream-sync-2026-10-03`
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}" >> '/tmp/upsync-home.8KIjgk/state/fm-upstream-sync-2026-10-03.status'`
   States: working, needs-decision, blocked, paused, done, failed.
   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 `blocked:` when you are stuck and need help.
5. If you hit the same obstacle twice, append `blocked: {why}` and stop; firstmate will help.
6. If a decision belongs above the implementation worker (product choices, destructive actions, ask-user findings),
   append `needs-decision: {summary of options}` and stop. Firstmate will reply with the decision.
   A decision or blocker you opened stays open until a `resolved` line carrying its exact key lands; a later `done:` or `working:` line never closes it, even when the answer is what started that work.
   Firstmate's reply normally writes that closing line at answer time; when a blocker or wait clears WITHOUT a firstmate reply, append `resolved: {how it cleared}` yourself (same `[key=<slug>]` if you opened it with one) as you resume.
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, append `blocked: {the daemon error}` 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 `/Users/ivan/.no-mistakes/worktrees/37852af5566c/01M11P1851NKH9TZRYN1BRXKH5/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 `/Users/ivan/.no-mistakes/worktrees/37852af5566c/01M11P1851NKH9TZRYN1BRXKH5/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
Delivery contract: mode=no-mistakes
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.
When starting no-mistakes, make `--intent` preserve all relevant content from this brief's `# Task` section plus every later accepted Firstmate requirement, clarification, constraint, exclusion, and supersession, carrying only each requirement's current accepted form; retain direct requirements instead of substituting a diff summary, and exclude generic operational, status, delivery, and other scaffold boilerplate unless it is task-specific.
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 `ask-user-authority` 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: Herdr lab helper contract exercised against bin/fm-herdr-lab.sh

Source: Herdr lab helper contract exercised against bin/fm-herdr-lab.sh

name upstream-sync-weekly -> "fm-lab-upstream-sync-we-43292-18475" (label capped at 16 chars, fm-lab- prefix) refusal: session literally named default fm-herdr-lab: refusing session name 'default' -> exit=1 refusal: caller-supplied --session on run fm-herdr-lab: run forbids caller-supplied --session -> exit=1 refusal: server lifecycle subcommand through run fm-herdr-lab: run forbids server operations -> exit=1

=== references/herdr-lab.md helper contract, exercised against bin/fm-herdr-lab.sh ===

  "$HERDR_LAB_HELPER" name upstream-sync-weekly -> "fm-lab-upstream-sync-we-43292-18475"  (label capped at 16 chars, fm-lab- prefix, pid+random suffix)

  refusal: session literally named default
    fm-herdr-lab: refusing session name 'default'
    -> exit=1

  refusal: session name without the fm-lab- prefix
    fm-herdr-lab: session name must start with 'fm-lab-' and contain only letters, digits, underscores, or dashes: not-a-lab-session
    -> exit=1

  refusal: caller-supplied --session on run
    fm-herdr-lab: run forbids caller-supplied --session; the helper appends the lab session
    -> exit=1

  refusal: server lifecycle subcommand through run
    fm-herdr-lab: run forbids server operations; use provision for the named lab server
    -> exit=1

  refusal: leading option on run
    fm-herdr-lab: run forbids a leading option before the Herdr subcommand; it could shift a server or session lifecycle operation past the guard or subvert session isolation
    -> exit=1
- Evidence: [Rendered upstream-sync doc + skill surfaces (HTML)](https://github.com/withally/firstmate/blob/e6d629c00fbdf8997cbb4ea0fa7a6d85811a9468/.no-mistakes/evidence/fm/fm-upstream-sync-skill-f2/upstream-sync-rendered.html) - Evidence: [Screenshot: catch-up log table and skill head](https://github.com/withally/firstmate/blob/e6d629c00fbdf8997cbb4ea0fa7a6d85811a9468/.no-mistakes/evidence/fm/fm-upstream-sync-skill-f2/upstream-sync-catchup-log.png) - Evidence: [Screenshot: Next monthly full run line in context](https://github.com/withally/firstmate/blob/e6d629c00fbdf8997cbb4ea0fa7a6d85811a9468/.no-mistakes/evidence/fm/fm-upstream-sync-skill-f2/upstream-sync-monthly-line.png) - Evidence: [Screenshot: docs/upstream-sync.md rendered head](https://github.com/withally/firstmate/blob/e6d629c00fbdf8997cbb4ea0fa7a6d85811a9468/.no-mistakes/evidence/fm/fm-upstream-sync-skill-f2/upstream-sync-rendered-top.png) - Evidence: [Screenshot: SKILL.md rendered head](https://github.com/withally/firstmate/blob/e6d629c00fbdf8997cbb4ea0fa7a6d85811a9468/.no-mistakes/evidence/fm/fm-upstream-sync-skill-f2/upstream-sync-skill-top.png)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

⏭️ **Rebase** - skipped

Step was skipped.

⚠️ **Review** - 2 infos
  • ℹ️ docs/upstream-sync.md:1 - This branch adds docs/upstream-sync.md as a new file while origin/main now carries a divergent copy that landed with the m2 cutover, so the branch and main conflict on that path. Verified live: git merge-base HEAD origin/main is b0638f67e (pre-cutover), origin/main is at 34d9081 (chore: snapshot upstream main for 2026-08-27 (#78)), and git merge-tree --write-tree --name-only HEAD origin/main reports exactly one conflict — CONFLICT (add/add): Merge conflict in docs/upstream-sync.md — while AGENTS.md, bin/fm-test-run.sh, and docs/documentation-audiences.json all auto-merge cleanly. The pipeline's rebase step owns resolving it, so this is not a blocker, but the resolution direction is load-bearing and worth stating: this branch's version must win wholesale. origin/main's copy is the older three-column log with no Window end commit column and no Next monthly full run line, and intake step 1 (SKILL.md:44-46) parses that column while intake step 2 (SKILL.md:59) reads that line — a resolution that kept or unioned main's copy would make the next sync stop at blocked: origin/main has a catch-up log whose newest row names no window end commit or blocked: origin/main carries no upstream-sync doc; the tier rule has no source. Nothing in main's copy is absent from this branch's (both catch-up rows are present here, with the m2 cutover already recorded as landed at 34d9081), so taking this branch's file verbatim loses nothing.
  • ℹ️ .agents/skills/upstream-sync/SKILL.md:168 - Step 5's recovery path says to read the excluded snapshot squash's catch-up log row (read its row with git show origin/main:docs/upstream-sync.md) but never states how to map a squash commit to a row, and step 12's required row fields cannot carry that mapping. Step 12 (SKILL.md:265) requires date, adopted base, window end commit, tier, and verdicts; the sync's own merge SHA is not among them and is unknowable when the row is appended, since the squash does not exist until merge. The mapping is unambiguous today only because this fix round hand-wrote landed on origin/main as 34d9081 (chore: snapshot upstream main for 2026-08-27 #78) into the 2026-08-27 row's base column, which a future checklist-appended row will not carry. A derivable key does exist and is reliable: step 13 (SKILL.md:280) titles the PR chore: snapshot upstream main for &lt;DATE&gt; and step 12 records that same &lt;DATE&gt; as the row's Catch-up date, so the squash's subject names its row exactly. Risk is low because rows are chronological and "the newest row at or before this squash" is a safe fallback, but an ambiguous lookup drops the accumulated keep-list, which is the silent loss steps 5 and 12 exist to prevent. Fix: state the key inline in step 5 — "the row whose Catch-up date equals the &lt;DATE&gt; in that squash's subject" — and mirror it at docs/upstream-sync.md:37.
✅ **Test** - passed

✅ No issues found.

  • bin/fm-test-run.sh tests/fm-test-run.test.sh tests/fm-documentation-audiences.test.sh tests/fm-ensure-agents-md.test.sh — all green
  • bin/fm-test-run.sh tests/fm-herdr-lab.test.sh tests/fm-lint.test.sh — all green
  • Regression proof: replaced bin/fm-test-run.sh with the base-commit version and ran bash tests/fm-test-run.test.sh — new case skill reference asset selects pure contract coverage fails; restored and it passes
  • bin/fm-test-run.sh --list --changed --base b0638f6 before/after the selector change on this change's own paths (exit 2 vs exit 0, 32 tests selected)
  • Extracted the SKILL.md step-1 shell block verbatim and executed it in a scratch clone of withally/firstmate against the live kunchenguid/firstmate remote, across 5 scenarios (missing SNAPSHOT, wrong fork, unknown SNAPSHOT, non-ancestor base, valid brief)
  • git push upstream HEAD:refs/heads/main after the valid step-1 run — refused, push url = DISABLED
  • docs/upstream-sync.md step 3 marker search and step 4 audit range executed on the real fork, with the step-5 forbidden range as a negative control
  • Applied the skill's step-2 tier rule to the doc's Next monthly full run line and catch-up log for 2026-08-27, 2026-09-05, 2026-09-30, 2026-10-01, 2026-10-03
  • FM_HOME=&lt;tmp&gt; bin/fm-brief.sh fm-upstream-sync-2026-10-03 firstmate --mode no-mistakes --herdr-lab with references/worker-brief.md substituted for {TASK} and the five values filled — verified zero remaining placeholders in the emitted brief
  • bin/fm-herdr-lab.sh name/provision/run refusal paths: default session name, missing fm-lab- prefix, caller-supplied --session, server lifecycle subcommand, leading option
  • Verified every bin/fm-*.sh and CLI flag referenced by the skill/docs exists (bin/fm-brief.sh --help, bin/fm-test-run.sh --help)
  • Checked one-sentence-per-Markdown-line across all four new/changed Markdown surfaces and balanced code fences
  • Rendered docs/upstream-sync.md and the three skill files to HTML with pandoc and captured Chrome screenshots of the catch-up log, the monthly-run line, and the skill head
⚠️ **Document** - 1 info
  • ℹ️ tests/fm-backend-herdr-focus-flash-e2e.test.sh - tests/fm-backend-herdr-focus-flash-e2e.test.sh requires the Herdr lab helper and a real herdr binary but sits in the unclassified family rather than real-herdr-gated, so bin/fm-test-run.sh --family real-herdr-gated --fail-on-gate-skip &#39;herdr not found&#39; never covers it and only the monthly --all run reaches it. Documented as-is in references/herdr-lab.md; the family assignment itself is executable test-map material and out of scope for the documentation phase.
✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

…ation cadence

Encode the captain's 2026-08-27 rulings for the weekly fork catch-up:
keep-list decided by rule and reviewed at the PR, weekly lint plus
colocated tests versus a monthly full suite (next monthly run 2026-10-01),
unrelated breakage filed as follow-up, a fixed worker brief template, and
the isolated Herdr lab setup documented once.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@withally
withally force-pushed the fm/fm-upstream-sync-skill-f2 branch from 46dd4f3 to 4f90bb8 Compare August 27, 2026 13:48
@withally
withally merged commit b19924f into main Aug 27, 2026
12 of 13 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