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
4 changes: 2 additions & 2 deletions .agents/skills/agent-conduct/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,9 @@ Where a lesson lands, when it earns a mechanical hook, and where work blocked on

- **Durable knowledge lives in the committed docs, not in agent memory.** Anything a future agent must honor (a rule, a contract, a hard-won gotcha, a pattern worth repeating or one to avoid) belongs in a committed governance file (`GOVERNANCE.md` for a cross-cutting rule, `AGENTS.md`, `CODESTYLE.md`, `WORKFLOW.md`, or a committed backlog the repository already keeps). Agent memory does not survive a new session, a new machine, or a new environment, so it holds only environment-specific nuance and in-flight session state, never anything whose loss on reset would matter. A durable lesson left only in memory is lost to the next agent.
- **Keep the governance current as you work.** When work surfaces something durable (a rule worth enforcing, a recurring gotcha, a positive pattern to repeat, a negative one to design out), record it in the governance docs as part of that change, rather than leaving it in a local note or routing around it with a one-off workaround. Where the governing doc is carried from a template this repo cannot edit directly, propose the change upstream rather than patching the local copy. A local patch leaves every sibling repo with the same trap. Governance is not static: it improves by agents folding good patterns in and designing bad ones out.
- **A blocker filed in another repository is recorded in the repository whose work it blocks.** The binding moment is the one where the upstream issue is filed or, where it already exists, found, because that session is the one that knows what stopped and why. It owes a second issue in the repository that is waiting rather than only the first, and where the upstream issue already exists the local issue names that one and no second upstream issue is filed. The local issue states what this repository cannot do and why, in its own terms rather than as a pointer to read elsewhere, since a reader who has to open the upstream issue to learn whether it affects them opens every one of them. The local issue names the upstream one as its blocker, carries the `blocked` label, and carries whatever labels its own work would carry anyway. A comment on the upstream issue then names the local one in return, a comment rather than an edit to the body because a second repository may join the same blocker later and because the body is often not this session's to rewrite. That order, the upstream issue and then the local issue and then the backlink comment, leaves a partial failure as a record naming its blocker rather than as a blocker naming a record nobody wrote. **A handoff does not do this job.** It carries the blockers a round met, and it belongs to one track and closes with its successor, where the wait outlives every session that met it and belongs in the backlog the whole repository reads.
- **A blocker filed in another repository is recorded in the repository whose work it blocks.** The binding moment is the one where the upstream issue is filed or, where it already exists, found, because that session is the one that knows what stopped and why. It owes a second issue in the repository that is waiting rather than only the first, and where the upstream issue already exists the local issue names that one and no second upstream issue is filed. The local issue states what this repository cannot do and why, in its own terms rather than as a pointer to read elsewhere, since a reader who has to open the upstream issue to learn whether it affects them opens every one of them. The local issue names the upstream one as its blocker, carries the `blocked` label, and carries whatever labels its own work would carry anyway. A comment on the upstream issue then names the local one in return, a comment rather than an edit to the body because a second repository may join the same blocker later and because the body is often not this session's to rewrite. That order, the upstream issue and then the local issue and then the backlink comment, leaves a partial failure as a record naming its blocker rather than as a blocker naming a record nobody wrote. **A handoff does not do this job.** It carries the blockers a round met, but it belongs to one track and closes when that track's work is done. The wait can outlive that track, so it belongs in the backlog the whole repository reads.
- **The blocker record is written under the ordinary write rules, and the label on it is taken off deliberately.** Filing an issue and commenting on another are state-changing calls, so "Repository Boundaries and Write Safety" binds each of them exactly as it binds any other write, which keeps the upstream issue inside this owner and makes a blocker under a different owner a matter of explicit permission rather than of this rule. The `blocked` label is what every reader of this record selects on, so a repository not carrying it cannot host one until the fleet label set is applied there, which is a change to that repository's configuration rather than anything this rule writes, and a session that finds it missing reports that. The label comes off when the blocker clears, and the session closing the upstream issue is best placed to take it off, since the backlink comments naming every waiting repository are on the issue it is closing, while any later session that finds it cleared takes it off instead. A fix can land well before either of those, so the label lags the fix rather than tracking it, which is why a session meeting a `blocked` issue reads the state of the issue that issue's body names rather than the label. The local issue stays open when the label comes off, because the work it records still has to be done and is ordinary backlog from that moment on.
- **A handoff parked on a maintainer decision carries the `blocked` label too.** Its blocker is a `decision` issue in this same repository rather than an issue elsewhere, and the parking comment on the handoff names it. A reader reads the named issue rather than the label, and the blocker clears when that issue loses its `decision` label. Unlike a cross-repository blocker, a session finding it cleared does not take the label off. It comes off only when a session hands the link back to be worked, so a loop running meanwhile never takes a link a present maintainer is still working.
- **A handoff parked on a maintainer decision carries the `blocked` label too.** Its blocker is a `decision` issue in this same repository rather than an issue elsewhere, and the parking comment on the handoff names it. A reader reads the named issue rather than the label, and the blocker clears when that issue loses its `decision` label. Unlike a cross-repository blocker, a session finding it cleared does not take the label off. It comes off only once a session writes the next round, so a running loop never takes a handoff a present maintainer is still working.
- **A durable rule earns a mechanical hook only where a hook can actually decide it, otherwise it stays prose.** The conditions below must hold together, not any one alone. The failure recurs even after the governing prose was demonstrably read and understood, so it is not a discovery or loading problem a structural fix (getting the rule into context at all) would already solve. The triggering shape is decidable from the tool call's own text, arguments, and working directory alone, with no semantic or contextual judgment required. And the failure is destructive or hard to reverse rather than a quality miss. A worktree-isolation lapse met all of them (it recurred under prose the agent had already read, "is this command's target a primary checkout" is a plain directory comparison, and the harm is another task's swept or reverted work), so it was promoted to a `gh-write-guard` hook rule. A skill's own trigger going unread by the session at all, by contrast, is a loading problem, fixed by getting the rule into context (the `CLAUDE.md` importing `AGENTS.md`), not by a hook. And "was this review finding actually evidence-backed" fails the second condition outright: a hook sees only the command text, never the judgment call itself, so it can only ever nag, not decide, and that class of rule stays prose and a chained Skill trigger. Those conditions gate promotion to a **host** hook, the involuntary layer that fires in every session under the maintainer's own credentials and that only the maintainer can grant an exemption from, which is why the bar there is destructive harm. A **committed** hook in the repository's own tree is a third layer between prose and that one, and it is earned on weaker grounds: it is opt-in per clone, visible in the tree, bypassable by design, and it therefore fits a rule whose harm is a quality miss rather than a destruction. The second condition still binds it, since a hook that cannot decide its own trigger is a hook that nags, so what earns the layer is finding the decidable half of a rule whose other half is judgment. The local-review rule under `GOVERNANCE.md` "Verification Discipline" is the worked example: whether a review's findings were rightly disposed of is judgment no hook can decide and stays prose, while whether a review pass ran over exactly the content being pushed is a receipt comparison, which the hub's own `.husky/pre-push` decides.

`GOVERNANCE.md` "Durable Knowledge and Self-Improvement" keeps the full rules, and the `agent-conduct` Skill at `.agents/skills/agent-conduct/SKILL.md` in the hub, not a repo-relative link since that path is hub-local and not carried into every fleet repo, carries it whole as a generated include and surfaces it at its decision moments.
Expand Down
4 changes: 2 additions & 2 deletions .agents/skills/backlog-burndown/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -557,8 +557,8 @@ A rule, a Skill, or a brief names a model tier, never a model. A model release i

Each cell is the name that tool's subagent dispatch takes, which follows the latest model of its family. A tool with no row here, or one that cannot name a model per subagent, runs every tier at the session's own model.

- **A tier resolves only through this table.** A word such as "frontier", "strongest", or "most capable" never resolves to `highest`. The industry's "frontier model" is the opposite of what this tier means here. A session that cannot see this table names no model rather than guessing one, so the subagent runs at the session's own model.
- **An orchestrating seat runs at `frontier` and names a tier on every dispatch.** It defaults a subagent to `frontier`, and picks `standard` or `bulk` deliberately for execution or mechanical work. A dispatch that names no model inherits whatever the session runs on, which is a choice nobody made.
- **A tier resolves only through this table.** A word such as "frontier", "strongest", or "most capable" never resolves to `highest`. The industry's "frontier model" is the opposite of what this tier means here. A session that cannot see this table names no model rather than guessing one.
- **An orchestrating seat runs at `frontier` and names a tier on every dispatch.** It defaults a subagent to `frontier`, and picks `standard` or `bulk` deliberately for execution or mechanical work.

<!-- /include -->

Expand Down
4 changes: 2 additions & 2 deletions .agents/skills/local-strict-review/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,8 @@ A rule, a Skill, or a brief names a model tier, never a model. A model release i

Each cell is the name that tool's subagent dispatch takes, which follows the latest model of its family. A tool with no row here, or one that cannot name a model per subagent, runs every tier at the session's own model.

- **A tier resolves only through this table.** A word such as "frontier", "strongest", or "most capable" never resolves to `highest`. The industry's "frontier model" is the opposite of what this tier means here. A session that cannot see this table names no model rather than guessing one, so the subagent runs at the session's own model.
- **An orchestrating seat runs at `frontier` and names a tier on every dispatch.** It defaults a subagent to `frontier`, and picks `standard` or `bulk` deliberately for execution or mechanical work. A dispatch that names no model inherits whatever the session runs on, which is a choice nobody made.
- **A tier resolves only through this table.** A word such as "frontier", "strongest", or "most capable" never resolves to `highest`. The industry's "frontier model" is the opposite of what this tier means here. A session that cannot see this table names no model rather than guessing one.
- **An orchestrating seat runs at `frontier` and names a tier on every dispatch.** It defaults a subagent to `frontier`, and picks `standard` or `bulk` deliberately for execution or mechanical work.

<!-- /include -->

Expand Down
20 changes: 14 additions & 6 deletions .agents/skills/pr-review-conduct/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,12 @@ visible comments, routinely still carries a finding nobody has answered. Treatin
`refusal=QUOTA` or `refusal=ERROR`, the pull request's newest Copilot review being an
account-quota refusal or an error refusal read as a possible quota hit, on this head or an
earlier one, is the one nothing the loop does clears, which is the case "Which Reviewers a
Repository Actually Has" below states. `status=COPILOT_QUOTA_EXHAUSTED_REPO_WIDE` is that same
Repository Actually Has" below states. An error refusal whose `RUN LOG READING` line says
transient is the exception. `wait` re-requests it once and exits `30` while that request is
pending. A second error refusal in a row, or a re-request made with no round answering it,
reads as possible quota. A held head exits `41` as `COPILOT_ERROR_TRANSIENT`, its request
waiting on `--request`.
`status=COPILOT_QUOTA_EXHAUSTED_REPO_WIDE` is that same
account state read from the reviewer's activity elsewhere when this head carries none of its
own, and a refusal holding across several heads with no cause its body names reaches it the
slower way. That exit is `wait`'s alone: `status` exits 0 over a refusal, carrying it as
Expand Down Expand Up @@ -229,8 +234,9 @@ must have done.
encountered an error, which is what the
weekly rate limit posts. Each covers no head, so the gate stays unsatisfied, and nothing the
loop does clears it, since re-requesting returns it again and spends quota doing so. Where the
reviewer's run log names a reset time `pr_review.py` reports it. Each refusal goes to the
maintainer, rather than into a wait.
reviewer's run log names a reset time `pr_review.py` reports it. Where it names a transient
fetch failure instead, `pr_review.py wait` re-requests once. Every other refusal, a repeat of
that one included, goes to the maintainer rather than into a wait.

Where a reviewer's behavior still surprises you after reading what it posted, the hub's
`docs/pr-reviewer-reference.md` records what each one does, what shapes it, and which repositories
Expand Down Expand Up @@ -267,13 +273,15 @@ Run `local-strict-review` against the branch's current diff before every push th
deserves a Copilot round anyway. `wait` also skips the request where
a review already covers the head, where the answer came outside a formal review, where it detects
drift, under a quota or error refusal, and where something is already in the request set, which
is the condition the recovery below clears. Requesting in the pull request UI is the maintainer's
route rather than this loop's.
is the condition the recovery below clears. An error refusal whose run log reads transient is
the exception, owed one re-request per Merge Gate item 2. Requesting in the pull request UI is
the maintainer's route rather than this loop's.
4. Run a bounded `uv run --no-project --script scripts/pr_review.py wait <number> --repo <owner>/<repo>` in a background process and read its terminal output.
A completed review raising **no findings** is a valid terminal outcome, so do not re-trigger it
or read silence as a missing review. A review whose body says it declined to review is the one
exception, and it is terminal the other way. Nothing follows it, and re-requesting the same
head only repeats the decline.
head only repeats the decline. A transient error refusal under Merge Gate item 2 is owed its one
re-request first.
5. Triage findings (see below).
6. Apply fixes or write a rationale for declines.
7. Reply to each thread, and resolve what was addressed and what was declined on evidence the
Expand Down
4 changes: 2 additions & 2 deletions .agents/skills/unattended-handoff/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,8 @@ A rule, a Skill, or a brief names a model tier, never a model. A model release i

Each cell is the name that tool's subagent dispatch takes, which follows the latest model of its family. A tool with no row here, or one that cannot name a model per subagent, runs every tier at the session's own model.

- **A tier resolves only through this table.** A word such as "frontier", "strongest", or "most capable" never resolves to `highest`. The industry's "frontier model" is the opposite of what this tier means here. A session that cannot see this table names no model rather than guessing one, so the subagent runs at the session's own model.
- **An orchestrating seat runs at `frontier` and names a tier on every dispatch.** It defaults a subagent to `frontier`, and picks `standard` or `bulk` deliberately for execution or mechanical work. A dispatch that names no model inherits whatever the session runs on, which is a choice nobody made.
- **A tier resolves only through this table.** A word such as "frontier", "strongest", or "most capable" never resolves to `highest`. The industry's "frontier model" is the opposite of what this tier means here. A session that cannot see this table names no model rather than guessing one.
- **An orchestrating seat runs at `frontier` and names a tier on every dispatch.** It defaults a subagent to `frontier`, and picks `standard` or `bulk` deliberately for execution or mechanical work.

<!-- /include -->

Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/fleet-skills/.source-digests/agent-conduct
Original file line number Diff line number Diff line change
@@ -1 +1 @@
35cbb6bb71550038
044a3bbb4da33402
Original file line number Diff line number Diff line change
@@ -1 +1 @@
e1af7dadfb2070a2
28fb141c0bacd468
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9dc270f21b0302cd
5e933f569ef7e7ac
Original file line number Diff line number Diff line change
@@ -1 +1 @@
184af41cfc570242
8743445c185bcca7
Original file line number Diff line number Diff line change
@@ -1 +1 @@
eddb00a5222e6b31
5bbb7f15ec4e23c4
Loading
Loading