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
7 changes: 4 additions & 3 deletions .agents/skills/pr-review-conduct/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,10 @@ the pull request in front of you, rather than deciding from a repository propert
must have done.

- **A reviewer that posted a skip notice is available for the asking.** It says it did not review
automatically, which is not the same as not reviewing at all. Comment `@coderabbitai review`, or
Qodo's `/review`, and wait for the result as with any other requested review. The agent driving
the loop posts that comment itself, on the same standing as requesting a review after a push.
automatically, which is not the same as not reviewing at all. Comment the reviewer's documented
review command, such as `@coderabbitai review`, and wait for the result as with any other
requested review. The agent driving the loop posts that comment itself, on the same standing as
requesting a review after a push.
- **A notice naming when the reviewer can next run is a rate limit, and asking does not clear
it.** It reads like the skip notice above and is the opposite case: the trigger returns the same
notice rather than a review, so a loop that keeps asking waits on something no amount of asking
Expand Down
20 changes: 16 additions & 4 deletions .agents/skills/session-handoff/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -308,13 +308,25 @@ It is accepted by `new` and `link`, the two subcommands that write, and by no ot

Exit `0` is success, `1` a refusal the caller can act on, a usage error included, and `2` the
command not having run to an answer, so a refusal and a failure to reach one never share a code. A
repository missing the `handoff` label is a refusal rather than a degraded empty answer, and it
names the command that applies the fleet label set except where the label read filled its window,
which is the one case where the label's absence is unproven rather than established.
fleet repository missing the `handoff` label, one the hub's `registry/repos.json` lists, is a
refusal rather than a degraded empty answer, and it names the command that applies the fleet label
set except where the label read filled its window, which is the one case where the label's absence
is unproven rather than established.

A fork under the registry's owner that the registry does not list, such as one kept for an
upstream contribution per `upstream-contribution-workflow`, can host a chain to keep a session's
state without taking on any fleet configuration. Missing the label there, a read prints a warning
and answers as an empty chain does, and `new` refuses until it is given `--create-label`, which
creates the one `handoff` label, confirms it, and then files the first link. Issues turned off stop
it before any write, naming the command that turns them on. Never apply the fleet label set to such
a fork. A repository under another owner, or an unregistered one of the owner's that is not a fork,
refuses before any write. `new` and `link` refuse both whatever the label state, since a label on
such a repository opens no write there, and that refusal bounds no read.

Creating an issue, commenting on one, closing one, and editing a body are each outward-facing
writes. `new` creates, comments, and closes, the label riding inside the one create call rather than
being a write of its own. `link` edits a body, comments, and closes. Each of them is bound by
being a write of its own, and `new --create-label` adds one write ahead of those, the label itself.
`link` edits a body, comments, and closes. Each of them is bound by
`GOVERNANCE.md` "Repository Boundaries and Write Safety" exactly as any other write is. Point them
at the repository `AGENTS.md` "Session Scope" sends the link to, the one holding the work the next
session resumes, and at no other. `link` also reaches an issue this chain never created, since the
Expand Down
63 changes: 52 additions & 11 deletions .agents/skills/upstream-contribution-workflow/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ name: upstream-contribution-workflow
description: >-
Governs how the maintainer contributes to a third-party repository he does not control (for
example esphome/esphome), distinct from the fleet's own internal branching model: a dirty work
branch on his own fork for the actual work and review iteration, squashed once clean to a second
branch that carries only the intended minimal history, that clean branch opened as the PR
against the upstream repo, and reviewer feedback applied to the dirty branch first, then
re-squashed into the clean one. Use this whenever about to open a pull request against a
repository outside the ptr727 fleet, whenever forking a third-party project to contribute a fix
or feature, whenever an upstream reviewer requests changes on a PR opened this way, and whenever
branch on his own fork for the actual work and review iteration, its fork-internal PR kept open
and never merged, squashed once clean to a second branch that carries only the intended minimal
history, that clean branch opened as the PR against the upstream repo, and reviewer feedback
applied to the dirty branch first, then re-squashed into the clean one. Use this whenever about
to open a pull request against a repository outside the ptr727 fleet, whenever forking a
third-party project to contribute a fix or feature, whenever an upstream reviewer requests
changes on a PR opened this way, whenever a fork-internal iteration PR looks ready to merge or
close, whenever the upstream base branch moves under a contribution in flight, and whenever
deciding which issue or PR template to use for a third-party repository. Triggers regardless of
the target repo's own type or workflow model, since this skill is about the shape of a
contribution to someone else's repo, not the target repo's own internal conventions, which this
Expand All @@ -29,15 +31,24 @@ fleet's internal model so the two are never conflated.

## The two-branch shape

1. **Fork the upstream repo**, if not already forked.
1. **Fork the upstream repo**, if not already forked. The fork's copy of the upstream base branch
(`main`, `dev`, whichever upstream PRs target) is the **mirror branch**. It moves only by
syncing from upstream, and nothing of the maintainer's is ever merged into it.
2. **Do the actual work on a dirty work branch**, on the maintainer's own fork. This branch is
allowed to be messy: false starts, fixup commits, back-and-forth in response to review, whatever
the real work looks like while it's happening. Open a PR from this branch into a branch on the
maintainer's **own fork** (not upstream), so all the iteration happens there, visible and
reviewable, without touching the upstream repo at all.
the real work looks like while it's happening. Open a PR from this branch into the mirror
branch on the maintainer's **own fork** (not upstream), so all the iteration happens there,
visible and reviewable by bots and the maintainer, without touching the upstream repo at all.
**That fork-internal PR is the iteration record, never a merge candidate.** It stays open for
the life of the contribution, however green it gets, and is never merged, per "The iteration PR
is never merged" below.
3. **Once the dirty branch is clean and the change is ready, squash it to a second branch** that
carries only the intended, minimal commit history, one commit (or a small, deliberate set) that
states what the change is, not how it was arrived at.
states what the change is, not how it was arrived at. Cut that branch fresh from the mirror
branch's current tip and squash the dirty branch's changes onto it. It is a plain branch, not a
PR on the fork, since the review it needs already happened on the iteration PR. One dirty branch
may feed several clean branches when upstream wants the change split, each carrying only its
own slice.
4. **Open the PR against the upstream repo from that second, clean branch.** This is the only
branch upstream ever sees. An upstream draft may be opened only after that clean presentation
branch exists and is published. When more preparation is needed, continue on the dirty branch,
Expand All @@ -63,6 +74,29 @@ fleet's internal model so the two are never conflated.
Never reverse this: never iterate directly on the branch that's open against upstream, and never
skip the squash step because the dirty branch "looks clean enough."

## The iteration PR is never merged

Merging the iteration PR into the mirror branch looks like the natural finish once it is green, and
it breaks the fork two ways. The mirror branch then carries a commit upstream does not, so it stops
being a mirror: it can no longer be fast-forwarded from upstream, every later sync has to merge
upstream into the maintainer's own change, and any sync touching the same lines conflicts. And the
iteration PR is the place where upstream drift is absorbed and its fallout fixed before the
upstream PR has to absorb the same drift, so merging or closing it removes that place.

When the upstream base moves, sync the mirror branch from upstream, merge the mirror branch into
the dirty branch, and fix whatever breaks in the iteration PR. That is a merge rather than a rebase,
since the dirty branch is append-only and is never force-pushed. Then re-squash onto the new mirror
tip whenever the clean branch needs to follow, per step 5.

For example, the fork's mirror branch and upstream both sit at commit `A`, with the iteration PR
from `work/x` into the mirror branch green. Upstream advances to `B`. The fork syncs its mirror
branch to `B`, merges `B` into `work/x`, and fixes the breakage in the iteration PR. Had `work/x`
been merged into the mirror branch at `A`, the mirror branch could not have fast-forwarded to `B`.

The contribution ends when upstream merges or declines the upstream PR. Only then close the
iteration PR, unmerged, and delete the dirty and clean branches. A merged change then reaches the
mirror branch through the next sync from upstream, the same way anyone else's change does.

## Use the upstream repo's own conventions, not the fleet's

Always use the upstream repo's own issue and PR templates, its own contribution guidelines, and
Expand All @@ -82,3 +116,10 @@ write-safety rules (never write to a repository outside explicit authorization,
GitHub id) also still apply in full. A fork the maintainer owns is within scope to push to, and
the upstream repository itself is written to only through the PR the maintainer explicitly asked
for.

The fork is not a fleet repository. It carries none of the fleet's instruction files or repository
settings, and a resync or the fleet label set is never applied to it. A session working
the contribution can still keep its state in the `session-handoff` chain on the fork. That needs
issues turned on and the one `handoff` label, which the hub's `scripts/handoff.py new
--create-label` creates on a fork under the fleet's owner, and nothing else of the fleet's
configuration.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7ab7baf90da9b766
0331a2ae5b800214
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8dfe7946b9693ac7
71ea890bf0050608
Original file line number Diff line number Diff line change
@@ -1 +1 @@
f98c8047451b8448
1436e605eb7e114f
7 changes: 4 additions & 3 deletions .claude-plugin/fleet-skills/skills/pr-review-conduct/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,10 @@ the pull request in front of you, rather than deciding from a repository propert
must have done.

- **A reviewer that posted a skip notice is available for the asking.** It says it did not review
automatically, which is not the same as not reviewing at all. Comment `@coderabbitai review`, or
Qodo's `/review`, and wait for the result as with any other requested review. The agent driving
the loop posts that comment itself, on the same standing as requesting a review after a push.
automatically, which is not the same as not reviewing at all. Comment the reviewer's documented
review command, such as `@coderabbitai review`, and wait for the result as with any other
requested review. The agent driving the loop posts that comment itself, on the same standing as
requesting a review after a push.
- **A notice naming when the reviewer can next run is a rate limit, and asking does not clear
it.** It reads like the skip notice above and is the opposite case: the trigger returns the same
notice rather than a review, so a loop that keeps asking waits on something no amount of asking
Expand Down
20 changes: 16 additions & 4 deletions .claude-plugin/fleet-skills/skills/session-handoff/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -308,13 +308,25 @@ It is accepted by `new` and `link`, the two subcommands that write, and by no ot

Exit `0` is success, `1` a refusal the caller can act on, a usage error included, and `2` the
command not having run to an answer, so a refusal and a failure to reach one never share a code. A
repository missing the `handoff` label is a refusal rather than a degraded empty answer, and it
names the command that applies the fleet label set except where the label read filled its window,
which is the one case where the label's absence is unproven rather than established.
fleet repository missing the `handoff` label, one the hub's `registry/repos.json` lists, is a
refusal rather than a degraded empty answer, and it names the command that applies the fleet label
set except where the label read filled its window, which is the one case where the label's absence
is unproven rather than established.

A fork under the registry's owner that the registry does not list, such as one kept for an
upstream contribution per `upstream-contribution-workflow`, can host a chain to keep a session's
state without taking on any fleet configuration. Missing the label there, a read prints a warning
and answers as an empty chain does, and `new` refuses until it is given `--create-label`, which
creates the one `handoff` label, confirms it, and then files the first link. Issues turned off stop
it before any write, naming the command that turns them on. Never apply the fleet label set to such
a fork. A repository under another owner, or an unregistered one of the owner's that is not a fork,
refuses before any write. `new` and `link` refuse both whatever the label state, since a label on
such a repository opens no write there, and that refusal bounds no read.

Creating an issue, commenting on one, closing one, and editing a body are each outward-facing
writes. `new` creates, comments, and closes, the label riding inside the one create call rather than
being a write of its own. `link` edits a body, comments, and closes. Each of them is bound by
being a write of its own, and `new --create-label` adds one write ahead of those, the label itself.
`link` edits a body, comments, and closes. Each of them is bound by
`GOVERNANCE.md` "Repository Boundaries and Write Safety" exactly as any other write is. Point them
at the repository `AGENTS.md` "Session Scope" sends the link to, the one holding the work the next
session resumes, and at no other. `link` also reaches an issue this chain never created, since the
Expand Down
Loading
Loading