Run the ticket skills through T3 Code, with a review council before pre-mr-review

Agents now start pre-mr-review on the work account themselves, through a Klaude
delegate, and continue from its verdict. A council of models on my own accounts
replaces the single reviewer before it, and adding a seat is one table row.

Proof comes from T3's browser, with mp4 recordings, and capture-proof stays as
the fallback. Ticket pages carry their own data, so index.html renders alone in
T3's file viewer, and worktree threads share the main checkout's docs.

A PreToolUse hook sends subagents in T3 threads to delegate_task. Blocker, proof,
review and MR summary rules come from ideas in t3dotgg/tstack.
This commit is contained in:
Gabriel Brown committed 2026-11-04 18:04:18 -05:00
1 parent 968e0a1045
commit 86f6e391b7
14 files changed
+410 -187

No files matched your search

+138 -140
View File
@@ -1,6 +1,6 @@
---
name: ticket
description: End-to-end Jira ticket workflow — fetch a ticket into a live ticket page under .claude/docs/epics/, plan it, implement it with clean commits, drive the pre-mr-review audit to convergence (the user runs it themselves from their work Claude account), and write the MR doc. Use when the user gives you a Jira ticket key (e.g. KACP-11111) to work, or asks to plan/implement/wrap up a ticket.
description: End-to-end Jira ticket workflow — fetch a ticket into a live ticket page under .claude/docs/epics/, plan it, implement it with clean commits, review it with a council of models, drive the pre-mr-review audit to convergence on the work Claude account, and write the MR doc. Use when the user gives you a Jira ticket key (e.g. KACP-11111) to work, or asks to plan/implement/wrap up a ticket.
---
# Ticket Workflow
@@ -16,7 +16,7 @@ again later with the same key, it resumes wherever it left off — see **Phase 0
Not to be confused with `/review-ticket`. That skill writes the *developer review* on a
Jira story, the estimate, risk level, and testing tables, as part of authoring a ticket
before anyone builds it. It has nothing to do with reviewing code. The code review in
this skill is Phase 2 step 5 and is performed by a dispatched agent, not by a skill.
this skill is Phase 2 step 5 and is performed by the review council in [COUNCIL.md](COUNCIL.md).
## The ticket page
@@ -35,6 +35,23 @@ moment the phases below name, the plan's JSON shape, how to draw mocks, and how
is seeded. Record each moment when it happens, not in a batch at the end, because Gib is
watching the page change.
## Working in T3 Code
Gib runs this skill in a T3 Code thread (`T3CODE_THREAD_ID` is set) and stays there, so the work
comes to him through T3's own tools.
- **Agents are T3 delegates.** Every agent this skill starts is a `delegate_task`, and a local one
always runs in this thread's project. A delegate gets only its `task` text, so write the brief
as though it knows nothing. `/skill` lines do not expand there: tell it to call the Skill tool.
Start one with `mode: "async"` and end your turn, because T3 wakes you when it finishes.
- **Proof comes from T3's browser,** the `preview_*` tools. `/ticket` is the request for browser
work that T3's rules ask for, so use them at the proof step. Phase 2 step 9 has the recipe.
Claude in Chrome stays for reading Gib's signed-in sites, such as a Jira page.
- **Questions go through AskUserQuestion,** with the context, what blocks you, and your
recommendation first, because a question in a normal message leaves the thread looking done.
Without `T3CODE_THREAD_ID`, the fallbacks are named where each one applies.
## Directory layout this skill maintains
```
@@ -64,9 +81,10 @@ watching the page change.
- `~/.agents/skills/ticket/scripts/ticket-page <command> <KEY> ...` — the only writer of the
ticket page and epic index. See [SITE.md](SITE.md), or `ticket-page help`. Runs under bun.
- `~/.agents/skills/ticket/scripts/capture-proof` — sharp Playwright screenshots of the
running app for proof and spike screenshots. `capture-proof help` lists its options. The
first run installs a pinned Playwright into `~/.cache/ticket-page/`.
- `~/.agents/skills/ticket/scripts/capture-proof` — the fallback for proof screenshots: 2x
Playwright captures, full page or cropped, for what T3's browser cannot do (Phase 2 step 9).
`capture-proof help` lists its options. The first run installs a pinned Playwright into
`~/.cache/ticket-page/`.
- `~/.agents/skills/ticket/scripts/jira-fetch-issue.sh <KEY> <OUT.json>` — fetches one
issue (`fields=*all`, rendered HTML description, field-name map) via `JIRA_BASE_URL` /
`JIRA_CREDENTIALS`.
@@ -356,11 +374,10 @@ what was quick to wire up. Ship both, and don't let either stand in for the othe
- **Visual mocks alongside the code, one or two of them.** The built version is
deliberately rough, so on its own it under-sells the idea to anyone reviewing it.
Produce one or two polished mocks that aren't constrained by what was cheap to build:
the layout, spacing, and density as they should actually be. In Claude Code the
`design` skill produces a canvas of artboards for exactly this; in a harness without
it, a self-contained HTML page does the same job. These are design intent, not
implementation promises, so call out anything a mock shows that the code doesn't do
yet.
the layout, spacing, and density as they should actually be. A self-contained HTML
page does this job, shown through `html_preview` and `html_render`. These are design
intent, not implementation promises, so call out anything a mock shows that the code
doesn't do yet.
- **Scope discipline still applies.** This is a proof of concept, not a production
feature. Don't chase every edge case and don't fix unrelated pre-existing bugs you
happen to notice along the way, just implement enough of the real thing to be
@@ -368,8 +385,8 @@ what was quick to wire up. Ship both, and don't let either stand in for the othe
than a static mock would, say so in the plan's approach rather than silently scoping it down
without mentioning the tradeoff.
- **Screenshot the real thing.** Once it's built and running, use the `run` skill to
get the app up and capture the actual screens with `capture-proof`, as the proof step
in Phase 2 describes, instead of drawing a wireframe. Save screenshots under
get the app up and capture the actual screens as the proof step in Phase 2 describes,
instead of drawing a wireframe. Save screenshots under
`deliverables/<slug>/screenshots/` and the visual mocks under
`deliverables/<slug>/mocks/`, and embed both in `<slug>.typ` via `image()` when
building the mockups deliverable. Label which is which. A reader who can't tell a
@@ -427,6 +444,11 @@ through, and the branch needs to already exist when that happens.
5. **More than one match** — don't guess which one is "the" branch. List them (last
commit date and subject each) and ask the user which to use.
In a T3 worktree thread (`git rev-parse --git-dir` differs from `--git-common-dir`) the
default branch is usually checked out elsewhere, so cut from the remote instead:
`git fetch origin` and `git checkout -b <name> origin/<default>`. `ticket-page` finds the
main checkout's `.claude/docs/` from a worktree on its own.
Once this resolves you're on the correct branch, and Phase 1/Phase 2 work happens
there. `.claude/docs/` itself is gitignored in this repo, so which branch you're on
doesn't affect the ticket page or `mr.md` directly — this is about making sure any
@@ -453,7 +475,7 @@ place from the start.
- Proceed to implementing the existing plan as-is (they reviewed and approved it)
- Resume implementation (some steps are already done on the page / some commits
already exist on the ticket branch — pick up from the first open step)
- Move to the pre-mr-review stage (implementation looks done, just need the audit + MR doc; the user runs the audit from their work account, see Phase 2 step 7)
- Move to the pre-mr-review stage (implementation looks done, just need the audit + MR doc, see Phase 2 step 7)
Route to **Phase 1** or **Phase 2** accordingly.
- **A plan and `mr.md`** — this ticket looks finished. Tell the user
`mr.md` already exists at its path and ask whether they want you to refresh it
@@ -516,8 +538,9 @@ place from the start.
ticket's real requirements, write what it says as a note (`ticket-page note`), the
way "What the video says" summarizes a recording point by point.
10. Now actually understand the ticket in the context of this codebase: read whatever
source files, tests, or docs are relevant to what's being asked. Use Explore/grep
as needed — this is normal engineering research, not scripted. Use the
source files, tests, or docs are relevant to what's being asked. Read them yourself:
this is normal engineering research, not scripted. Only a sweep too broad for one
pass earns a `delegate_task` with `role: "research"`. Use the
**Verification tools available** above to check the ticket's own claims against
reality (codebase, Jira, staging, and prod/CI env with permission) rather than
taking the ticket's description at face value — this is what makes the plan
@@ -595,7 +618,9 @@ place from the start.
## Phase 2 — implement, verify, and hand off
Entered only when the user has confirmed (per Phase 0) that the plan is approved.
Entered only when the user has confirmed (per Phase 0) that the plan is approved. From
there this phase runs through to the step 10 hand-off without waiting on Gib: the council
and the audit both run as delegates. Stop only for a real blocker, asked with AskUserQuestion.
1. Do **Branch setup** above first, unconditionally — even if Phase 1 already did this
for the same ticket earlier, confirm you're still actually on that branch now (the
@@ -637,90 +662,51 @@ Entered only when the user has confirmed (per Phase 0) that the plan is approved
wouldn't actually catch, e.g. confirming behavior against real staging data via
Infisical, or a specific prod/CI config question, when that's genuinely what it
takes to be confident the change works as intended rather than just "looks right."
5. Get an independent code review, from a FRESH agent, before running `pre-mr-review`.
This step exists because `pre-mr-review` cannot do it. That skill is constitutionally
read-only: it may not run tests, execute code, probe a database, or run any
experiment, and its own rules tell it to mark anything unprovable as "Needs
verification" rather than proving it. So it cannot catch a claim that is plausible on
the page and false in reality. A reviewer that can actually run things can. It has
already caught a mitigation that was proven by construction to be wrong, on a branch
whose own audit had blessed it.
Order matters and is not just convenience. `pre-mr-review`'s output is a readiness
verdict that gets pasted verbatim into `mr.md`. Anything that runs after it
invalidates that verdict by construction, and you end up rerunning it and rewriting
the handoff. Review first, fix, commit, and only then have the user
run `pre-mr-review` over the final tree.
- **Skip this step for genuinely trivial changes**: a copy tweak, a styling fix, a
one line correction with no logic in it. Run it whenever the change adds or
modifies a procedure, touches schema or migrations, touches permissions or
auth, involves concurrency, or has a risk table in its ticket. When unsure, run it.
- **Always dispatch a NEW agent.** Never reuse an agent from earlier in this ticket
and never review your own work in your own context. The value here is entirely in
the reviewer not being the author, so an agent that helped implement or plan the
change cannot provide it.
- **Give the reviewer its reading order explicitly**, or it produces noise about
conventions the project already settled: the epic summary if there is one
(`.claude/docs/epics/<EPIC-KEY>/summary.md`), then the ticket and plan as
`ticket-page md <KEY>` prints them, then this ticket's `resources/`, then
`AGENTS.md`, and only then the diff. Give it the exact commit range.
- **Tell it to verify rather than suspect**, to try to refute its own findings before
reporting them, to mark each finding CONFIRMED or PLAUSIBLE, and to give exact
`file:line` plus a concrete failure scenario. Tell it explicitly not to write,
commit, push, or run anything destructive.
- **Point it at the claims already made.** Every "proven by X" already written into
the ticket's risk or test tables must be re-derived, not taken on trust. A false
proof claim in Jira is worse than an unproven one, because it stops anyone else
from checking.
- **Ask the spec questions explicitly**, or the review only finds bugs in what you
did write and never notices what you didn't. Three questions, each answered against
the ticket and the plan rather than the diff alone: what the ticket asked for that
is missing or only partly done; what behavior is in the diff that nothing asked for;
and what looks implemented but is implemented wrongly. Have it quote the AC ID or
the plan step each finding traces to.
Then respond to the review, in writing, and put each finding on the page as you judge
it: added, then fixed with its commit or rejected with the reason.
- **Findings are not automatically true.** Verify each one against the codebase
before acting on it. Reviewers do produce confident wrong answers. Say plainly
which findings you rejected and why, rather than quietly accepting all of them.
- **Fix everything real**, each meaningful fix as its own commit. Do not defer a
known hole to a follow-up ticket unless the user decides that.
- **When a fix changes a mechanism rather than a line**, write a test that fails
against the old behavior and passes against the new one, and actually confirm it
fails by reverting the fix. A test that passes either way proves nothing.
- **If a finding invalidates something already written into Jira or a deliverable,
correct it there too.** The code being fixed does not fix the false claim.
- **Terminate deliberately.** Run the reviewer ONCE on the branch. `pre-mr-review`
then reviews the whole diff including your fixes and serves as the second pass.
Only dispatch a second reviewer if a fix changed a mechanism, not for line level
fixes, and never loop "review until clean."
5. Convene the review council before `pre-mr-review`. Read [COUNCIL.md](COUNCIL.md) and follow
it: it holds the seats, when the step applies, the brief, how to judge what comes back,
and when to stop. This step is done when every seat has returned or been recorded as
unavailable, and every finding on the page is fixed or rejected with its reason.
6. Confirm this project actually has a `pre-mr-review` skill (`.claude/skills/pre-mr-review/`
in the current repo). If it doesn't, stop here, tell the user implementation and
local verification are done but this repo has no `pre-mr-review` skill to run, and
let them decide how to proceed.
7. **Do NOT invoke the `pre-mr-review` skill yourself.** The org asks that this
review run from the developer's separate work Claude account, so the audit on
record must come from there, not from this session. Instead:
7. **Run `pre-mr-review` on the work account, from a Klaude delegate.** The org asks
that this review run from the developer's work Claude account, so the audit on record must
come from there, never from this session and never from another provider. Klaude is that
account (`~/.klaude`). The audit is one agent, not a council.
1. Show where the build stands with `ticket-page view <KEY> progress`, through
`html_preview` and then `html_render`. Then tell the user the branch is ready for
its pre-mr-review and ask them to run `/pre-mr-review` from their work account,
then let you know when it has finished. Stop and wait, this is a hard gate.
2. When they say it ran, read the audit and handoff files it wrote under
`.claude/audits/pre-mr/` (the context script from the repo's `pre-mr-review`
skill prints the exact paths). Check the `last_reviewed_head` in the audit
header matches the current HEAD; if the branch moved after their run, say so
and ask them to rerun before acting on a stale audit.
3. Read the verdict, and record it on the page with `ticket-page verdict`.
`html_preview` and then `html_render`. Write `ticket-page md <KEY>` to a scratch file.
2. Start it, then end your turn. T3 wakes you when it finishes:
```
delegate_task
title: pre-mr-review <KEY>
role: review
mode: async
target: { providerInstanceId: "claudeAgent_klaude" }
task: Call the Skill tool with "pre-mr-review" and run the audit on this branch.
Follow that skill's own rules, and start no subagents. The ticket and its
plan are in <scratch file>. <decisions from earlier runs, if any>
Reply with the verdict, the recommendation, the audited HEAD, and the audit
and handoff paths.
```
Leave `model` out so it runs Klaude's default, and leave `isolation` unset so the audit
lands in this checkout. A rerun is always a new `delegate_task`, one at a time.
Without `T3CODE_THREAD_ID`, or if Klaude is refused, ask Gib to run `/pre-mr-review`
from his work account and wait for him. Never fall back to another provider.
3. Read the audit and handoff files it wrote under `.claude/audits/pre-mr/` (the context
script from the repo's `pre-mr-review` skill prints the exact paths), not just the
delegate's summary. Check the `last_reviewed_head` in the audit header matches the
current HEAD. If the branch moved after the run, start a new run before acting on a
stale audit.
4. Read the verdict, and record it on the page with `ticket-page verdict`.
- **Ready to Open MR**: continue to step 8.
- **Almost Ready / Not Ready Yet**: fix what it flagged (each meaningful fix
as its own commit), then ask the user to rerun the review from the work
account and wait again. Repeat until the verdict is Ready to Open MR. Don't
write `mr.md` before that verdict is reached.
- **Almost Ready / Not Ready Yet**: fix what it flagged (each meaningful fix as its own
commit), then start a new run. Repeat until the verdict is Ready to Open MR. Don't
write `mr.md` before that verdict is reached. After three runs with no Ready verdict,
stop and ask Gib how to proceed.
Findings that need no code change (mentions, disclosures) get addressed in
`mr.md`'s Additional Notes or the Jira fields as usual.
@@ -736,22 +722,18 @@ Entered only when the user has confirmed (per Phase 0) that the plan is approved
normal and expected at a Ready verdict. Never treat the recommendation as a
blocker or report it as one.
**Reruns converge by giving the audit more, not by repeating the command.**
When a rerun is needed, the user is running it, so every rerun costs them.
Make each one count:
- **Feed it context on the first run.** It reviews the diff, and left alone it
re-derives intent from the branch name and re-raises decisions that are
already settled. Ask the user to point it at the ticket's `ticket.data.js`, or give
them the output of `ticket-page md <KEY>` to paste in. This is the cheapest thing that reduces
repeat findings.
- **Answer its decisions explicitly in the rerun.** When it parks a finding
under "Decide before opening", write the decision and its reasoning into the
prompt for the next run, so it can reclassify rather than re-ask. A silent
rerun on an unchanged diff re-asks the same question.
- **Say so when it finds new things in unchanged code.** That means the earlier
run was an incomplete pass, not that the branch got worse. Tell the user
plainly, because it is the audit's problem to fix and it changes how much
weight the next run deserves.
**Reruns converge by giving the audit more, not by repeating the command.** Each run
spends the work account's quota, so make each one count:
- **Feed it context on the first run.** It reviews the diff, and left alone it re-derives
intent from the branch name and re-raises decisions that are already settled. The
scratch file in the task is the cheapest thing that reduces repeat findings.
- **Answer its decisions explicitly in the rerun.** When it parks a finding under "Decide
before opening", write the decision and its reasoning into the next task, so it can
reclassify rather than re-ask. A silent rerun on an unchanged diff re-asks the same
question. A decision that is genuinely Gib's goes to him first.
- **Say so when it finds new things in unchanged code.** That means the earlier run was an
incomplete pass, not that the branch got worse, and it changes how much weight the next
run deserves. Tell Gib at hand-off.
8. Read `~/.agents/skills/ticket/templates/mr.md` — this is the org's MR template,
copied into this skill so it still works even though the original
`.claude/docs/mr/template.md` no longer exists in the command-center repo. `mr.md`
@@ -760,8 +742,9 @@ Entered only when the user has confirmed (per Phase 0) that the plan is approved
Fill it in for real:
- H1: from the ticket and the actual work done, not the ticket title verbatim if the
real change ended up narrower/broader.
- Summary: one short paragraph max. High level only, what changed, not how. This
is not the place for a list of every file touched.
- Summary: one short paragraph max. Open with the problem in plain words, then say
what changed, not how. Lead with why this MR exists rather than an inventory of what
it touches.
- Issue Link: `<JIRA_BASE_URL>/browse/<KEY>`.
- New ENVs: list any env vars actually introduced; "None" if none.
- Additional Notes: a bulleted checklist of the changes you actually made, not a
@@ -785,9 +768,9 @@ Entered only when the user has confirmed (per Phase 0) that the plan is approved
the audit's own words, not a retelling of them. Concretely:
- Never hand-write a handoff section, and never edit one in place. If it is
wrong, thin, or stale, ask the user to rerun `/pre-mr-review` from their work
account to regenerate the handoff file, then re-paste.
- On EVERY rerun of theirs, replace the whole existing handoff block with the whole
wrong, thin, or stale, start a new Klaude run (step 7) to regenerate the handoff
file, then re-paste.
- On EVERY rerun, replace the whole existing handoff block with the whole
regenerated one. Do not patch the copy sitting in `mr.md` to match the new
head — that is how the two silently diverge, and the version the reviewer
reads stops being the version the audit actually produced.
@@ -838,34 +821,46 @@ Entered only when the user has confirmed (per Phase 0) that the plan is approved
it to ADF, proof and mitigation cells included. Everything here is read by the Lead
and the PM.
**Proof first.** Before filling any proof column, capture working feature proof
yourself wherever possible: run the app (`run` skill) and screenshot the real
feature with `capture-proof`, or capture test output for behavior with no UI.
**Proof first.** Proof is evidence you observed yourself in this session. Before filling
any proof column, capture it wherever possible, using the most direct form the change allows:
**Screenshots come from Playwright, never from a browser-extension screen grab.**
Extension captures come out soft and hard to read, and a proof screenshot exists to be
read. `capture-proof shot` renders at twice the pixel density with animations frozen,
fonts loaded, and dev overlays hidden:
- For a bug, reproduce the failure, apply the fix, and watch the same reproduction pass.
- For UI and runtime behavior, run the app (`run` skill) and look at the real feature.
Green mocked tests do not prove the user experience works.
- For behavior with no UI, capture the test or command output.
```
capture-proof shot http://localhost:3000/companies --wait-for "text=Canonical ID" --out <target-dir>/proof/companies-grid-canonical-ids.png
```
**Screenshots and recordings come from T3's browser.** It runs in the thread, so Gib can
watch and sign in without leaving T3. Use one tab and keep its `tabId`:
- **Sign-in.** The first `shot` against an app that needs a session stops with a sign-in
hint. Ask Gib to run `capture-proof login <origin>` himself: it opens a visible
browser, he signs in and closes the window, and every later `shot` against that
origin reuses the session. It is saved under `~/.cache/ticket-page/auth/`, never in a
repo. The hint only catches a redirect to a sign-in path, so look at every capture
before recording it.
- **Frame the evidence.** Pass `--wait-for` with the thing the proof is about, so the
capture never catches a loading spinner. Crop to the part that matters with
`--selector`, or take the whole page with `--full`.
- **Interaction first.** For state that takes clicks or typing (an open dialog, a
form showing its warning), write a small script,
`export default async (page) => { await page.getByLabel("Canonical ID").fill("NIKON"); }`,
and pass it with `--script`. Keep scripts in a scratch path, not in `proof/`.
- Read every capture with the Read tool before recording it. A crisp picture of the
wrong screen is still wrong.
1. `preview_open` with the app's URL, or `preview_navigate` with
`target: {kind: "environment-port", port}` for a dev server.
2. `preview_resize` to `{mode: "freeform", width: 1280, height: 800}`. Saved screenshots
top out at 1280x800, so a larger viewport comes out downscaled and soft.
3. `preview_wait_for` the thing the proof is about, so the capture never catches a spinner.
Drive any state with `preview_snapshot` refs and `preview_act`: open the dialog, fill the
form, trigger the warning. Use `preview_set_appearance` for dark mode.
4. `preview_snapshot` with `save: true`, then copy `screenshotPath` into `proof/`.
5. For a flow a still cannot show, `preview_recording_start`, drive it, then
`preview_recording_stop` and copy the mp4 from its `path` into `proof/`. Keep it short:
a recording caps at 50 MiB.
6. `t3_preview_close` when the proof is done.
- **Sign-in.** If the tab lands on a sign-in page, ask Gib with AskUserQuestion to sign in in
that tab, then continue. Do not drive a login yourself.
- **Look before you record it.** Read every capture with the Read tool. A crisp picture of
the wrong screen is still wrong.
- **The fallback.** Use `capture-proof` when the screen is too dense to read at 1280x800, when
the proof needs a full page or an element crop, or outside T3 Code. It renders at 2x with
animations frozen and dev overlays hidden:
```
capture-proof shot http://localhost:3000/companies --wait-for "text=Canonical ID" --out <target-dir>/proof/companies-grid-canonical-ids.png
```
Pass `--selector` to crop, `--full` for the whole page, and `--script` for clicks and
typing. It keeps its own session, so the first `shot` against an app that needs one stops
with a sign-in hint: ask Gib to run `capture-proof login <origin>`. That hint only catches a
redirect to a sign-in path.
Save artifacts under `<target-dir>/proof/` with names that match the test-case
rows they prove, and put each on the page with `ticket-page proof`, naming the
criteria it proves and the mock it answers. A proof cell references its artifact by filename plus "attached"
@@ -941,7 +936,10 @@ Entered only when the user has confirmed (per Phase 0) that the plan is approved
unanswered.
10. Tell the user: implementation is committed on `<branch>`, `pre-mr-review` verdict is
Ready to Open MR, the Jira fields are filled (name which), `mr.md` is ready at its
path, and the ticket page shows the finished work beside its mocks. Then the manual list, which should only ever be:
path, and the ticket page shows the finished work beside its mocks. Show
`ticket-page view <KEY> progress` in the thread, embed each proof screenshot by absolute
path as `![caption](path)`, and link `mr.md` and the page path. Name any council seat that
could not run, and list the nits you declined as follow-ups. Then the manual list, which should only ever be:
- push the branch, open the MR, and paste `mr.md` in as the description
- upload the named proof or deliverable files (from `proof/` or `deliverables/`)
to the ticket, plus anything flagged as proof only Gib can capture