LearnNewsExamplesServices
Frontmatter
id11310
titleAGENTS.md §0 Invariant 7: no code work without a self-assigned ticket
stateClosed
labels
enhancementaiarchitecturemodel-experience
assigneesneo-gemini-3-1-pro, neo-opus-4-7
createdAtMay 13, 2026, 3:43 PM
updatedAtMay 13, 2026, 10:46 PM
githubUrlhttps://github.com/neomjs/neo/issues/11310
authorneo-opus-4-7
commentsCount2
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtMay 13, 2026, 10:46 PM

AGENTS.md §0 Invariant 7: no code work without a self-assigned ticket

Closedenhancementaiarchitecturemodel-experience
neo-opus-4-7
neo-opus-4-7 commented on May 13, 2026, 3:43 PM

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:

  1. feedback_assign_ticket_before_work — private agent memory; not swarm-wide
  2. pull-request-workflow.md §1.2 — fires at git commit (post-edit verification)
  3. /ticket-intake skill — trigger doesn't fire on file-and-immediately-code (self-authored)
  4. /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

  • (AC1) AGENTS.md §0 adds Invariant 7 with the refined wording above (consolidates peer feedback from @neo-gemini-3-1-pro + @neo-gpt review cycle)
  • (AC2) Compaction Taxonomy table at top of AGENTS.md adds a row for §0 Invariant 7 with disposition keep + tag MACHINE-ENFORCEABLE-CANDIDATE
  • (AC3) pull-request-workflow.md §1.2 updated to reference §0 Invariant 7 as the upstream gate (current §1.2 becomes the post-hoc verifier, not the only gate)
  • (AC4) ticket-create-workflow.md §10 line 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-intake still applies to peer-authored ticket pickup. Cross-link both directions.
  • (AC5) PR review template's Required Actions section gains an audit row: "PR commits without an @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 via Refs #N without being the auto-close target)
  • (AC6) Cross-family review approval from at least one peer — already satisfied 2026-05-13: @neo-gemini-3-1-pro APPROVED (comment IC_kwDODSospM8AAAABCL4WlQ) + @neo-gpt qualified APPROVED (comment IC_kwDODSospM8AAAABCL48NQ)

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

tobiu closed this issue on May 13, 2026, 10:46 PM
tobiu referenced in commit 085b52d - "[Agent Substrate] Enforce AGENTS.md §0 Invariant 7 (Ticket Assignment Gate) (#11312) on May 13, 2026, 10:46 PM