Friction Source
Surfaced 2026-05-13 by @tobiu after V-B-A on swarm coordination patterns:
"never write code, without working on a self-assigned ticket. this could resolve multiple edge cases."
Empirical anchor (same session, 2026-05-13):
- 139 v13-era "real" tickets across the swarm; 18 had no assignee (Gemini 12 / Opus 6 / GPT 0)
- GraphQL timeline check on 10 no-assignee resolved tickets: zero
AssignedEvent entries across the entire set. Skill was bypassed entirely, not partially followed.
- Time-to-close on the bypass pattern: 1 minute to 2 hours (file-and-immediately-code path)
- Bypass shape:
gh issue create → immediate PR → Resolves #N closes ticket; /ticket-intake never fires because its trigger is "Picking up an existing assigned ticket"
- My own #11306, #11307, #11308 (filed same session) had this gap until self-corrected — substrate-level pattern, not per-agent
Substrate-conflict V-B-A anchor: ticket-create-workflow.md §10 line 130 currently reads "Assignment (manage_issue_assignees) belongs to the intake process, not the creation process." This sentence is itself the source of the bypass pattern — agents file via create_issue, see §10 saying "don't assign at create," and then skip /ticket-intake entirely. AC4 below resolves this contradiction.
Why a §0 Invariant (not a skill enhancement)
The existing substrate fragments don't compose cleanly:
feedback_assign_ticket_before_work — private agent memory; not swarm-wide
pull-request-workflow.md §1.2 — fires at git commit (post-edit verification)
/ticket-intake skill — trigger doesn't fire on file-and-immediately-code (self-authored)
/ticket-create skill §10 — actively tells agents NOT to assign at create (conflict)
Four different gates, all partial or actively conflicting. The right shape is a single §0 invariant: "no tracked repository file modification without a self-assigned ticket." Mechanically verifiable, no conditional exceptions, always-loaded — same shape as the existing 6 invariants.
The Fix
Add Invariant 7 to AGENTS.md §0 (just below current Invariant 6):
7. **No tracked repository file modification without a self-assigned ticket.** Before editing any git-tracked file (code, tests, substrate docs, agent skills, workflow YAML, etc.), verify an existing ticket has you in `assignees`. Self-authored: claim assignment to `@me` via `manage_issue_assignees` immediately after `create_issue` (or atomically via `create_issue` if/when the MCP tool supports an `assignees` alias — currently unverified, see #11308). Peer-authored: claim via `manage_issue_assignees` before first edit. Verified post-hoc at PR commit per `pull-request-workflow.md §1.2`.
Also update the Compaction Taxonomy table in AGENTS.md (rows 33-61) to add a row for §0 Invariant 7 with disposition keep + tag MACHINE-ENFORCEABLE-CANDIDATE.
Wording precision rationale (peer-review convergence 2026-05-13):
- "tracked repository file modification" (not "code work" / not broad "repository modification"): mechanically scoped to git-tracked file edits. Excludes pure project-board state changes, label-only edits, comment-only activity — none of which need a ticket-and-assignment gate. @neo-gpt's refinement vs @neo-gemini-3-1-pro's broader phrasing; chose GPT's framing for precision.
- Substrate docs explicitly covered. Per @neo-gemini-3-1-pro feedback, the parenthetical enumerates substrate types (substrate docs, agent skills, workflow YAML) rather than implying via "etc."
- Defensive
create_issue parameter wording. Per @neo-gpt: don't declare create_issue({assignees:['@me']}) as normative without verifying the MCP tool actually supports the alias. Current safe phrasing: claim via manage_issue_assignees immediately after create; #11308 handles the parameter-support verification + atomic optimization.
Edge cases the invariant collapses
| Pattern |
Pre-invariant behavior |
Post-invariant behavior |
| File self-authored ticket + immediately code |
No assignment, /ticket-intake never fires, §10 actively tells you not to assign |
MUST claim assignment via manage_issue_assignees before first file edit |
| Pick up peer's ticket |
/ticket-intake mandates assignment IF skill is invoked |
§0 makes the assignment unconditional regardless of skill invocation |
| Discovered need mid-PR (need to refactor X) |
"Quick fix" pattern: agent edits without ticket |
MUST file ticket first OR confirm existing assigned ticket covers the scope |
| Substrate-doc edit during code work |
Implicit "covered by parent ticket" |
Parent ticket must list agent as assignee — substrate edits are explicitly covered |
Acceptance Criteria
Out of Scope
- Mechanical CI gate auto-rejecting PRs with unassigned target tickets — separate ticket if needed; invariant-level discipline first
- Verifying / extending
create_issue MCP tool to support assignees parameter at create-time — covered by sibling #11308 (/ticket-create defaults). #11310 (policy) and #11308 (implementation) stay separate per peer-review convergence.
- Backfilling existing no-assignee tickets — manual cleanup orthogonal to the invariant
- Project-board state changes / label-only edits / pure comment activity — these are NOT tracked-file modifications and do NOT need a ticket-and-assignment gate
Avoided Traps
- Putting this in a skill instead of §0 — skills fire conditionally; §0 invariants are always-loaded reflex-level. The bypass pattern's whole problem is that the skill DIDN'T fire. Promotion to §0 closes that class structurally.
- Phrasing as a "should" not "must" — §0 invariants are MUST; conditional softening defeats the purpose.
- "close-target" vs "target ticket" — per @neo-gpt, "close-target" couples the invariant to magic-close semantics (Resolves/Closes/Fixes keywords). An agent can legitimately work on a ticket via
Refs #N (no auto-close, e.g., partial implementation). The invariant gates "are you working on a ticket?" not "which ticket does this PR auto-close?"
- Declaring
create_issue({assignees:['@me']}) normative — per @neo-gpt, the MCP tool's parameter support is unverified. Safe wording describes the discipline (claim @me before first edit), not the specific mechanism.
- Bundling #11310 (policy) with #11308 (implementation) — peer-review consensus: keep them separate to preserve the boundary. Policy ticket = AGENTS.md substrate; implementation ticket =
/ticket-create MCP-default wiring.
- Substrate accretion bypass — this PR is net-expansion to always-loaded substrate (one new line in §0 + one taxonomy row + small §1.2 cross-ref + small §10 rewrite). Per
pull-request-workflow.md §1.1, compress-to-trigger default doesn't apply for §0 invariants (highest-frequency irreversibility per #11217 class). keep is justified — explicit slot-rationale will appear in PR body.
Related
Friction Source
Surfaced 2026-05-13 by @tobiu after V-B-A on swarm coordination patterns:
Empirical anchor (same session, 2026-05-13):
AssignedEvententries across the entire set. Skill was bypassed entirely, not partially followed.gh issue create→ immediate PR →Resolves #Ncloses ticket;/ticket-intakenever fires because its trigger is "Picking up an existing assigned ticket"Substrate-conflict V-B-A anchor:
ticket-create-workflow.md §10line 130 currently reads "Assignment (manage_issue_assignees) belongs to the intake process, not the creation process." This sentence is itself the source of the bypass pattern — agents file viacreate_issue, see §10 saying "don't assign at create," and then skip/ticket-intakeentirely. AC4 below resolves this contradiction.Why a §0 Invariant (not a skill enhancement)
The existing substrate fragments don't compose cleanly:
feedback_assign_ticket_before_work— private agent memory; not swarm-widepull-request-workflow.md §1.2— fires at git commit (post-edit verification)/ticket-intakeskill — trigger doesn't fire on file-and-immediately-code (self-authored)/ticket-createskill §10 — actively tells agents NOT to assign at create (conflict)Four different gates, all partial or actively conflicting. The right shape is a single §0 invariant: "no tracked repository file modification without a self-assigned ticket." Mechanically verifiable, no conditional exceptions, always-loaded — same shape as the existing 6 invariants.
The Fix
Add Invariant 7 to
AGENTS.md §0(just below current Invariant 6):7. **No tracked repository file modification without a self-assigned ticket.** Before editing any git-tracked file (code, tests, substrate docs, agent skills, workflow YAML, etc.), verify an existing ticket has you in `assignees`. Self-authored: claim assignment to `@me` via `manage_issue_assignees` immediately after `create_issue` (or atomically via `create_issue` if/when the MCP tool supports an `assignees` alias — currently unverified, see #11308). Peer-authored: claim via `manage_issue_assignees` before first edit. Verified post-hoc at PR commit per `pull-request-workflow.md §1.2`.Also update the Compaction Taxonomy table in
AGENTS.md(rows 33-61) to add a row for §0 Invariant 7 with dispositionkeep+ tagMACHINE-ENFORCEABLE-CANDIDATE.Wording precision rationale (peer-review convergence 2026-05-13):
create_issueparameter wording. Per @neo-gpt: don't declarecreate_issue({assignees:['@me']})as normative without verifying the MCP tool actually supports the alias. Current safe phrasing: claim viamanage_issue_assigneesimmediately after create; #11308 handles the parameter-support verification + atomic optimization.Edge cases the invariant collapses
manage_issue_assigneesbefore first file editAcceptance Criteria
AGENTS.md §0adds Invariant 7 with the refined wording above (consolidates peer feedback from @neo-gemini-3-1-pro + @neo-gpt review cycle)AGENTS.mdadds a row for §0 Invariant 7 with dispositionkeep+ tagMACHINE-ENFORCEABLE-CANDIDATEpull-request-workflow.md §1.2updated to reference §0 Invariant 7 as the upstream gate (current §1.2 becomes the post-hoc verifier, not the only gate)ticket-create-workflow.md §10line 130 rewritten to remove the contradictory "Assignment belongs to the intake process, not the creation process" sentence. New shape: at-create-or-immediately-after-create assignment is REQUIRED per §0 Invariant 7;/ticket-intakestill applies to peer-authored ticket pickup. Cross-link both directions.@me-assigned target ticket → §0 Invariant 7 violation" (note: "target ticket" not "close-target" — per @neo-gpt to avoid magic-close semantic coupling; a ticket can be the work-target viaRefs #Nwithout being the auto-close target)IC_kwDODSospM8AAAABCL4WlQ) + @neo-gpt qualified APPROVED (commentIC_kwDODSospM8AAAABCL48NQ)Out of Scope
create_issueMCP tool to supportassigneesparameter at create-time — covered by sibling #11308 (/ticket-createdefaults). #11310 (policy) and #11308 (implementation) stay separate per peer-review convergence.Avoided Traps
Refs #N(no auto-close, e.g., partial implementation). The invariant gates "are you working on a ticket?" not "which ticket does this PR auto-close?"create_issue({assignees:['@me']})normative — per @neo-gpt, the MCP tool's parameter support is unverified. Safe wording describes the discipline (claim @me before first edit), not the specific mechanism./ticket-createMCP-default wiring.pull-request-workflow.md §1.1,compress-to-triggerdefault doesn't apply for §0 invariants (highest-frequency irreversibility per #11217 class).keepis justified — explicit slot-rationale will appear in PR body.Related
/ticket-createprojects:+assignees:defaults — the implementation arm). Cross-linked both directions.feedback_assign_ticket_before_workpull-request-workflow.md §1.2ticket-assignment-pre-flight-gate