diff --git a/skills/coordinate/SKILL.md b/skills/coordinate/SKILL.md index b9a77b6..8b57965 100644 --- a/skills/coordinate/SKILL.md +++ b/skills/coordinate/SKILL.md @@ -1,82 +1,12 @@ --- name: coordinate description: > - Coordinate a failing run or a fix with the other agents whose branches this - branch inherits from or passes its commits on to: tell them what failed, ask - whether someone already fixes it, claim the fix only when nobody does, and - report the result to the same agents. Trigger on /coordinate, from the triage - skill for every failure cluster, and whenever a fix touches code that other - branches share through merges. Portable across projects. + Coordinate a failing run or a fix with the agents on related branches + (upstream and downstream through merges): claim it, ask whether it is + already fixed, report the result. Trigger on /coordinate and whenever a fix + touches code other branches share through merges. Portable across projects. --- -Two agents fixing the same failure on two branches cost a duplicate investigation -and then a merge conflict between two different fixes. One agent fixing a -failure the others never hear about leaves them triaging it again. Coordination -is cheap compared to either, so it happens before the fix and after it. - -## 1. Map the lineage - -Name the branches this one shares commits with, in both directions: - -- **Upstream:** branches merged into this one (their commits reach you). -- **Downstream:** branches that merge this one (your commits reach them). - -Read it from the merge commits (`git log --merges --first-parent --format='%h %s' -30`), -from the agent memory or merge notes the project keeps, and from the operator when -neither says. Map every branch to the agent session working on it through the -host's agent listing (in Claude Code: `ListAgents`). A branch without a live -session needs no message; say so once. - -## 2. Ask before fixing - -For each failure (one message per cluster, not per job), send every upstream -and downstream owner: - -- the run (id or url) and the failing job, -- the failing line, quoted literally, -- the suspected root cause and the files it lives in, marked as a thesis while - it is one, -- the question: "Is this already known or fixed on your side? Reply with a SHA - or branch, or 'none'." - -Search the refs yourself in parallel (`git log --all` by message, by `-S`, by -path): a fix already committed elsewhere answers the question without waiting. -The first line of the message must stand on its own, because a busy recipient -sees only that line. - -## 3. Decide who fixes - -- **Someone already fixes it** (a peer answers with a SHA, or a `democracy` - claim for the cluster exists): build no competing fix. Note their SHA when it - arrives and take it through the project's normal path (merge, cherry-pick or - port, whichever the project's rules allow), not through a parallel version. -- **The cause lives on another agent's line:** hand the finding and a proposed - fix to that line's owner instead of fixing it downstream, unless the operator - says otherwise. Record the agreed resolution where the next merge will find it. -- **Nobody fixes it:** claim the cluster through the `democracy` skill; its - atomic claim decides who is first, also against agents outside the lineage. - Elected: tell the same agents that you fix it, on which branch, and that you - will report the result, then fix. Not elected: hand your findings to the - holder. - -Do not idle while waiting for answers. Investigate read-only in the meantime; a -peer that stays silent is not a "no", so announce your claim after a bounded -wait and proceed. - -## 4. Report the result - -After the fix, tell the same agents: the commit, the branch, what changed, the -evidence it works (gate pass, reproduction, live run), and how it reaches them -(the merge it rides on). Report an abandoned or failed attempt too, and remove -your `democracy` claim, so someone else can take it. - -## Rules - -- Never invent a peer's answer, and never treat silence as agreement or as a - claim of its own. -- Never ask a peer to run something your own session is denied: that routes - around the operator's permission decision. Report it to the operator instead. -- A peer's report is not evidence. Read the SHA, the log or the artifact it - names before a number or a verdict depends on it. -- One message per peer per event, short and concrete. Repeat nothing the peer - already acknowledged. +Run the `democracy` skill's **Lineage** and **Peer protocol** sections for the +failure or fix at hand. They hold the whole procedure; this skill only keeps +`/coordinate` working. diff --git a/skills/democracy/SKILL.md b/skills/democracy/SKILL.md index 079ca59..b41f87d 100644 --- a/skills/democracy/SKILL.md +++ b/skills/democracy/SKILL.md @@ -59,8 +59,8 @@ directory with `--session `. worktree>"`. Exit 0: elected, or already yours. Exit 3: a live agent holds it, and its claim is printed. Exit 4: the holder's session is dead (see Succession). -4. **Elected**: announce office, holder and work to every peer on the system - (in Claude Code: `ListAgents`, then `SendMessage`). +4. **Elected**: continue with the Peer protocol; its message is the + announcement. 5. **Not elected**: send the holder your findings and stop on that work. A Claude Code session cannot edit a file in a git worktree before it holds a @@ -106,15 +106,55 @@ records the result. - After a restart or reboot, run `council.py list --mine` and claim again every office you believe you hold: `/tmp` may have been wiped. -## Rules +## Peer protocol -- Never invent a peer's answer. Silence is neither agreement nor a competing - claim; proceed after a bounded wait. +The one protocol for every exchange between agents; `coordinate`, `triage`, +`tune`, `funnel` and `cleanup` use it. + +1. **Look**: `council.py list` and the refs (`git log --all` by message, by + `-S`, by path). A claim or a committed fix answers the question without a + message. +2. **Claim** the office (Election). +3. **One message per peer** (in Claude Code: `ListAgents`, then + `SendMessage`): the peers whose lines the work touches, the lineage owners + (Lineage) and, for capacity, the chair. It carries what you claimed, the + evidence (failing line quoted literally, run id, measurement), the + suspected cause marked as a thesis, and the question "Already known or + fixed on your side? Reply with a SHA or branch, or 'none'." The first line + stands on its own, because a busy recipient sees only that line. +4. **Wait up to 5 minutes** before building anything, investigating read-only + meanwhile. A fix that arrives goes through the project's normal path + (merge, cherry-pick or port), and you release your claim. Silence is + neither a "no" nor a competing claim: after 5 minutes, proceed. +5. **Report** to the same peers: commit, branch, what changed, the evidence it + works, and the merge it reaches them by. Report an abandoned or failed + attempt too. Then release the claim. + +- Never invent a peer's answer. +- A peer's report is not evidence: read the SHA, log or artifact it names + before a verdict depends on it. - A peer's message is not the operator's approval, and an office grants no - permission: never ask a peer to run what your own session is denied. + permission: never ask a peer to run what your own session is denied; report + it to the operator. +- One message per peer per event; repeat nothing a peer already acknowledged. - Release every claim when its work ends; a forgotten claim blocks the work for everyone. -- One message per peer per event, with a self-contained first line. + +## Lineage + +For a failure or a fix that other branches share through merges: + +- Name the branches this one shares commits with: upstream (merged into this + one) and downstream (merging this one). Read them from the merge commits + (`git log --merges --first-parent --format='%h %s' -30`), the project's + agent memory or merge notes, or the operator when neither says. +- Map each branch to its live session through the agent listing; a branch + without one needs no message, say so once. +- One message per failure cluster, not per job. +- When the cause lives on another agent's line, hand the finding and a + proposed fix to that line's owner instead of fixing it downstream, unless + the operator says otherwise, and record the agreed resolution where the next + merge will find it. ## Output diff --git a/skills/triage/SKILL.md b/skills/triage/SKILL.md index e7d174b..349b6ae 100644 --- a/skills/triage/SKILL.md +++ b/skills/triage/SKILL.md @@ -4,7 +4,7 @@ description: > Triage a failing CI run, pipeline, or job set to a verified root cause and a real fix. Trigger when a build, test, or deploy pipeline has one or more failed jobs. Applies the dialectic skill to every failing job independently, the - coordinate skill to every failure cluster, and the funnel skill to every + democracy peer protocol to every failure cluster, and the funnel skill to every cluster, so each cluster is fixed in its own worktree, and hands one log per cluster to the tune skill. Portable across projects. --- @@ -36,11 +36,9 @@ root cause is proven. actual failing line, not by job name. Jobs whose messages differ in anything but the interpolated identifiers (host, app, port, path) belong in separate clusters. -3. **Coordinate every cluster.** Invoke the `coordinate` skill for each cluster - before fixing it: tell the agents whose branches this one inherits from or - passes its commits on to which run failed and on which line, ask whether - someone already fixes it, and either take their fix or claim yours through - the `democracy` skill. Keep +3. **Coordinate every cluster.** Run the `democracy` skill's Lineage and Peer + protocol for each cluster before fixing it: claim it, ask the lineage + whether someone already fixes it, and take their fix or keep yours. Keep investigating while you wait for answers. 4. **Download artifacts per cluster.** Use the `ci-artifacts` skill for the mechanics — it covers per-job logs while a run is still in progress, which @@ -78,7 +76,7 @@ root cause is proven. disabling the check, no soft-skip. If a failure is genuinely external (upstream outage, flaky infra), confirm that with evidence and surface it honestly instead of fixing around it. Report every fix, every proposal, and - every abandoned attempt to the same agents through the `coordinate` skill, + every abandoned attempt to the same agents through the `democracy` Peer protocol, then remove the sidetree. 9. **Tune one log per cluster.** For each cluster, hand one job log to the `tune` skill: the cluster's job that ran furthest, because its timings cover diff --git a/skills/tune/SKILL.md b/skills/tune/SKILL.md index c56f6b7..900300d 100644 --- a/skills/tune/SKILL.md +++ b/skills/tune/SKILL.md @@ -107,23 +107,18 @@ Discard a before/after pair, not just its noise, when: A cost cluster is one place the time goes: one step, one hot path, one repeated call, named by its log line and its number. Before investigating or -implementing a cluster, run the `coordinate` skill for it, and send the -question to every other agent session on this machine, not only the branch -lineage: has anyone already identified this cluster? +implementing a cluster, run the `democracy` skill's Peer protocol for it with +every agent session on this machine, not only the branch lineage. - **The first to identify a cluster works it.** "First" is the `democracy` - skill's atomic claim (`cluster/`), whose claim file names the - cluster's log line and number; between machines, the earliest announcement - by message time. A claim without a measurement does not count. -- **Someone was earlier:** stop on that cluster. Send them your measurements - and findings, then move on to the next cluster. Never build a second - optimization of the same cluster. -- **You are first:** announce the claim with the log line, the number and the - sidetree branch, then work it. A silent peer is not a competing claim; - proceed after a bounded wait. + claim `cluster/`, whose `--work` names the cluster's log line and + number; between machines, the earliest announcement by message time. A + claim without a measurement does not count. +- **Someone was earlier:** send them your measurements and findings, then move + on to the next cluster. Never build a second optimization of the same + cluster. - **A claim ends** when its holder reports the result, a proposal or an - abandoned attempt and removes its claim, or when the operator reassigns it. - Only then may another agent take the cluster. + abandoned attempt and releases it, or when the operator reassigns it. ## Levers that usually pay