Workflow lanes are self-contradictory about who merges, have no slug for the tpm merge lane, and name merge as the only PR outcome #1189

Open
opened 2026-08-22 22:14:36 +00:00 by coilyco-ops · 5 comments
Member

Requested by Kai on 2026-08-22. Charter half is filed at coilyco-flight-deck/agent-compose#321; this is the tooling and doctrine half.

The gap

The seat that gates pull requests should exercise close and revert, not merge alone. Two separate problems block that, and only one of them is a missing verb.

Problem 1: the doctrine never mentions close, though the verb already exists

aosguard ops forgejo pr close and pr reopen already ship, landed by #488 as the stranded-PR cleanup verbs. The lifecycle is complete: files, commits, create, edit, close, reopen, update, merge.

But the workflow doctrine in AGENTS.md describes only merge. The four lane slugs are:

  • merge-remote-main
  • pull-request
  • pull-request-and-merge
  • remote-branch-only

Every one of them describes landing work. None describes declining it. The rules under "Git workflow" say "ALWAYS merge your own pull request on pull-request-and-merge" and "NEVER merge on pull-request or remote-branch-only" - merge, merge, merge. An agent reading that doctrine has no sanctioned action for a pull request that should not land, so the pull request stays open forever.

That is the same litter the doctrine already legislates against, relocated. AGENTS.md says "A branch with no PR is litter: nothing points at it, no review is pending on it." An open PR that nobody will merge or close is the identical failure with an extra step.

This is a documentation defect against a capability that already exists, which makes it the cheap half.

Problem 2: there is no revert verb, and there cannot be a simple one

aosguard ops forgejo has no pr revert, and adding one is not symmetric with pr close:

  • Close is PATCH state=closed - one call, exactly reversible by pr reopen. The verb's own help says a wrong close is not a wall.
  • Revert has no Forgejo API. Undoing a merged pull request means a git revert commit against main plus a follow-up pull request. It mutates the shared branch, and there is no inverse call.

So pr revert would be a composite operation, not an API wrapper, and it sits in a different consequence class from every other pr verb. Three options worth weighing rather than assuming:

  1. A composite verb that creates the revert branch, commits the revert, opens the PR, and stops - leaving the merge to the ordinary gate. Keeps the destructive step behind the existing merge policy.
  2. No verb, documented workflow only. Revert is rare enough that a written procedure may beat a tool, and a tool invites reaching for it.
  3. A verb that reverts directly on main. Fastest, and the one that most deserves scrutiny, since AGENTS.md already treats force-push and history rewriting as the walls that stay closed. A direct revert is not a force-push, but it is a mutation of main that no review gate sees.

Option 1 looks right, but this issue should not presume it.

Problem 3: the lane slugs undersell the lane

AGENTS.md is explicit that "Every lane slug names what the AGENT does, never what someone else does" and that reading pull-request-and-merge as "someone else merges it later" inverts the lanes.

By that same rule, a lane whose seat can merge, close, and revert is not fully described by a slug that names only merging. Either the slug widens, or the doctrine states plainly that -and-merge is shorthand for the full gate authority. The second is probably less disruptive - renaming lanes ripples through ward.workflow frontmatter across every repo - but the ambiguity should be resolved deliberately rather than left for a reader to guess.

Where this lands in the reflow

director and exec merge into tpm in the v3 Core Roster reflow, and qa is cut with its code review moving to tpm - see #1176 and agent-compose#317. So the seat this doctrine governs is tpm, and it is simultaneously the reviewing seat and the landing seat.

That is precisely why the one-exit gate matters here: a reviewer who can only approve is a rubber stamp by construction. Write the doctrine against tpm rather than director.

Note that #1176 already carries the roles.kdl reconciliation for this reflow, including moving tooling-code-review onto tpm. This issue should land after or alongside it, not before, or it will describe a seat that does not exist yet.

Acceptance

  1. AGENTS.md workflow doctrine states the full pull-request action surface for the gating seat: merge, close, and revert - with close presented as ordinary and reversible, and revert as consequential.
  2. The bar for closing is written, so an agent knows when close beats leaving a PR open. Superseded, wrong approach, obsolete, and empty branch are the obvious cases.
  3. A decision is recorded on the three pr revert options above, with reasoning, whether or not a verb ships.
  4. The lane-slug ambiguity is resolved explicitly - either widened slugs, or a stated shorthand rule.
  5. If a verb ships, aosguard ops forgejo describes it with the same consequence framing the other destructive verbs get, and the existing coily* owner scoping and branch protection still apply.
  6. Sequenced against #1176 so it names tpm rather than a slug that is being retired.

Not in scope

The tpm role charter itself - what the seat owns and the bar for each action - is agent-compose#321. This issue is the doctrine and the verbs.

Requested by Kai on 2026-08-22. Charter half is filed at `coilyco-flight-deck/agent-compose#321`; this is the tooling and doctrine half. ## The gap The seat that gates pull requests should exercise **close** and **revert**, not merge alone. Two separate problems block that, and only one of them is a missing verb. ## Problem 1: the doctrine never mentions close, though the verb already exists `aosguard ops forgejo pr close` and `pr reopen` **already ship**, landed by #488 as the stranded-PR cleanup verbs. The lifecycle is complete: `files`, `commits`, `create`, `edit`, `close`, `reopen`, `update`, `merge`. But the workflow doctrine in `AGENTS.md` describes only merge. The four lane slugs are: * `merge-remote-main` * `pull-request` * `pull-request-and-merge` * `remote-branch-only` Every one of them describes landing work. **None describes declining it.** The rules under "Git workflow" say "ALWAYS merge your own pull request on `pull-request-and-merge`" and "NEVER merge on `pull-request` or `remote-branch-only`" - merge, merge, merge. An agent reading that doctrine has no sanctioned action for a pull request that should not land, so the pull request stays open forever. That is the same litter the doctrine already legislates against, relocated. `AGENTS.md` says "**A branch with no PR is litter**: nothing points at it, no review is pending on it." An open PR that nobody will merge or close is the identical failure with an extra step. **This is a documentation defect against a capability that already exists**, which makes it the cheap half. ## Problem 2: there is no revert verb, and there cannot be a simple one `aosguard ops forgejo` has no `pr revert`, and adding one is not symmetric with `pr close`: * **Close** is `PATCH state=closed` - one call, exactly reversible by `pr reopen`. The verb's own help says a wrong close is not a wall. * **Revert** has no Forgejo API. Undoing a merged pull request means a `git revert` commit against `main` plus a follow-up pull request. It **mutates the shared branch**, and there is no inverse call. So `pr revert` would be a composite operation, not an API wrapper, and it sits in a different consequence class from every other `pr` verb. Three options worth weighing rather than assuming: 1. **A composite verb** that creates the revert branch, commits the revert, opens the PR, and stops - leaving the merge to the ordinary gate. Keeps the destructive step behind the existing merge policy. 2. **No verb, documented workflow only.** Revert is rare enough that a written procedure may beat a tool, and a tool invites reaching for it. 3. **A verb that reverts directly on `main`.** Fastest, and the one that most deserves scrutiny, since `AGENTS.md` already treats force-push and history rewriting as the walls that stay closed. A direct revert is not a force-push, but it is a mutation of `main` that no review gate sees. Option 1 looks right, but this issue should not presume it. ## Problem 3: the lane slugs undersell the lane `AGENTS.md` is explicit that **"Every lane slug names what the AGENT does, never what someone else does"** and that reading `pull-request-and-merge` as "someone else merges it later" inverts the lanes. By that same rule, a lane whose seat can merge, close, *and* revert is not fully described by a slug that names only merging. Either the slug widens, or the doctrine states plainly that `-and-merge` is shorthand for the full gate authority. The second is probably less disruptive - renaming lanes ripples through `ward.workflow` frontmatter across every repo - but the ambiguity should be resolved deliberately rather than left for a reader to guess. ## Where this lands in the reflow `director` and `exec` merge into **`tpm`** in the v3 Core Roster reflow, and **`qa` is cut with its code review moving to `tpm`** - see #1176 and `agent-compose#317`. So the seat this doctrine governs is `tpm`, and it is simultaneously the reviewing seat and the landing seat. That is precisely why the one-exit gate matters here: a reviewer who can only approve is a rubber stamp by construction. Write the doctrine against `tpm` rather than `director`. Note that #1176 already carries the `roles.kdl` reconciliation for this reflow, including moving `tooling-code-review` onto `tpm`. **This issue should land after or alongside it**, not before, or it will describe a seat that does not exist yet. ## Acceptance 1. `AGENTS.md` workflow doctrine states the full pull-request action surface for the gating seat: merge, close, and revert - with close presented as ordinary and reversible, and revert as consequential. 2. The bar for closing is written, so an agent knows when close beats leaving a PR open. Superseded, wrong approach, obsolete, and empty branch are the obvious cases. 3. A decision is recorded on the three `pr revert` options above, with reasoning, whether or not a verb ships. 4. The lane-slug ambiguity is resolved explicitly - either widened slugs, or a stated shorthand rule. 5. If a verb ships, `aosguard ops forgejo` describes it with the same consequence framing the other destructive verbs get, and the existing `coily*` owner scoping and branch protection still apply. 6. Sequenced against #1176 so it names `tpm` rather than a slug that is being retired. ## Not in scope The `tpm` role charter itself - what the seat owns and the bar for each action - is `agent-compose#321`. This issue is the doctrine and the verbs.
Author
Member

Scope expansion, 2026-08-22: the slugs do not encode who merges, and AGENTS.md already contradicts itself about it

Kai's observation, and it is the larger defect. Verified by reading AGENTS.md on main rather than a composed rendering.

Two lanes are each defined twice, incompatibly

pull-request-and-merge:

  • line 71 - "open a PR for the director lane. Merge only after the issue thread shows workflow: pull-request-and-merge, WARD-OUTCOME: done, and a passed review summary."
  • line 86 - "the agent commits to a task branch, pushes it, opens a pull request, and merges that pull request itself once it is green."

One says another seat gates it behind a review summary. The other says the author merges it as soon as CI is green. Those cannot both be the rule.

pull-request:

  • line 70 - "push a branch and open a human-gated Forgejo PR."
  • lines 88 and 96 - the author stops "and the director merge lane takes over" / "the director merge lane carries a pull-request from there."

Human-gated, or director-gated. Also cannot both be the rule.

Line 88 warns against exactly what line 71 says

line 88 - "Reading pull-request-and-merge as 'someone else merges it later' inverts the two lanes and leaves finished work sitting unmerged."

Line 71 states that reading as the definition. The file diagnoses its own defect and does not notice.

This is live in this repository. Line 3 declares workflow: pull-request-and-merge in the frontmatter, so any agent working here reads both definitions and picks one.

The third merger has no slug

"The director merge lane" is named three times - lines 71, 88, 96 - and no slug exists for it. Kai's intent, stated plainly:

who merges slug today verdict
the authoring agent pull-request-and-merge correct at line 86, contradicted at line 71
the human pull-request correct at line 70, contradicted at lines 88 and 96
another agent seat (tpm) none the gap
nobody remote-branch-only consistent
n/a, no PR at all merge-remote-main consistent

The naming rule itself blocks the fix

This is the part worth deciding rather than patching. Line 88 states:

"Every lane slug names what the AGENT does, never what someone else does."

That rule is why the distinction cannot currently be expressed. From the authoring agent's perspective, human-merge and tpm-merge are the same action - push a branch, open a PR, stop. The difference is entirely about who picks it up, which the rule forbids the slug from naming. So the taxonomy is structurally incapable of carrying the thing Kai wants it to carry, and adding a fourth slug under the existing rule will not fix that.

Three ways out, and this issue should record which is chosen:

  1. Bend the rule for gate-holder identity. pull-request-human-merge and pull-request-tpm-merge. Most explicit, most readable at a glance, and it costs the elegance of the current rule - which was written to prevent a specific misreading and is otherwise doing real work.
  2. Move merge authority off the slug entirely. Keep pull-request meaning "author stops at the PR" and add a separate frontmatter field, e.g. ward.merge_authority: human | tpm | self. Preserves the naming rule intact, makes the axis explicit, and costs a second field to read and keep in sync.
  3. Rename so the author's own action differs. If the author requests review from a named seat, that is an agent action and the rule survives - pull-request-request-tpm-review or similar. Honest under the rule but clumsy, and it only works if the author genuinely does something different.

Option 2 looks cleanest against the existing rule. Option 1 is what a reader would guess. Not presuming either.

Sequencing

The slug work and the close/revert work edit the same paragraphs - lines 69-96 - so they should land together rather than as competing diffs. Both still sequence behind #1176 so they name tpm.

One practical note: any slug rename ripples into ward.workflow frontmatter across every repo in the fleet, and into whatever validates that field. That cost argues for option 2 and should be measured before choosing option 1.

Added to acceptance

  1. Lines 70, 71, 88, and 96 are reconciled so each lane has exactly one definition, and the merger is unambiguous in every one.
  2. A lane exists for tpm-merge, by whichever of the three mechanisms is chosen, with the choice and its reasoning recorded here.
  3. The "names what the AGENT does" rule is either restated to accommodate the gate-holder axis, or explicitly preserved with the axis moved off the slug.
  4. Every repo carrying ward.workflow is checked, since a rename is a fleet-wide edit and a redefinition silently changes what existing declarations mean.
## Scope expansion, 2026-08-22: the slugs do not encode who merges, and AGENTS.md already contradicts itself about it Kai's observation, and it is the larger defect. Verified by reading `AGENTS.md` on `main` rather than a composed rendering. ### Two lanes are each defined twice, incompatibly **`pull-request-and-merge`:** * **line 71** - "open a PR for **the director lane**. Merge only after the issue thread shows `workflow: pull-request-and-merge`, `WARD-OUTCOME: done`, and **a passed review summary**." * **line 86** - "the agent commits to a task branch, pushes it, opens a pull request, and **merges that pull request itself once it is green**." One says another seat gates it behind a review summary. The other says the author merges it as soon as CI is green. Those cannot both be the rule. **`pull-request`:** * **line 70** - "push a branch and open a **human-gated** Forgejo PR." * **lines 88 and 96** - the author stops "and **the director merge lane** takes over" / "the director merge lane carries a `pull-request` from there." Human-gated, or director-gated. Also cannot both be the rule. ### Line 88 warns against exactly what line 71 says > **line 88** - "Reading `pull-request-and-merge` as 'someone else merges it later' inverts the two lanes and leaves finished work sitting unmerged." Line 71 states that reading as the definition. The file diagnoses its own defect and does not notice. **This is live in this repository.** Line 3 declares `workflow: pull-request-and-merge` in the frontmatter, so any agent working here reads both definitions and picks one. ### The third merger has no slug "The director merge lane" is named three times - lines 71, 88, 96 - and **no slug exists for it**. Kai's intent, stated plainly: | who merges | slug today | verdict | |---|---|---| | the authoring agent | `pull-request-and-merge` | correct at line 86, contradicted at line 71 | | the human | `pull-request` | correct at line 70, contradicted at lines 88 and 96 | | **another agent seat (tpm)** | **none** | **the gap** | | nobody | `remote-branch-only` | consistent | | n/a, no PR at all | `merge-remote-main` | consistent | ### The naming rule itself blocks the fix This is the part worth deciding rather than patching. Line 88 states: > **"Every lane slug names what the AGENT does, never what someone else does."** That rule is why the distinction cannot currently be expressed. From the authoring agent's perspective, human-merge and tpm-merge are **the same action** - push a branch, open a PR, stop. The difference is entirely about who picks it up, which the rule forbids the slug from naming. So the taxonomy is structurally incapable of carrying the thing Kai wants it to carry, and adding a fourth slug under the existing rule will not fix that. Three ways out, and this issue should record which is chosen: 1. **Bend the rule for gate-holder identity.** `pull-request-human-merge` and `pull-request-tpm-merge`. Most explicit, most readable at a glance, and it costs the elegance of the current rule - which was written to prevent a specific misreading and is otherwise doing real work. 2. **Move merge authority off the slug entirely.** Keep `pull-request` meaning "author stops at the PR" and add a separate frontmatter field, e.g. `ward.merge_authority: human | tpm | self`. Preserves the naming rule intact, makes the axis explicit, and costs a second field to read and keep in sync. 3. **Rename so the author's own action differs.** If the author requests review from a named seat, that *is* an agent action and the rule survives - `pull-request-request-tpm-review` or similar. Honest under the rule but clumsy, and it only works if the author genuinely does something different. Option 2 looks cleanest against the existing rule. Option 1 is what a reader would guess. Not presuming either. ### Sequencing The slug work and the close/revert work edit **the same paragraphs** - lines 69-96 - so they should land together rather than as competing diffs. Both still sequence behind #1176 so they name `tpm`. One practical note: any slug rename ripples into `ward.workflow` frontmatter across every repo in the fleet, and into whatever validates that field. That cost argues for option 2 and should be measured before choosing option 1. ### Added to acceptance 7. Lines 70, 71, 88, and 96 are reconciled so each lane has exactly one definition, and the merger is unambiguous in every one. 8. A lane exists for tpm-merge, by whichever of the three mechanisms is chosen, with the choice and its reasoning recorded here. 9. The "names what the AGENT does" rule is either restated to accommodate the gate-holder axis, or explicitly preserved with the axis moved off the slug. 10. Every repo carrying `ward.workflow` is checked, since a rename is a fleet-wide edit and a redefinition silently changes what existing declarations mean.
coilyco-ops changed title from Workflow lanes name merge as the only PR outcome, so pr close goes unused and pr revert has no verb at all to Workflow lanes are self-contradictory about who merges, have no slug for the tpm merge lane, and name merge as the only PR outcome 2026-08-22 22:51:31 +00:00
Author
Member

Decision, 2026-08-22: option 1, with role-agnostic slugs

Kai's call. Option 1 - the slug names the gate holder - and the naming rule at line 88 bends to accommodate it. Verbosity is explicitly acceptable for this family.

Literal tpm is rejected as non-durable. The roster has already reflowed once (nine seats to seven, director and exec into tpm), and a slug carrying a seat name rots at the next reflow. The slugs name the relationship to the work, not the seat.

Kai's proposed set:

  • author-author-merge
  • agent-reviewer-merge
  • human-reviewer-merge

These replace pull-request and pull-request-and-merge. merge-remote-main and remote-branch-only are untouched - neither is a PR-merge lane.

The migration is far cheaper than this issue previously warned

I flagged earlier that a rename "ripples into ward.workflow frontmatter across every repo in the fleet" and used that cost to argue against option 1. That was wrong, and the actual declarations retire the objection. Surveyed across 22 repos:

declared lane repos
merge-remote-main 16 - agent-proxy, agent-compose, mcp-beaver, node-stats-mcp, bluesky-mcp, lunch-money-k8s, agentic-os-kai, agentic-os-hardware, eco-app, eco-ops, galaxy-gen, steam-ops, website, inbox, lore, voice-corpus
pull-request-and-merge 5 - agentic-os, ward, infrastructure, deploy, sirens-echo
pull-request 0
remote-branch-only 0
(none declared) 1 - umbra

The ambiguous slug is declared by nobody. pull-request - the one that means human-merge in line 70 and director-merge in lines 88 and 96 - has zero declarations. So splitting it into human-reviewer-merge and agent-reviewer-merge requires no per-repo decision and no migration. It is purely additive, and the ambiguity has never actually bitten a repo because no repo has ever used it.

That leaves 5 mechanical edits: pull-request-and-merge becomes author-author-merge in five frontmatter blocks. Only one meaning is in play there, so it is a find-and-replace rather than a judgment call. The 16 merge-remote-main repos are untouched.

Acceptance item 10 is correspondingly cheap. It is five edits plus whatever validates the field.

One naming asymmetry to settle before anything is written

The three slugs do not follow one pattern:

  • agent-reviewer-merge and human-reviewer-merge are <merger>-merge
  • author-author-merge doubles the word, which under the same pattern would be author-merge

Two consistent readings, and the choice should be deliberate since these go into five frontmatter blocks and a validator:

(a) <merger>-merge - author-merge, agent-reviewer-merge, human-reviewer-merge. Each slug names exactly one thing: who merges. Shortest, and reads cleanly as a set.

(b) <opener>-<merger>-merge - author-author-merge, author-agent-reviewer-merge, author-human-reviewer-merge. Carries both parties, which is more information, and honours "verbose is fine" more literally. The opener is always the author on all three, so the first token is constant and arguably dead weight.

Recommendation: (a). The opener never varies across these three lanes, so naming it adds a token that never discriminates. author-merge sits naturally beside the other two, and the whole family still reads as "who merges."

Kai to settle. Nothing should be written until it is, because a slug is expensive to rename twice.

Second-order note, not for this issue

The new family names the merger; merge-remote-main names the destination. That is a mixed taxonomy, and a fully consistent set might make it something like author-direct-merge. Not recommended here - it is declared by 16 repos, the rename buys clarity rather than correctness, and it would turn a 5-edit change into a 21-edit one. Worth its own issue if it ever bothers anyone; worth not smuggling into this one.

Separate finding: umbra declares no lane

coilyco-flight-deck/umbra has no ward.workflow in its AGENTS.md frontmatter, while every other surveyed repo declares one. Under this doctrine that means an agent working umbra has no defined merge authority and has to infer one. Not caused by this change and not in scope, but it should not be discovered later by an agent guessing - worth its own issue.

## Decision, 2026-08-22: option 1, with role-agnostic slugs Kai's call. **Option 1** - the slug names the gate holder - and the naming rule at line 88 bends to accommodate it. Verbosity is explicitly acceptable for this family. **Literal `tpm` is rejected as non-durable.** The roster has already reflowed once (nine seats to seven, `director` and `exec` into `tpm`), and a slug carrying a seat name rots at the next reflow. The slugs name the *relationship* to the work, not the seat. Kai's proposed set: * `author-author-merge` * `agent-reviewer-merge` * `human-reviewer-merge` These replace `pull-request` and `pull-request-and-merge`. `merge-remote-main` and `remote-branch-only` are untouched - neither is a PR-merge lane. ## The migration is far cheaper than this issue previously warned I flagged earlier that a rename "ripples into `ward.workflow` frontmatter across every repo in the fleet" and used that cost to argue against option 1. **That was wrong**, and the actual declarations retire the objection. Surveyed across 22 repos: | declared lane | repos | |---|---| | `merge-remote-main` | **16** - agent-proxy, agent-compose, mcp-beaver, node-stats-mcp, bluesky-mcp, lunch-money-k8s, agentic-os-kai, agentic-os-hardware, eco-app, eco-ops, galaxy-gen, steam-ops, website, inbox, lore, voice-corpus | | `pull-request-and-merge` | **5** - agentic-os, ward, infrastructure, deploy, sirens-echo | | `pull-request` | **0** | | `remote-branch-only` | **0** | | *(none declared)* | **1** - umbra | **The ambiguous slug is declared by nobody.** `pull-request` - the one that means human-merge in line 70 and director-merge in lines 88 and 96 - has zero declarations. So splitting it into `human-reviewer-merge` and `agent-reviewer-merge` requires **no per-repo decision and no migration**. It is purely additive, and the ambiguity has never actually bitten a repo because no repo has ever used it. That leaves **5 mechanical edits**: `pull-request-and-merge` becomes `author-author-merge` in five frontmatter blocks. Only one meaning is in play there, so it is a find-and-replace rather than a judgment call. The 16 `merge-remote-main` repos are untouched. Acceptance item 10 is correspondingly cheap. It is five edits plus whatever validates the field. ## One naming asymmetry to settle before anything is written The three slugs do not follow one pattern: * `agent-reviewer-merge` and `human-reviewer-merge` are **`<merger>-merge`** * `author-author-merge` doubles the word, which under the same pattern would be `author-merge` Two consistent readings, and the choice should be deliberate since these go into five frontmatter blocks and a validator: **(a) `<merger>-merge`** - `author-merge`, `agent-reviewer-merge`, `human-reviewer-merge`. Each slug names exactly one thing: who merges. Shortest, and reads cleanly as a set. **(b) `<opener>-<merger>-merge`** - `author-author-merge`, `author-agent-reviewer-merge`, `author-human-reviewer-merge`. Carries both parties, which is more information, and honours "verbose is fine" more literally. The opener is always the author on all three, so the first token is constant and arguably dead weight. **Recommendation: (a).** The opener never varies across these three lanes, so naming it adds a token that never discriminates. `author-merge` sits naturally beside the other two, and the whole family still reads as "who merges." Kai to settle. Nothing should be written until it is, because a slug is expensive to rename twice. ## Second-order note, not for this issue The new family names **the merger**; `merge-remote-main` names **the destination**. That is a mixed taxonomy, and a fully consistent set might make it something like `author-direct-merge`. **Not recommended here** - it is declared by 16 repos, the rename buys clarity rather than correctness, and it would turn a 5-edit change into a 21-edit one. Worth its own issue if it ever bothers anyone; worth not smuggling into this one. ## Separate finding: umbra declares no lane `coilyco-flight-deck/umbra` has no `ward.workflow` in its `AGENTS.md` frontmatter, while every other surveyed repo declares one. Under this doctrine that means an agent working umbra has no defined merge authority and has to infer one. Not caused by this change and not in scope, but it should not be discovered later by an agent guessing - worth its own issue.
Author
Member

Settled: the semantics, and why the original triple is already consistent

Kai's natural-language statement of the three lanes, which is the authoritative definition:

  1. agent author creates the PR, merges their own PR
  2. agent author creates the PR, defers the merge, a reviewer agent (tpm, another engineer, etc) merges
  3. agent author creates the PR, defers the merge, a human merges

This retires my author-merge recommendation

I argued for <merger>-merge on the grounds that "the opener is always the author, so naming it adds a token that never discriminates." The semantics show the second token is not the opener at all - it is the reviewer, and the reviewer is exactly what varies:

lane reviewer slug
1 none - the author is its own gate author-author-merge
2 an agent agent-reviewer-merge
3 a human human-reviewer-merge

Read that way the family is <gate-holder>-merge, where the gate holder is a two-token identity: author-author, agent-reviewer, human-reviewer. The doubling in the first is not redundancy - it marks the collapse of two roles into one party, which is precisely the property that distinguishes lane 1 from the other two. author-merge would erase that.

Keep Kai's slugs exactly as proposed. The naming question is closed.

The shared concept the slugs should carry into the prose

Lanes 2 and 3 share "defers the merge." That is one behaviour with two destinations, and it is already the strictest rule in the current doctrine - line 96's "NEVER merge on pull-request." The rewritten prose should state deferral once as the shared property of both reviewer lanes rather than restating a prohibition per lane.

Lane 1 is the exception: the author does not defer, and line 95's "ALWAYS merge your own pull request" applies there and only there.

Confirms the rejection of literal tpm

Kai's lane 2 reads "a reviewer agent (tpm, another engineer, etc)." The gate holder is any agent seat, not specifically tpm. So agent-reviewer-merge is correct and a hypothetical tpm-merge would have been wrong on two counts - non-durable across roster reflows, and too narrow even today.

Revised acceptance

Replacing items 7 through 9:

  1. The three PR lanes are author-author-merge, agent-reviewer-merge, and human-reviewer-merge, defined by Kai's three sentences above.
  2. merge-remote-main and remote-branch-only are unchanged.
  3. The contradictions at lines 70, 71, 88, and 96 are removed by construction, since each new slug has exactly one meaning and names its gate holder.
  4. Line 88's naming rule is restated: a lane slug names what the agent does and who holds the merge gate, since the gate holder is what distinguishes lanes 2 and 3 and cannot be expressed otherwise.
  5. Deferral is stated once as the shared property of the two reviewer lanes.
  6. Five frontmatter edits: pull-request-and-merge becomes author-author-merge in agentic-os, ward, infrastructure, deploy, and sirens-echo. Nothing else moves, since pull-request and remote-branch-only have zero declarations.
## Settled: the semantics, and why the original triple is already consistent Kai's natural-language statement of the three lanes, which is the authoritative definition: 1. **agent author creates the PR, merges their own PR** 2. **agent author creates the PR, defers the merge, a reviewer agent (tpm, another engineer, etc) merges** 3. **agent author creates the PR, defers the merge, a human merges** ### This retires my `author-merge` recommendation I argued for `<merger>-merge` on the grounds that "the opener is always the author, so naming it adds a token that never discriminates." The semantics show the second token is not the opener at all - **it is the reviewer**, and the reviewer is exactly what varies: | lane | reviewer | slug | |---|---|---| | 1 | **none** - the author is its own gate | `author-author-merge` | | 2 | an **agent** | `agent-reviewer-merge` | | 3 | a **human** | `human-reviewer-merge` | Read that way the family is `<gate-holder>-merge`, where the gate holder is a two-token identity: `author-author`, `agent-reviewer`, `human-reviewer`. The doubling in the first is not redundancy - it marks the collapse of two roles into one party, which is precisely the property that distinguishes lane 1 from the other two. `author-merge` would erase that. **Keep Kai's slugs exactly as proposed.** The naming question is closed. ### The shared concept the slugs should carry into the prose Lanes 2 and 3 share **"defers the merge."** That is one behaviour with two destinations, and it is already the strictest rule in the current doctrine - line 96's "NEVER merge on `pull-request`." The rewritten prose should state deferral once as the shared property of both reviewer lanes rather than restating a prohibition per lane. Lane 1 is the exception: the author does not defer, and line 95's "ALWAYS merge your own pull request" applies there and only there. ### Confirms the rejection of literal `tpm` Kai's lane 2 reads "a reviewer agent (**tpm, another engineer, etc**)." The gate holder is **any** agent seat, not specifically `tpm`. So `agent-reviewer-merge` is correct and a hypothetical `tpm-merge` would have been wrong on two counts - non-durable across roster reflows, and too narrow even today. ### Revised acceptance Replacing items 7 through 9: 7. The three PR lanes are `author-author-merge`, `agent-reviewer-merge`, and `human-reviewer-merge`, defined by Kai's three sentences above. 8. `merge-remote-main` and `remote-branch-only` are unchanged. 9. The contradictions at lines 70, 71, 88, and 96 are removed by construction, since each new slug has exactly one meaning and names its gate holder. 10. Line 88's naming rule is restated: a lane slug names what the agent does **and who holds the merge gate**, since the gate holder is what distinguishes lanes 2 and 3 and cannot be expressed otherwise. 11. Deferral is stated once as the shared property of the two reviewer lanes. 12. Five frontmatter edits: `pull-request-and-merge` becomes `author-author-merge` in agentic-os, ward, infrastructure, deploy, and sirens-echo. Nothing else moves, since `pull-request` and `remote-branch-only` have zero declarations.
Author
Member

Correction: author-author-merge becomes agent-author-merge

The previous comment defended author-author-merge on the grounds that the doubling "marks the collapse of two roles into one party." That was a rationalisation constructed around a probable typo, not Kai's reasoning, and it should not have been written as a settled justification. Withdrawn.

Kai's three sentences give the actual pattern. Every one opens with "agent author creates the PR," and the slugs vary on two axes - who acts, and in what role:

author reviewer
agent agent-author-merge agent-reviewer-merge
human (empty) human-reviewer-merge

So the family is <actor>-<role>-merge:

  • agent-author-merge - the agent, in its author role, merges its own pull request
  • agent-reviewer-merge - an agent, in a reviewer role, merges
  • human-reviewer-merge - a human, in a reviewer role, merges

agent-reviewer and human-reviewer are both actor-plus-role. author-author is not - "author" is a role with no actor, so its first token carries no information. agent-author completes the grid.

The empty cell is meaningful rather than an oversight: human-author-merge does not exist because humans do not author on these lanes. Every lane in this family starts with an agent writing the code. If that ever stops being true, the grid already has the slot.

This also reads correctly in frontmatter. workflow: agent-author-merge states that an agent wrote it and an agent landed it. author-author-merge states neither.

Superseding acceptance item 7

  1. The three PR lanes are agent-author-merge, agent-reviewer-merge, and human-reviewer-merge, defined by Kai's three sentences. The naming pattern is <actor>-<role>-merge, and the pattern itself should be stated in the doctrine so a future lane is named by rule rather than by precedent.

Item 12's five frontmatter edits now write agent-author-merge into agentic-os, ward, infrastructure, deploy, and sirens-echo - subject to the per-repo lane review currently in progress, which may move some of those five to a different lane entirely.

## Correction: `author-author-merge` becomes `agent-author-merge` The previous comment defended `author-author-merge` on the grounds that the doubling "marks the collapse of two roles into one party." **That was a rationalisation constructed around a probable typo, not Kai's reasoning, and it should not have been written as a settled justification.** Withdrawn. Kai's three sentences give the actual pattern. Every one opens with "agent author creates the PR," and the slugs vary on two axes - **who** acts, and **in what role**: | | author | reviewer | |---|---|---| | **agent** | `agent-author-merge` | `agent-reviewer-merge` | | **human** | *(empty)* | `human-reviewer-merge` | So the family is **`<actor>-<role>-merge`**: * **`agent-author-merge`** - the agent, in its author role, merges its own pull request * **`agent-reviewer-merge`** - an agent, in a reviewer role, merges * **`human-reviewer-merge`** - a human, in a reviewer role, merges `agent-reviewer` and `human-reviewer` are both actor-plus-role. `author-author` is not - "author" is a role with no actor, so its first token carries no information. `agent-author` completes the grid. The empty cell is meaningful rather than an oversight: **`human-author-merge` does not exist because humans do not author on these lanes.** Every lane in this family starts with an agent writing the code. If that ever stops being true, the grid already has the slot. This also reads correctly in frontmatter. `workflow: agent-author-merge` states that an agent wrote it and an agent landed it. `author-author-merge` states neither. ### Superseding acceptance item 7 7. The three PR lanes are **`agent-author-merge`**, `agent-reviewer-merge`, and `human-reviewer-merge`, defined by Kai's three sentences. The naming pattern is `<actor>-<role>-merge`, and the pattern itself should be stated in the doctrine so a future lane is named by rule rather than by precedent. Item 12's five frontmatter edits now write `agent-author-merge` into agentic-os, ward, infrastructure, deploy, and sirens-echo - subject to the per-repo lane review currently in progress, which may move some of those five to a different lane entirely.
Author
Member

Per-repo lane assignment, decided by Kai 2026-08-22

All 32 active repos assigned. Survey and decisions complete.

human-reviewer-merge - 5

coilysiren/website · coilysiren/coilysiren · coilyco-bridge/.github · coilyco-flight-deck/.github · coilyco-gaming/.github

The public identity surface. An agent cannot check whether something sounds like Kai.

agent-reviewer-merge - 4

coilyco-bridge/deploy · coilyco-flight-deck/infrastructure · coilyco-bridge/agentic-os-kai · coilyco-flight-deck/agent-proxy

Live systems and personal operating context. The gate here is judgment, not CI.

agent-author-merge - 5

coilyco-flight-deck/agentic-os · coilyco-flight-deck/ward · coilyco-flight-deck/umbra · coilyco-flight-deck/agent-compose · coilyco-gaming/sirens-echo

Strong automated gates already hold the line - pre-commit catalog, CI, evals.

merge-remote-main - 18

mcp-beaver · node-stats-mcp · bluesky-mcp · lunch-money-k8s · homebrew-tap · scoop-bucket · eco-app · eco-mods · eco-ops · factorio-mods · factory-game-v3 · galaxy-gen · steam-ops · inbox · lore · voice-corpus · agentic-os-hardware · agentic-os-xxx

Low blast radius, mostly private or trivially reversible. The publish targets are automated formula updates where a PR gate would fight the automation.

remote-branch-only - 0

Still declared by nobody.

The principle behind the split, worth writing into doctrine

Kai's choices are consistent with one rule: author-merge where an automated gate already holds the line, reviewer-merge where the gate is human judgment.

  • agentic-os, ward, agent-compose, sirens-echo, umbra - pre-commit catalog, CI, and evals verify correctness mechanically
  • deploy, infrastructure - CI cannot tell you a rollout was a bad idea
  • agentic-os-kai, agent-proxy - nothing automated checks whether operating context or model routing is right

Stating that rule in the doctrine means the next repo gets assigned by principle rather than by copying a neighbour. Recommended as a new acceptance item.

What actually changes

14 repos change, 18 stay put. Of the 14, only three are pure renames:

repo today becomes kind
agentic-os pull-request-and-merge agent-author-merge rename
ward pull-request-and-merge agent-author-merge rename
sirens-echo pull-request-and-merge agent-author-merge rename
deploy pull-request-and-merge agent-reviewer-merge behaviour
infrastructure pull-request-and-merge agent-reviewer-merge behaviour
agentic-os-kai merge-remote-main agent-reviewer-merge behaviour
agent-proxy merge-remote-main agent-reviewer-merge behaviour
agent-compose merge-remote-main agent-author-merge behaviour
umbra (none) agent-author-merge new
website merge-remote-main human-reviewer-merge behaviour
coilysiren merge-remote-main human-reviewer-merge behaviour
3x .github merge-remote-main human-reviewer-merge behaviour

Acceptance item 12 is superseded: it is 14 frontmatter edits, not five, and eleven of them change how work actually lands.

Blocking dependency: agent-reviewer-merge has no mechanism

This is the one thing that should stop a naive implementation.

Four repos are about to declare a lane that requires a reviewer agent to pick up a pull request and merge it. Nothing dispatches that reviewer today. The current doctrine names "the director merge lane" three times and never says who invokes it, on what trigger, or how the authoring agent signals that a PR is ready for review.

Two of those four - deploy and infrastructure - are the highest-issue repos in the estate at 131 open each. Declaring the lane before the mechanism exists means work in them stops at an open PR nobody collects, which is precisely the litter this whole issue set exists to prevent.

Sequencing that avoids it:

  1. Land the slug rename and doctrine rewrite, moving the three pure-rename repos to agent-author-merge. Safe immediately - no behaviour change.
  2. Move the human-reviewer-merge repos. Also safe - Kai is the mechanism, and those five carry 18 open issues between them.
  3. Do not move the four agent-reviewer-merge repos until reviewer dispatch exists. They stay on their current lanes until then.
  4. umbra and agent-compose can take agent-author-merge at step 1 - neither needs a reviewer.

That reviewer-dispatch mechanism is not scoped anywhere yet and needs its own issue. It should answer: what triggers a review, which seat is selected, how the author signals readiness, and what happens when no reviewer is available. agent-compose#321 gives the reviewing seat its close and revert authority but does not say how it gets invoked.

Added acceptance

  1. The assignment rule - automated gate implies author-merge, judgment gate implies reviewer-merge - is stated in the doctrine so future repos are assigned by principle.
  2. The four agent-reviewer-merge repos are not migrated until reviewer dispatch exists. Sequencing above.
  3. A separate issue scopes reviewer dispatch: trigger, seat selection, readiness signal, and the no-reviewer-available path.
## Per-repo lane assignment, decided by Kai 2026-08-22 All 32 active repos assigned. Survey and decisions complete. ### `human-reviewer-merge` - 5 `coilysiren/website` · `coilysiren/coilysiren` · `coilyco-bridge/.github` · `coilyco-flight-deck/.github` · `coilyco-gaming/.github` The public identity surface. An agent cannot check whether something sounds like Kai. ### `agent-reviewer-merge` - 4 `coilyco-bridge/deploy` · `coilyco-flight-deck/infrastructure` · `coilyco-bridge/agentic-os-kai` · `coilyco-flight-deck/agent-proxy` Live systems and personal operating context. The gate here is judgment, not CI. ### `agent-author-merge` - 5 `coilyco-flight-deck/agentic-os` · `coilyco-flight-deck/ward` · `coilyco-flight-deck/umbra` · `coilyco-flight-deck/agent-compose` · `coilyco-gaming/sirens-echo` Strong automated gates already hold the line - pre-commit catalog, CI, evals. ### `merge-remote-main` - 18 `mcp-beaver` · `node-stats-mcp` · `bluesky-mcp` · `lunch-money-k8s` · `homebrew-tap` · `scoop-bucket` · `eco-app` · `eco-mods` · `eco-ops` · `factorio-mods` · `factory-game-v3` · `galaxy-gen` · `steam-ops` · `inbox` · `lore` · `voice-corpus` · `agentic-os-hardware` · `agentic-os-xxx` Low blast radius, mostly private or trivially reversible. The publish targets are automated formula updates where a PR gate would fight the automation. ### `remote-branch-only` - 0 Still declared by nobody. ## The principle behind the split, worth writing into doctrine Kai's choices are consistent with one rule: **author-merge where an automated gate already holds the line, reviewer-merge where the gate is human judgment.** * `agentic-os`, `ward`, `agent-compose`, `sirens-echo`, `umbra` - pre-commit catalog, CI, and evals verify correctness mechanically * `deploy`, `infrastructure` - CI cannot tell you a rollout was a bad idea * `agentic-os-kai`, `agent-proxy` - nothing automated checks whether operating context or model routing is *right* Stating that rule in the doctrine means the next repo gets assigned by principle rather than by copying a neighbour. Recommended as a new acceptance item. ## What actually changes **14 repos change, 18 stay put.** Of the 14, only three are pure renames: | repo | today | becomes | kind | |---|---|---|---| | agentic-os | `pull-request-and-merge` | `agent-author-merge` | rename | | ward | `pull-request-and-merge` | `agent-author-merge` | rename | | sirens-echo | `pull-request-and-merge` | `agent-author-merge` | rename | | deploy | `pull-request-and-merge` | `agent-reviewer-merge` | **behaviour** | | infrastructure | `pull-request-and-merge` | `agent-reviewer-merge` | **behaviour** | | agentic-os-kai | `merge-remote-main` | `agent-reviewer-merge` | **behaviour** | | agent-proxy | `merge-remote-main` | `agent-reviewer-merge` | **behaviour** | | agent-compose | `merge-remote-main` | `agent-author-merge` | **behaviour** | | umbra | *(none)* | `agent-author-merge` | **new** | | website | `merge-remote-main` | `human-reviewer-merge` | **behaviour** | | coilysiren | `merge-remote-main` | `human-reviewer-merge` | **behaviour** | | 3x .github | `merge-remote-main` | `human-reviewer-merge` | **behaviour** | Acceptance item 12 is superseded: it is **14 frontmatter edits**, not five, and eleven of them change how work actually lands. ## Blocking dependency: `agent-reviewer-merge` has no mechanism **This is the one thing that should stop a naive implementation.** Four repos are about to declare a lane that requires a reviewer agent to pick up a pull request and merge it. **Nothing dispatches that reviewer today.** The current doctrine names "the director merge lane" three times and never says who invokes it, on what trigger, or how the authoring agent signals that a PR is ready for review. Two of those four - `deploy` and `infrastructure` - are the highest-issue repos in the estate at 131 open each. Declaring the lane before the mechanism exists means work in them stops at an open PR nobody collects, which is precisely the litter this whole issue set exists to prevent. **Sequencing that avoids it:** 1. Land the slug rename and doctrine rewrite, moving the three pure-rename repos to `agent-author-merge`. Safe immediately - no behaviour change. 2. Move the `human-reviewer-merge` repos. Also safe - Kai is the mechanism, and those five carry 18 open issues between them. 3. **Do not move the four `agent-reviewer-merge` repos until reviewer dispatch exists.** They stay on their current lanes until then. 4. `umbra` and `agent-compose` can take `agent-author-merge` at step 1 - neither needs a reviewer. That reviewer-dispatch mechanism is not scoped anywhere yet and needs its own issue. It should answer: what triggers a review, which seat is selected, how the author signals readiness, and what happens when no reviewer is available. `agent-compose#321` gives the reviewing seat its close and revert authority but does not say how it gets invoked. ## Added acceptance 13. The assignment rule - automated gate implies author-merge, judgment gate implies reviewer-merge - is stated in the doctrine so future repos are assigned by principle. 14. The four `agent-reviewer-merge` repos are **not** migrated until reviewer dispatch exists. Sequencing above. 15. A separate issue scopes reviewer dispatch: trigger, seat selection, readiness signal, and the no-reviewer-available path.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-flight-deck/agentic-os#1189
No description provided.