Merge feature/kvb-org-swarm-unify into master

This commit is contained in:
Kevin Veen-Birkenbach committed 2026-11-11 08:45:47 +00:00
commit 275745ba1d
16 files changed
+118 -22

No files matched your search

+10 -2
View File
@@ -74,7 +74,8 @@ flowchart LR
check --> check_ansible[kvb-check-ansible] check --> check_ansible[kvb-check-ansible]
check --> check_score[kvb-check-score] check --> check_score[kvb-check-score]
org --> org_organize[kvb-org-organize] org --> org_organize[kvb-org-organize]
org --> org_split[kvb-org-split] org --> org_swarm[kvb-org-swarm]
org --> org_unify[kvb-org-unify]
org --> org_coordinate[kvb-org-coordinate] org --> org_coordinate[kvb-org-coordinate]
org --> org_perform[kvb-org-perform] org --> org_perform[kvb-org-perform]
org --> org_matrix[kvb-org-matrix] org --> org_matrix[kvb-org-matrix]
@@ -188,7 +189,8 @@ flowchart LR
end end
subgraph cat_org [org] subgraph cat_org [org]
democracy[kvb-org-organize] democracy[kvb-org-organize]
funnel[kvb-org-split] funnel[kvb-org-swarm]
unify[kvb-org-unify]
coordinate[kvb-org-coordinate] coordinate[kvb-org-coordinate]
subagent_model[kvb-org-perform] subagent_model[kvb-org-perform]
status_matrix[kvb-org-matrix] status_matrix[kvb-org-matrix]
@@ -297,6 +299,12 @@ flowchart LR
democracy --> merge_fix democracy --> merge_fix
democracy -. claim and release .-> rasci democracy -. claim and release .-> rasci
funnel --> rasci funnel --> rasci
unify --> funnel
unify --> rasci
unify --> gate
unify --> branch_gc
unify --> cleanup
unify --> radio
status_matrix --> rasci status_matrix --> rasci
cleanup --> artefacts cleanup --> artefacts
artefacts --> rasci artefacts --> rasci
+1 -1
View File
@@ -67,7 +67,7 @@ commit starts from zero.
only while a host process under it lives; a `docker compose exec` deploy only while a host process under it lives; a `docker compose exec` deploy
runs on in its container unguarded. runs on in its container unguarded.
- 90/5 is allowed only on `gate: green` for the exact head: in - 90/5 is allowed only on `gate: green` for the exact head: in
`kvb-check-score`, the `90/5` label and the `kvb-org-split` bar. `kvb-check-score`, the `90/5` label and the `kvb-org-swarm` bar.
- Never edit `kvb-gate.json` by hand. - Never edit `kvb-gate.json` by hand.
## Output ## Output
+1 -1
View File
@@ -35,7 +35,7 @@ steps 0 to 2; the judgement stays yours.
member's only when the first leaves part of the cluster unexplained. Pull member's only when the first leaves part of the cluster unexplained. Pull
them even when the log looks conclusive: it only names the artifact; the them even when the log looks conclusive: it only names the artifact; the
assertion, server-side exception and state dumps are inside. assertion, server-side exception and state dumps are inside.
5. **One funnel per cluster** via the `kvb-org-split` skill: one agent per 5. **One funnel per cluster** via the `kvb-org-swarm` skill: one agent per
claimed cluster, its own worktree and branch from the exact current HEAD, claimed cluster, its own worktree and branch from the exact current HEAD,
that cluster its only concern, worked as `funnel.md` next to this file that cluster its only concern, worked as `funnel.md` next to this file
says (dialectic, shared vs hidden causes, root fix); read it before says (dialectic, shared vs hidden causes, root fix); read it before
+2 -2
View File
@@ -14,7 +14,7 @@ skill's Rules apply here too.
the first, keep going until the job is actually green, not just past the the first, keep going until the job is actually green, not just past the
first error. first error.
3. **Fix at the root**: apply the real fix for each proven root cause in the 3. **Fix at the root**: apply the real fix for each proven root cause in the
sidetree, with a test and a negative control as the `kvb-org-split` skill sidetree, with a test and a negative control as the `kvb-org-swarm` skill
demands. Light runs (no Docker, about a minute: targeted pytest or demands. Light runs (no Docker, about a minute: targeted pytest or
unittest, ruff, single lint files) self-admit with unittest, ruff, single lint files) self-admit with
`${CLAUDE_SKILL_DIR}/../kvb-org-organize/scripts/watch.py admit --kind `${CLAUDE_SKILL_DIR}/../kvb-org-organize/scripts/watch.py admit --kind
@@ -23,7 +23,7 @@ skill's Rules apply here too.
`${CLAUDE_SKILL_DIR}/../kvb-org-queue/scripts/queue.py hold --kind <kind> `${CLAUDE_SKILL_DIR}/../kvb-org-queue/scripts/queue.py hold --kind <kind>
--task <register task> -- <command>`, which waits for the rule-based --task <register task> -- <command>`, which waits for the rule-based
grant and releases on exit. The fix enters the main line only grant and releases on exit. The fix enters the main line only
at the funnel's bar (the `kvb-org-split` skill's: fix confidence ≥ 90 %, at the funnel's bar (the `kvb-org-swarm` skill's: fix confidence ≥ 90 %,
break risk ≤ 5 %, cost and time ≤ 100 % in the `kvb-check-score` break risk ≤ 5 %, cost and time ≤ 100 % in the `kvb-check-score`
block; over 100 %, ask the operator before the commit, naming the cause) block; over 100 %, ask the operator before the commit, naming the cause)
after its independent review; below the bar the cluster ends as a after its independent review; below the bar the cluster ends as a
+1 -1
View File
@@ -15,7 +15,7 @@ with the questions of `listen.md` next to this file. Keep the answers for the
session, never ask again, work only inside them; a candidate outside them session, never ask again, work only inside them; a candidate outside them
becomes a proposal. Invoked by another skill (kvb-ci-triage, kvb-ci-observe) becomes a proposal. Invoked by another skill (kvb-ci-triage, kvb-ci-observe)
or an autonomous run: no questions; examine the handed-over log with the or an autonomous run: no questions; examine the handed-over log with the
defaults (10 s floor per run, the `kvb-org-split` skill's 90/5 bar as merge defaults (10 s floor per run, the `kvb-org-swarm` skill's 90/5 bar as merge
bar, 60 minutes per delegated agent), ask only when an operator-only fact bar, 60 minutes per delegated agent), ask only when an operator-only fact
blocks. blocks.
+1 -1
View File
@@ -28,7 +28,7 @@ Levers that usually pay:
## Delegating it ## Delegating it
Hand every optimization to an agent through the `kvb-org-split` skill: one Hand every optimization to an agent through the `kvb-org-swarm` skill: one
sidetree per candidate, branched from an exact commit, with a time cap and sidetree per candidate, branched from an exact commit, with a time cap and
"measure first, report the time split before implementing". One agent per "measure first, report the time split before implementing". One agent per
candidate, never more; the brief names the step, its log line and number, the candidate, never more; the brief names the step, its log line and number, the
+1 -1
View File
@@ -15,7 +15,7 @@ checklist (multi-select) with suggestions, free text allowed:
3. **Which limits apply to optimizations.** Suggestions: the scope that may 3. **Which limits apply to optimizations.** Suggestions: the scope that may
be changed (files, roles, services); whether new dependencies, toolchains be changed (files, roles, services); whether new dependencies, toolchains
or languages may be introduced; whether infrastructure or CI configuration or languages may be introduced; whether infrastructure or CI configuration
may change; the merge bar (default: the `kvb-org-split` skill's bar of fix may change; the merge bar (default: the `kvb-org-swarm` skill's bar of fix
confidence ≥ 90 %, break risk ≤ 5 %, cost and time ≤ 100 %, over confidence ≥ 90 %, break risk ≤ 5 %, cost and time ≤ 100 %, over
100 % only after asking the operator, naming the cause); a time cap per 100 % only after asking the operator, naming the cause); a time cap per
delegated agent (default 60 minutes). delegated agent (default 60 minutes).
+1 -1
View File
@@ -34,7 +34,7 @@ hotfix.py void --repo <worktree> --target <t> [--target ...]
## Before every deploy, merge or gate ## Before every deploy, merge or gate
1. `sync`: fetches, merges `origin/<default>`, then every branch up the funnel 1. `sync`: fetches, merges `origin/<default>`, then every branch up the funnel
chain the `kvb-org-split` skill records as `base` (open rows of this chain the `kvb-org-swarm` skill records as `base` (open rows of this
repository), each with `--no-verify --no-edit`. It needs the task's branch repository), each with `--no-verify --no-edit`. It needs the task's branch
checked out, a clean tracked tree and the worktree lock free; exit 2 checked out, a clean tracked tree and the worktree lock free; exit 2
names the blocker. Exit 4: a merge conflicted and was aborted; names the blocker. Exit 4: a merge conflicted and was aborted;
+3 -3
View File
@@ -23,7 +23,7 @@ request, so a red one blocks nothing else.
created once: `gh label create "in analysis" --color FBCA04 --description created once: `gh label create "in analysis" --color FBCA04 --description
"An agent analyses this issue"`, `gh label create "in progress" --color "An agent analyses this issue"`, `gh label create "in progress" --color
1D76DB --description "An agent works on a fix"`. 1D76DB --description "An agent works on a fix"`.
4. **Solve** each with the `kvb-org-split` skill: claim `work/issue-<n>`, 4. **Solve** each with the `kvb-org-swarm` skill: claim `work/issue-<n>`,
enter it in the `kvb-org-rasci` register (objective: the issue fixed; key enter it in the `kvb-org-rasci` register (objective: the issue fixed; key
results: a test that failed before and passes after, the pull request results: a test that failed before and passes after, the pull request
open), branch `fix/<scope>/<n>` from the default branch in its own open), branch `fix/<scope>/<n>` from the default branch in its own
@@ -40,10 +40,10 @@ request, so a red one blocks nothing else.
edit <n> --remove-label "in analysis" --add-label "in progress"`. edit <n> --remove-label "in analysis" --add-label "in progress"`.
5. **Open the pull request** with the `kvb-git-pr-create` skill, closing 5. **Open the pull request** with the `kvb-git-pr-create` skill, closing
exactly its issue; one for a failing default branch is posted with exactly its issue; one for a failing default branch is posted with
`radio.py post`. Below the split bar the proposal becomes a draft pull `radio.py post`. Below the swarm bar the proposal becomes a draft pull
request with the residuals and the evidence that would close them. request with the residuals and the evidence that would close them.
6. **Report** per issue, then release its claim and tear its sidetree down 6. **Report** per issue, then release its claim and tear its sidetree down
as `kvb-org-split` describes; the branch stays until the merge. An issue as `kvb-org-swarm` describes; the branch stays until the merge. An issue
dropped or handed on loses its label and gets a comment saying why. dropped or handed on loses its label and gets a comment saying why.
## Output ## Output
+1 -1
View File
@@ -23,7 +23,7 @@ confirms it.
evidence, the score block, and one `Closes #<n>` line per issue the evidence, the score block, and one `Closes #<n>` line per issue the
branch fixes, each verified as the `kvb-git-issue-close` skill does. branch fixes, each verified as the `kvb-git-issue-close` skill does.
5. **Confirm** with one `AskUserQuestion`: title (Conventional Commits), 5. **Confirm** with one `AskUserQuestion`: title (Conventional Commits),
base, state and labels. The state follows the bar of the `kvb-org-split` base, state and labels. The state follows the bar of the `kvb-org-swarm`
skill (fix confidence ≥ 90 %, break risk ≤ 5 %, cost and time skill (fix confidence ≥ 90 %, break risk ≤ 5 %, cost and time
≤ 100 %): ready at or above it, a draft with the residuals in the body ≤ 100 %): ready at or above it, a draft with the residuals in the body
below it. A cost or time over 100 % goes into this question with below it. A cost or time over 100 % goes into this question with
+1 -1
View File
@@ -11,7 +11,7 @@ holds:
- **`hotfix`**: the pull request targets the default branch and fixes a - **`hotfix`**: the pull request targets the default branch and fixes a
failure on it, a red default-branch run or an issue that reproduces there; failure on it, a red default-branch run or an issue that reproduces there;
name the run or issue. name the run or issue.
- **`90/5`**: the pull request meets the bar of the `kvb-org-split` skill (fix - **`90/5`**: the pull request meets the bar of the `kvb-org-swarm` skill (fix
confidence ≥ 90 %, break risk ≤ 5 %, cost and time ≤ 100 %; over confidence ≥ 90 %, break risk ≤ 5 %, cost and time ≤ 100 %; over
100 %, ask the operator first, naming the cause), from the 100 %, ask the operator first, naming the cause), from the
`kvb-check-score` block in its body or freshly assessed, and only when `kvb-check-score` block in its body or freshly assessed, and only when
+2 -2
View File
@@ -1,7 +1,7 @@
# Coordinating a failure or fix with peers # Coordinating a failure or fix with peers
`kvb-org-coordinate`, `kvb-ci-triage`, `kvb-code-tune`, `kvb-org-split` and `kvb-org-coordinate`, `kvb-ci-triage`, `kvb-code-tune`, `kvb-org-swarm`,
`kvb-cleanup` follow these steps. `kvb-org-unify` and `kvb-cleanup` follow these steps.
1. **Look**: `council.py list`, the `kvb-org-rasci` register, the radio, 1. **Look**: `council.py list`, the `kvb-org-rasci` register, the radio,
`hotfix.py match --line '<line>' --repo <worktree>` of the `kvb-git-hotfix` `hotfix.py match --line '<line>' --repo <worktree>` of the `kvb-git-hotfix`
@@ -1,11 +1,11 @@
--- ---
name: kvb-org-split name: kvb-org-swarm
description: > description: >
Keep agent work in its own worktree until it meets the 90/5 bar Keep agent work in its own worktree until it meets the 90/5 bar
(kvb-check-score), else a proposal. Trigger when delegating or parallelizing. (kvb-check-score), else a proposal. Trigger when delegating or parallelizing.
--- ---
# Funnel # Swarm
The main line only receives changes that have earned it. Everything else stays The main line only receives changes that have earned it. Everything else stays
in a sidetree until it does, or leaves as a proposal. in a sidetree until it does, or leaves as a proposal.
@@ -52,9 +52,8 @@ in a sidetree until it does, or leaves as a proposal.
5. **Independent review.** Before any merge, run the `kvb-think-dialectic` 5. **Independent review.** Before any merge, run the `kvb-think-dialectic`
skill with skeptics who did not write the change, briefed the same way skill with skeptics who did not write the change, briefed the same way
(exact diff and claim, capped answer). A hole returns the change to stage 3. (exact diff and claim, capped answer). A hole returns the change to stage 3.
6. **Merge.** At or above the bar, merge the sidetree branch by the 6. **Merge.** At or above the bar, through the `kvb-org-unify` skill: one
repository's commit rules, then re-verify on the main line with the integration branch, one gate, the line on the operator's word.
project's gate.
7. **Tear down.** Read `teardown.md` next to this file before tearing down a 7. **Tear down.** Read `teardown.md` next to this file before tearing down a
merged, proposed or abandoned sidetree. merged, proposed or abandoned sidetree.
File renamed without changes.
File renamed without changes.
+89
View File
@@ -0,0 +1,89 @@
---
name: kvb-org-unify
description: >
Unify a swarm's branches into one integration branch, gate it once, land it
on the operator's word, then clear worktrees, branches and leftovers.
Trigger on "unify", "swarm zusammenführen" or after a kvb-org-swarm round.
---
The `kvb-org-swarm` skill splits a goal into sidetrees; this skill brings them
home in one pass. Invoking it clears the merges into `unify/<goal>`; the line
receives nothing, and nothing is removed, without the operator's word in this
run. Never push: that stays with the operator (`kvb-git-push`).
## Step 0: claim
Claim `work/unify-<goal>` through the `kvb-org-organize` skill and enter it in
the `kvb-org-rasci` register: objective "every swarm branch of `<goal>` at the
bar on `<line>`", key results gate green, landed, cleaned up, overview posted.
`<line>` is the line the operator names, else the default branch.
## Step 1: collect
The register is the swarm's record (stage 2 of `kvb-org-swarm` sets `--branch`
and `--base`):
```bash
jq -r --arg base "<line>" 'to_entries[] | select(.value.base == $base and .value.branch) | [.key, .value.branch, .value.workdir // "-", .value.status] | @tsv' "${AGENTS_COUNCIL_ROOT:-/tmp/agents-council}/rasci.json"
```
Per branch: `git log --oneline <line>..<branch>` (empty: already merged, go
to step 5), `git status --porcelain` in its worktree, its latest
`kvb-check-score` block and its independent review (`kvb-org-swarm` stage 5).
A branch is **ready** only at the bar, clean, reviewed and with its owner's
claim released or the owner's yes by `radio.py post`; everything else is a
proposal with its reason: below the bar (the score), unreviewed, dirty, owner
busy.
## Step 2: integrate
A worktree in a released directory on `unify/<goal>` from `<line>`. Merge the
ready branches, highest register priority first, with
`git merge --no-ff --no-verify <branch>`. A conflict: `git merge --abort`, and
the branch becomes a proposal naming the conflicting files.
## Step 3: gate
The project's full gate on `unify/<goal>` through `queue.py hold`
(`kvb-check-gate`), and `security.py` over `<line>..unify/<goal>`
(`kvb-check-security`), logs under `/tmp`. Red: find the merge that broke it
(`git bisect start --first-parent`), rebuild the branch without it, which
becomes a proposal naming the failing test, and gate again.
## Step 4: land
Show the `kvb-check-score` commit table of `<line>..unify/<goal>` and every
proposal. On the operator's word: `git merge --ff-only unify/<goal>` in the
line's checkout; when the line moved meanwhile, merge it into `unify/<goal>`
and gate again first. The push goes to the operator as a `kvb-org-operator`
row.
## Step 5: clean up
Per merged branch and for `unify/<goal>`, the teardown of `kvb-org-swarm`
(`teardown.md`: jobs, stacks, container-owned files, worktree, register). A
proposal keeps its branch and loses worktree, stacks and temporary files. Then
the dry runs of `kvb-git-branch-gc` (`--merged-into <line>`) and the
inventory of `kvb-cleanup` for the swarm's logs, scratch and Docker leftovers,
merged into one table (area, item, size, owner, risk, what breaks if wrong)
and one `AskUserQuestion` pick; each skill removes only the picked items, by
its own execute rules. What the sandbox blocks becomes a `kvb-org-operator`
row.
## Step 6: report
Post the overview to the operator, not merged first:
`${CLAUDE_SKILL_DIR}/../kvb-org-radio/scripts/radio.py post --to Operator
"unify <goal>: <m> of <n> merged; NOT merged: <branch> (<reason>, closes with
<step>), ..."`. Set the register task `done`, or `stopped` while a key result
is open.
## Output
First line, when any branch stayed out: **⚠️ <k> of <n> swarm branches NOT
merged**. Then one table, not merged rows first:
| Branch | Task | Score | Verdict | Reason / what closes the gap |
Verdict: **⚠️ NOT MERGED** (proposal), ✅ merged, 🧹 removed. Below it the
cleanup result per area and the operator rows handed over.