Context
Operator friction item, 2026-07-25, raised as an explicit friction→gold prompt: "friction→gold means to not take everything 'valid as written', but to keep an eye out on what makes sense, and what does not."
Two observed instances:
ticket-intake fired on a ticket its own author wrote minutes earlier. Happened in this session: #15891 was authored through ticket-create's full six-stage challenge chain, then picked up ~20 minutes later in the same context window, where intake's trigger ("immediately when assigned a new ticket") nominally demands a 31,608-byte re-validation of the author's own fresh reasoning.
epic-review fired on a self-authored epic. Operator-observed: a session graduated an ideation sandbox → epic → subs, then the same author, in the same context window, ran epic-review on their own epic before starting a sub.
Both gates are consumption-side duals of a creation-side gate that already ran: ticket-create ↔ ticket-intake, epic-create ↔ epic-review. They were designed for the cross-author and stale-artifact cases and are currently applied reflexively to the self-author, same-session case, where they re-derive reasoning that is still live in context.
The Problem
Neither trigger carries an authorship or freshness carve
Verbatim from the SKILL.md frontmatter:
ticket-intake: "Use this skill immediately when assigned a new ticket, before checking out a branch or writing any codebase modifications."
epic-review: "Use this skill when an agent is about to pick up its first sub from an unreviewed epic (per model-identity)."
epic-review's "per model-identity" clause actively guarantees the pathology: the epic's author is a model identity, so authoring an epic and then picking up its first sub triggers a self-review by construction.
Cost of a reflexive invocation
| Gate |
Bytes |
~Tokens |
ticket-intake |
31,608 |
~8,780 |
epic-review |
25,370 |
~7,040 |
| pair |
56,978 |
~15,800 |
Against the Codex flatrate window (~258K before compaction) a reflexively-invoked pair is ~6% of the window. Measured this session, ~90% of token cost is re-reading context, so a payload loaded once is paid again on every subsequent message and again after every compaction.
The operator's proposed rule is falsified by the operator's own caveat
The proposal was "same author, less than 24h old, no need to use it", paired with the caveat "old is a tricky pony when we merge 20-40 PRs a day." The caveat wins. Measured on origin/dev:
| Window |
Commits |
Rate |
| last 1d |
41 |
41/day |
| last 3d |
90 |
30/day |
| last 7d |
207 |
29/day |
24 hours is 30–40 merges of drift. Wall-clock age is a weak staleness proxy in this repo. The right question is not how old is the ticket but how much moved underneath it.
The Architectural Reality
.agents/skills/ticket-intake/SKILL.md + references/ (31,608B) — the Pre-Execution Reflection Gate; creation-side dual is ticket-create.
.agents/skills/epic-review/SKILL.md + references/ (25,370B) — six-stage pre-work epic gate, "per-agent-per-epic one-shot"; creation-side dual is epic-create.
.claude/CLAUDE.md §edge_case_triggers carries "Ticket Creation Freshness: Before any create_issue, invoke ticket-create" — the creation side is turn-loaded and unconditional. The consumption side is skill-triggered and is where the carve belongs. Turn-loaded substrate is Tier-4 and out of scope for an agent-authored change; this ticket touches only the two skills.
- ADR 0008 §2.1 governs the frontmatter
description contract that both triggers live in; the carve is a trigger-language change, so it is a Map edit, not new payload. create-skill consulted per ticket-create §1b.
- Sibling precedent for narrowing rather than deleting a gate: #15891 / PR #15893 (
post-review-pickup 20,396 → 7,852B), same operator directive lineage.
The Fix (direction — implementer refines)
Make both gates authorship- and drift-aware, keyed on externally-checkable facts rather than wall-clock age.
Proposed three-tier carve, applied to both skills:
| Case |
Gate behavior |
| Different author |
Full gate, unchanged. This is what the gates were built for and the change must not weaken it. |
| Self-authored, same session |
Exempt. The creation-side dual ran in this context window and its reasoning is still live. Re-running the consumption-side dual re-derives the author's own last hour. |
| Self-authored, different session |
Narrowed probe, not the full payload. The reasoning is gone from context, but the artifact is still yours — so run the drift check only, and escalate to the full gate only if it fires. |
The drift probe, mechanical and cheap:
git log origin/dev --since="<ticket createdAt>" --name-only
intersected with the paths the ticket declares in its Architectural Reality / Fix sections. Zero intersection = reality did not move underneath this ticket, and intake's core question ("did Neo reality change?") is answered no without loading 31KB. A non-empty intersection is exactly when the gate earns its cost, and it names the specific files to re-check.
Why this beats the 24h rule: it measures the thing the gate actually cares about. A ticket 3 days old whose surface nobody touched is fresher than a 6-hour-old ticket sitting under 15 merges.
Every exemption input is externally checkable — session identity, GitHub issue author, and git log — so the carve cannot become a self-declared loophole. That is the load-bearing constraint: an agent must not be able to talk itself out of a gate.
Additionally: epic-review's "per model-identity" clause should read "per model-identity other than the epic's author", which alone removes the operator-observed instance.
Acceptance Criteria
Out of Scope
- Turn-loaded substrate.
.claude/CLAUDE.md §edge_case_triggers' "Ticket Creation Freshness" line is Tier-4 operator authority; this ticket does not touch it. If the carve implies a turn-loaded edit, surface it rather than making it.
- The creation-side gates.
ticket-create and epic-create stay unconditional — the carve exists precisely because the creation-side gate ran.
- Shortening the two payloads' content. That is the #15891-class lane and should be a separate ticket per skill; this one changes only when they fire.
- Other pre-flight gates (
structural-pre-flight, turn-memory-pre-flight, architecture-pre-flight). They may have the same shape, but each needs its own creation-side-dual analysis; bundling would make the loophole surface unreviewable.
- Any mechanical enforcement of the carve. It is trigger language read by the agent, not a lint.
Avoided Traps
- The 24h rule as stated. Falsified by the measured 29–41 commits/day; it would exempt tickets sitting under 30+ merges while still gating a week-old ticket nobody's surface moved under.
- Self-declared freshness. "I judged this ticket still valid" is the loophole shape L3 warns about. Every input here is external: session id, issue author,
git log. If an implementer finds themselves adding a judgment call, that is the signal the carve is being widened.
- Deleting the gates. The cross-author case is the majority case and the gates are load-bearing there — a stale ticket picked up by a different agent is exactly how wrong work gets built. This narrows the trigger; it does not weaken the gate.
- Exempting on authorship alone. A ticket you wrote three weeks ago is not fresh — your reasoning is gone from context, which is precisely when intake pays. Session-scope is doing the real work in tier 2, not authorship.
- Assuming same-session implies same-context. After a compaction the author's reasoning may be as gone as another agent's. If a cheap compaction signal is available, tier 2 should key on it; if not, note the residual honestly rather than pretending session-id is a proxy for context continuity.
Decision Record impact
aligned-with ADR 0008 — the change is trigger language in the SKILL.md Map, within the §2.1 frontmatter contract. No ADR is amended or challenged.
ADR successor-risk: adr-aligned — artifact dated 2026-07-25; ADR 0008 governs skill-shape and this is a Map-level trigger edit; evidence = both SKILL.md frontmatter blocks quoted above; route continue.
Related
- #13652 (Epic — mechanical enforcement replaces prompt-machinery; skill cadence is named in its intended solution) — candidate parent.
- #15891 / PR #15893 — sibling reduction under the same operator directive; precedent for narrowing substrate rather than deleting it.
- #15892 — the ADR-0019 twin/export amendment from the same review session; unrelated surface, same friction→gold lineage.
ticket-create §1b Meta-Skill Sweep and ADR 0008 §2.1 — the gates this ticket's own implementation must satisfy.
Live latest-open sweep: checked latest 20 open issues at 2026-07-25T10:07Z plus a semantic search over all states for intake/exemption/freshness-gate scope — nearest hits (#12990, #15790) are both CLOSED and unrelated; no equivalent found. A2A in-flight claim sweep at 2026-07-25T09:51Z, all read-states: no claim on skill-trigger scope; newest peer traffic is 2026-07-25T00:37Z (~9.5h stale, roster parked by operator).
Origin Session ID: cb8b1069-54cc-43fd-943f-0e20b45661c8
Retrieval Hint: query_raw_memories("ticket-intake epic-review self-authored same-session exemption drift probe not wall-clock age")
Authored by Grace (@neo-opus-grace, Opus 5)
Amendment 1 (2026-07-25) — authorship was the wrong axis
@tobiu raised the case that breaks the three-tier carve above: different author, but hot context. An ideation-sandbox graduation you participated in, where a peer authors the epic and its subs. Authorship says "different author → full gate"; context says "I was there."
The V-B-A inverts the intuition, so the carve does not widen here. Reading what epic-review actually checks (epic-review-workflow.md):
| Stage |
What it checks |
What a discussion participant holds |
| 1 — Roadmap Fit |
does the epic fit the roadmap |
mostly agreed in the discussion — cite, don't re-derive |
| 2 — Approach Elegance |
is the approach right |
same |
| 2.5 — Source Discussion Criteria Mapping |
"Has the Epic dropped any graduation criteria established in its source Discussion?" — mapping presence, Decision Record preservation, mapping completeness; unexplained deferrals are failures |
the participant is the best-qualified reviewer alive for this stage |
| 3 — Sub-Structure Coherence |
coverage, overlaps, phase boundaries, missing phases, scope creep, structural pre-flight |
nothing — the peer's decomposition |
| 3.1 — Evidence Matrix seeding |
per-AC L1–L4 evidence classification |
nothing |
| 4 — Prescription Layer |
is each sub at the right layer |
nothing |
| 5 — Avoided Traps |
completeness of rejected alternatives |
partial |
Stage 2.5's own first step is "Fetch the source Discussion body and extract the Graduation Criteria." A participant already holds that, so the highest-value stage becomes nearly free — while Stages 3–4, the peer's independent transformation of discussion → epic → subs, are entirely unseen regardless of participation.
Conclusion: participation lowers the COST of the most valuable stage; it does not remove the need for the review. The correct handling is narrowing and re-ordering, not exemption:
- Stages 1–2: cite the discussion position instead of re-deriving it (link the comment, one line).
- Stage 2.5: run it — from context, no Extraction round-trip.
- Stages 3 / 3.1 / 4 / 5: run in full. Unseen work.
The corrected general axis
Authorship was a proxy. The real question is what have you already seen — so the carve scopes to the unseen, not to who typed it:
| What you hold |
Gate behavior |
| the artifact AND its reasoning (self-authored, same session) |
exempt |
| the inputs but not the transformation (discussion participant, peer-authored epic) |
run the stages covering the transformation; cite the rest |
| neither |
full gate |
This subsumes both observed cases and is still externally checkable: authorship and session identity from the artifact and the session id; participation from the Discussion's own comment thread (did you post in it?), which is a public fact, not a self-assessment.
AC deltas from this amendment
Trap added
- Reading "hot context" as "already reviewed". The discussion is the input to the epic; the epic is a transformation of it. Holding the input tells you nothing about the transformation, and Stage 3's whole purpose is checking the transformation. An agent that exempts itself here would be skipping the only stages it was never qualified to skip.
Context
Operator friction item, 2026-07-25, raised as an explicit friction→gold prompt: "friction→gold means to not take everything 'valid as written', but to keep an eye out on what makes sense, and what does not."
Two observed instances:
ticket-intakefired on a ticket its own author wrote minutes earlier. Happened in this session: #15891 was authored throughticket-create's full six-stage challenge chain, then picked up ~20 minutes later in the same context window, where intake's trigger ("immediately when assigned a new ticket") nominally demands a 31,608-byte re-validation of the author's own fresh reasoning.epic-reviewfired on a self-authored epic. Operator-observed: a session graduated an ideation sandbox → epic → subs, then the same author, in the same context window, ranepic-reviewon their own epic before starting a sub.Both gates are consumption-side duals of a creation-side gate that already ran:
ticket-create↔ticket-intake,epic-create↔epic-review. They were designed for the cross-author and stale-artifact cases and are currently applied reflexively to the self-author, same-session case, where they re-derive reasoning that is still live in context.The Problem
Neither trigger carries an authorship or freshness carve
Verbatim from the SKILL.md frontmatter:
ticket-intake: "Use this skill immediately when assigned a new ticket, before checking out a branch or writing any codebase modifications."epic-review: "Use this skill when an agent is about to pick up its first sub from an unreviewed epic (per model-identity)."epic-review's "per model-identity" clause actively guarantees the pathology: the epic's author is a model identity, so authoring an epic and then picking up its first sub triggers a self-review by construction.Cost of a reflexive invocation
ticket-intakeepic-reviewAgainst the Codex flatrate window (~258K before compaction) a reflexively-invoked pair is ~6% of the window. Measured this session, ~90% of token cost is re-reading context, so a payload loaded once is paid again on every subsequent message and again after every compaction.
The operator's proposed rule is falsified by the operator's own caveat
The proposal was "same author, less than 24h old, no need to use it", paired with the caveat "old is a tricky pony when we merge 20-40 PRs a day." The caveat wins. Measured on
origin/dev:24 hours is 30–40 merges of drift. Wall-clock age is a weak staleness proxy in this repo. The right question is not how old is the ticket but how much moved underneath it.
The Architectural Reality
.agents/skills/ticket-intake/SKILL.md+references/(31,608B) — the Pre-Execution Reflection Gate; creation-side dual isticket-create..agents/skills/epic-review/SKILL.md+references/(25,370B) — six-stage pre-work epic gate, "per-agent-per-epic one-shot"; creation-side dual isepic-create..claude/CLAUDE.md§edge_case_triggers carries "Ticket Creation Freshness: Before anycreate_issue, invoketicket-create" — the creation side is turn-loaded and unconditional. The consumption side is skill-triggered and is where the carve belongs. Turn-loaded substrate is Tier-4 and out of scope for an agent-authored change; this ticket touches only the two skills.descriptioncontract that both triggers live in; the carve is a trigger-language change, so it is a Map edit, not new payload.create-skillconsulted perticket-create§1b.post-review-pickup20,396 → 7,852B), same operator directive lineage.The Fix (direction — implementer refines)
Make both gates authorship- and drift-aware, keyed on externally-checkable facts rather than wall-clock age.
Proposed three-tier carve, applied to both skills:
The drift probe, mechanical and cheap:
git log origin/dev --since="<ticket createdAt>" --name-onlyintersected with the paths the ticket declares in its Architectural Reality / Fix sections. Zero intersection = reality did not move underneath this ticket, and intake's core question ("did Neo reality change?") is answered
nowithout loading 31KB. A non-empty intersection is exactly when the gate earns its cost, and it names the specific files to re-check.Why this beats the 24h rule: it measures the thing the gate actually cares about. A ticket 3 days old whose surface nobody touched is fresher than a 6-hour-old ticket sitting under 15 merges.
Every exemption input is externally checkable — session identity, GitHub issue author, and
git log— so the carve cannot become a self-declared loophole. That is the load-bearing constraint: an agent must not be able to talk itself out of a gate.Additionally:
epic-review's "per model-identity" clause should read "per model-identity other than the epic's author", which alone removes the operator-observed instance.Acceptance Criteria
ticket-intakeandepic-reviewfrontmatter triggers carry the authorship carve; both remain within ADR 0008 §2.1's Map contract and the router byte budget.epic-review's "per model-identity" clause excludes the epic's own author.git logshape above or better), and lives in the Map, not behind another payload read..agents/skillsMarkdown delta is negative or pointer-sized;node ai/scripts/lint/lint-skill-manifest.mjs --base origin/devgreen.Out of Scope
.claude/CLAUDE.md§edge_case_triggers' "Ticket Creation Freshness" line is Tier-4 operator authority; this ticket does not touch it. If the carve implies a turn-loaded edit, surface it rather than making it.ticket-createandepic-createstay unconditional — the carve exists precisely because the creation-side gate ran.structural-pre-flight,turn-memory-pre-flight,architecture-pre-flight). They may have the same shape, but each needs its own creation-side-dual analysis; bundling would make the loophole surface unreviewable.Avoided Traps
git log. If an implementer finds themselves adding a judgment call, that is the signal the carve is being widened.Decision Record impact
aligned-with ADR 0008— the change is trigger language in the SKILL.md Map, within the §2.1 frontmatter contract. No ADR is amended or challenged.ADR successor-risk:
adr-aligned— artifact dated 2026-07-25; ADR 0008 governs skill-shape and this is a Map-level trigger edit; evidence = both SKILL.md frontmatter blocks quoted above; routecontinue.Related
ticket-create§1b Meta-Skill Sweep and ADR 0008 §2.1 — the gates this ticket's own implementation must satisfy.Live latest-open sweep: checked latest 20 open issues at 2026-07-25T10:07Z plus a semantic search over all states for intake/exemption/freshness-gate scope — nearest hits (#12990, #15790) are both CLOSED and unrelated; no equivalent found. A2A in-flight claim sweep at 2026-07-25T09:51Z, all read-states: no claim on skill-trigger scope; newest peer traffic is 2026-07-25T00:37Z (~9.5h stale, roster parked by operator).
Origin Session ID:
cb8b1069-54cc-43fd-943f-0e20b45661c8Retrieval Hint:
query_raw_memories("ticket-intake epic-review self-authored same-session exemption drift probe not wall-clock age")Authored by Grace (@neo-opus-grace, Opus 5)
Amendment 1 (2026-07-25) — authorship was the wrong axis
@tobiu raised the case that breaks the three-tier carve above: different author, but hot context. An ideation-sandbox graduation you participated in, where a peer authors the epic and its subs. Authorship says "different author → full gate"; context says "I was there."
The V-B-A inverts the intuition, so the carve does not widen here. Reading what
epic-reviewactually checks (epic-review-workflow.md):Stage 2.5's own first step is "Fetch the source Discussion body and extract the Graduation Criteria." A participant already holds that, so the highest-value stage becomes nearly free — while Stages 3–4, the peer's independent transformation of discussion → epic → subs, are entirely unseen regardless of participation.
Conclusion: participation lowers the COST of the most valuable stage; it does not remove the need for the review. The correct handling is narrowing and re-ordering, not exemption:
The corrected general axis
Authorship was a proxy. The real question is what have you already seen — so the carve scopes to the unseen, not to who typed it:
This subsumes both observed cases and is still externally checkable: authorship and session identity from the artifact and the session id; participation from the Discussion's own comment thread (did you post in it?), which is a public fact, not a self-assessment.
AC deltas from this amendment
epic-reviewgains the participant path: Stages 1–2 citable, 2.5 run-from-context, 3–5 full. It must NOT be expressible as "I was in the discussion, so I skip the review".Trap added