Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .agents/skills/updatefirstmate/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ This touches only the firstmate repo and its own worktrees, never anything under
bin/fm-update.sh
```
It fast-forwards this firstmate repo's default branch from origin, then updates every registered local or remote secondmate home through its placement-specific guarded path.
Origin is the only source it advances from, so in a fork, upstream work reaches homes only after it has landed on the fork's own default branch; CONTRIBUTING.md's "Fork remotes and upstream sync" owns that deliberate sync procedure.
It prints one status line per target (`updated <old>..<new>` / `already current` / `skipped: <reason>`), followed by two action lines that tell you exactly what to do next:
- `reread-firstmate: yes|no`
- `nudge-secondmates: fm-<id>...|none`
Expand Down
30 changes: 28 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
Thanks for wanting to contribute.
One rule up front:

**Human-authored pull requests targeting `main` must be raised through [`no-mistakes`](https://github.com/kunchenguid/no-mistakes).**
**Human-authored pull requests targeting the upstream repository's `main` must be raised through [`no-mistakes`](https://github.com/kunchenguid/no-mistakes).**
We require this to reduce the maintainer's burden of reviewing and merging contributions.
The `Require no-mistakes` check is scoped to the upstream repository, so a downstream fork sets its own delivery rigor per change and legitimately raises direct pull requests on its own `main`.

`no-mistakes` puts a local git proxy in front of your real remote.
Pushing through it runs an AI-driven review/test/lint pipeline in an isolated worktree, forwards the push upstream only after every check passes, and opens a clean PR automatically.
Expand All @@ -16,7 +17,8 @@ GitHub Actions and Dependabot are exempt so their automation keeps working, but

## Workflow

1. Fork the repo, then clone the parent repo or set your local `origin` back to the parent (`git@github.com:kunchenguid/firstmate.git`).
1. Fork the repo, then clone your fork so `origin` is the repository you can push to.
Add the upstream repository as a separate read-only remote with `git remote add upstream https://github.com/kunchenguid/firstmate`.
2. Create a branch and make your changes.
3. Initialize the gate with your fork as the push target: `no-mistakes init --fork-url git@github.com:<you>/firstmate.git` (contributing to firstmate requires **no-mistakes v1.46.0+** for structured attestation; without a fork, plain `no-mistakes init` still works for maintainers with push access).
4. Commit your changes.
Expand All @@ -32,6 +34,30 @@ GitHub Actions and Dependabot are exempt so their automation keeps working, but

See the [no-mistakes quick start](https://kunchenguid.github.io/no-mistakes/start-here/quick-start/) for the full first-run walkthrough.

## Fork remotes and upstream sync

A downstream fork keeps two remotes with different rights, and every contributor and agent in that fork depends on the distinction.
`origin` is the fork you can push to, and it is the only repository that receives branches, pull requests, and merges.
`upstream` is the parent repository, and it is read-only: never push to it, and never open a pull request against it from a fork that is operating independently.
Confirm which one you are about to write to with `git remote get-url origin` before any push or pull-request creation, because the two remotes differ only by owner in the URL.

Firstmate homes self-update by fast-forwarding from `origin`, which `bin/fm-update.sh` and the [`updatefirstmate`](.agents/skills/updatefirstmate/SKILL.md) skill own.
That is the reason a fork cannot pick up upstream work simply by fetching it: the work has to reach the fork's own default branch first.
Sync the fork deliberately, as its own reviewable change:

1. `git fetch upstream` and start a branch from the fork's current `main`.
2. `git merge upstream/main` on that branch, producing a merge commit whose first parent is the fork's `main` and whose second parent is the upstream commit being synced.
Merge rather than rebase, so every home can fast-forward onto the result instead of being asked to reconcile rewritten history.
3. Resolve conflicts with evidence rather than preference, and keep a local fix whenever it still covers a case the upstream change does not.
4. Run the repo's gates on the merge result, then push the branch to `origin` and open the pull request on the fork.
5. Land it with the configured merge authority, after which every home fast-forwards to it in the ordinary way.

After any remote retarget, re-run `no-mistakes init` and inspect the gate mirror's own `git remote -v` before trusting the next pipeline run.
The pipeline rebases and opens pull requests from that mirror's `origin`, not from the checkout you are working in, so a mirror still pointing at the old remote sends work to the wrong repository while every local check still looks correct.

Treehouse pool worktrees are `git worktree` entries that share the primary checkout's object store and configuration, so they inherit its remotes rather than defining their own.
Correcting the remotes once in the primary checkout is therefore what makes every existing and future pool worktree correct.

## Repo conventions

- This repo is a template for running a firstmate orchestrator agent.
Expand Down
4 changes: 4 additions & 0 deletions docs/documentation-audiences.json
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,10 @@
"path": "docs/verification/runtime-backends.md",
"audience": "maintainer-verification"
},
{
"path": "docs/verification/self-update.md",
"audience": "maintainer-verification"
},
{
"path": "docs/verification/stow-memory.md",
"audience": "maintainer-verification"
Expand Down
53 changes: 53 additions & 0 deletions docs/verification/self-update.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Self-update verification

Active evidence that `/updatefirstmate` advances a firstmate home from its own `origin`.
The procedure this evidence exercises is owned by [`updatefirstmate`](../../.agents/skills/updatefirstmate/SKILL.md) for the agent path and by [`CONTRIBUTING.md`](../../CONTRIBUTING.md) ("Fork remotes and upstream sync") for the maintainer path.

## Origin is the only update source

Verified 2026-09-01 against `cm-maple7/firstmate` with a throwaway home cloned from the fork and deliberately set one commit behind its default branch.

Setup:

```sh
git clone https://github.com/cm-maple7/firstmate.git "$HOME_DIR"
git -C "$HOME_DIR" remote -v
origin https://github.com/cm-maple7/firstmate.git (fetch)
origin https://github.com/cm-maple7/firstmate.git (push)

git -C "$HOME_DIR" reset --hard HEAD~1
git -C "$HOME_DIR" log --oneline -1
d77251e fix(bin): absorb background-run stale wakes and trust declared pauses over ci-monitoring (#2)
```

Run:

```sh
FM_ROOT_OVERRIDE="$HOME_DIR" FM_HOME="$HOME_DIR" bash bin/fm-update.sh
firstmate: updated d77251e..6aa4beb (instructions changed: AGENTS.md, bin, .agents/skills)
reread-firstmate: yes
nudge-secondmates: none

git -C "$HOME_DIR" log --oneline -1
6aa4beb Merge pull request #5 from cm-maple7/fm/fm-fork-as-origin-followthrough
```

The home advanced by fast-forward to the fork's default branch, and the updater reported the tracked instruction surface as changed so the caller re-reads `AGENTS.md`.
`6aa4beb` is the merge that landed the upstream sync on the fork, so this run also demonstrates the full chain: upstream work reaches a home only after landing on the fork's own default branch.

Refresh this record by repeating the three commands above whenever the update path or the fork's remote layout changes.

## Pool worktrees inherit the primary checkout's remotes

Verified 2026-09-01 on the same fork.
Treehouse pool worktrees are `git worktree` entries sharing the primary checkout's git directory, so they read its remote configuration rather than defining their own.

```sh
git -C "$POOL_WORKTREE" rev-parse --git-common-dir
/Users/charlie/src/firstmate/.git

git -C "$POOL_WORKTREE" remote get-url origin
https://github.com/cm-maple7/firstmate.git
```

Correcting the remotes once in the primary checkout is therefore what makes every existing and future pool worktree correct; no per-worktree repair step exists or is needed.
Loading