Skip to content
Back to skills

Dev

ASecurity

Ticket-driven DEV pipeline, end-to-end — preflight (tracker/design-source/git/DB pinged for real) → fetch the ticket → read spec + schema (the ticket is a claim, the spec is the spec) → UI tickets pull the design from the ticket's design link (design source = visual oracle; exact colors/spacing/text from node data) → implement on a feature branch → /verify gate + evidence → self-review with machine-measured design fidelity → 2 fresh review agents must approve (+1 on high-stakes diffs; committ...

  • 6 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 2, 2026
developmentpythongobashnodedebugginggitapibackendsecurity

Works with

  • claude code
  • terminal
  • cli
  • api

Security analysis

A100/100

Scanned September 23, 2026

npx -y skills add connorpham/vteam-harness --skill dev --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Dev?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Dev
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/connorpham-dev/badge)](https://www.skillsdirectory.com/skills/connorpham-dev)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: dev
description: "Ticket-driven DEV pipeline, end-to-end — preflight (tracker/design-source/git/DB pinged for real) → fetch the ticket → read spec + schema (the ticket is a claim, the spec is the spec) → UI tickets pull the design from the ticket's design link (design source = visual oracle; exact colors/spacing/text from node data) → implement on a feature branch → /verify gate + evidence → self-review with machine-measured design fidelity → 2 fresh review agents must approve (+1 on high-stakes diffs; committed review trail enforced at pre-push) → push + PR → mandatory 7-part plain-language report comment on the ticket, then transition to In Review (Done belongs to /qa). Runs the machine DoR gate and claims the ticket before coding."
argument-hint: "<TICKET: VT-nnn | tracker URL> [assignee=<name>] [branch=feat|fix]"
---

> **Model routing for this tool** (from `model-routing.data.yaml`, snapshot 2026-08-17):
> `frontier` → **fable** · `workhorse` → **opus** · `standard` → **sonnet** · `utility` → **haiku**
> Roles → tiers: ba-challenger: standard · ba-draft: standard · dev-r1: workhorse · dev-r2: standard (high-stakes: workhorse) · dev-r3: workhorse · explore: utility · qa-challenger: standard · sa-background: workhorse · sa-challenger: workhorse · sa-writer: workhorse
> Resolve at runtime: `python3 .vteam/scripts/model_route.py <role> --tool claude-code [--high-stakes]` — high-stakes diffs (review.high_stakes_*) bump dev-r2 to the workhorse tier.
> Spawning a subagent: pass the resolved name as the Agent tool's `model` parameter.

> **Environment:** `app:` is not configured in vteam.config.yaml — env bring-up is
> manual this session, and `app_check.sh` prints `APP: SKIP`. Set `app.start` +
> `app.url` (+ optional `app.health`, `app.open_files`, `app.headed` — schema:
> DESIGN.md §2) to enable the watchable session: headed Chrome via
> `.vteam/scripts/browser.mjs`, health probe via `.vteam/scripts/app_check.sh`,
> editor opening via `.vteam/scripts/open_files.sh`.


# /dev — implement a ticket, prove it before delivering

**Immutable principles** (violation = the task is not done):
1. **The spec is the spec, the ticket is a claim.** Expected behavior comes from
   the spec shard (`docs/specs/<feature>.md`) and the schema — never from
   ticket prose alone. Ticket contradicts spec/schema → STOP and ask before coding.
2. **No code before understanding.** T1's task-sheet (requirement, acceptance
   criteria, touched models/routes, cited sources) must exist before the first
   edit. Ambiguous ticket → ask, do not guess.
3. **Minimal, surgical change** (the `guidelines` workflow is the method authority
   — load it). No drive-by refactors, no scope expansion; a side finding gets its
   own note/ticket (T5), never smuggled into this branch.
4. **Never commit on the protected branch.** Branch `feat/<TICKET>-<slug>` (or
   `fix/…`) from its up-to-date tip.
5. **"Done" is machine-checked AND peer-checked.** The /verify gate must be green
   with exact result lines recorded, AND every review card T4b requires must
   approve BEFORE any commit/push/PR/comment. How many cards is not your call:
   `python3 .vteam/scripts/change_class.py --sha WORKTREE` reads the diff and
   names the class — `docs` (no card), `surface` (one card, one real bullet),
   `logic` (R1 + R2), `high-stakes` (one more). Run it BEFORE you brief reviewers,
   quote its line in the task sheet, and brief for what the class actually is: on a
   surface change the useful bullet is "I grepped the old string out of the BUILT
   artifact and found the test that asserted it", not three invented attacks. UI
   change → headed browser evidence under `evd/<TICKET>/dev/` (the
   root layer `evd/<TICKET>/` belongs to the QA lane). A claim
   without recorded output is not a claim.
6. **The ticket is not done without the report comment.** Closing requires posting
   the 7-part report comment to the tracker — always print the exact posted text
   in the final summary. After the comment + PR merge, T6.3 transitions the ticket
   to In Review (at `autonomy.level: full`); moving to Done is /qa's call after a
   PASS verdict.
7. **Visible, human-readable process.** One plain-language checkpoint line at
   EVERY phase transition — `▶ [T3/T6] <what's happening, in plain words>`. Every
   report/summary must pass the bar: **a non-programmer understands it** (jargon
   goes in an appendix, never the body).

Tempted to skip a step? Find your excuse in `red-flags.md` first — if it's listed, the answer is already no, and a gate fires anyway.

Method authority: the `guidelines` workflow. Tracker recipes: the configured
tracker provider (`providers/tracker/<name>`). Schema: read the project's schema
file for real field names — never guess. Framework docs: read the in-repo
framework guide before writing code when the project declares one (the installed
version may differ from training data).

---

## T0 — RESOLVE + ANNOUNCE THE TICKET

1. **Preflight the whole chain first**: `bash .vteam/scripts/preflight.sh` — pings
   tracker, design source, git, DB, test infra for real. Non-UI ticket → add
   `--backend` so the design-source legs only warn. RED → show the misses +
   unblock steps; continue only with green parts. Never print tokens.
2. Fetch the issue + ALL comments + attachments. No ticket key given → list the
   assignee's open tickets and ask the user to pick.
3. **Assignee filter.** Default assignee comes from config (`assignee=<name>`
   overrides). Ticket assigned to someone else → STOP and ask.
4. **Status must be workable — In Progress is a CLAIM, not an invitation.**
   To Do / Open = OK. **In Progress → another session's until proven otherwise**:
   read the latest claim comment + `git branch -a --list '*<TICKET>*'`
   (`npx vteam-harness resume <TICKET>` reads all these signals in one shot and
   names the furthest proven stage). A claim
   younger than the claim TTL, or a branch someone is pushing → STOP, pick other
   work. A claim past TTL with no remote branch and no fresh worklog → ORPHANED
   (previous session died): take over, write one `failed: previous session died
   mid-work` row to the ledger so loop guards count crashed sessions, and resume
   the leftover local branch if one exists instead of restarting. Done/Closed →
   tell the user. In Review → ask whether this is rework. The `reopen` label =
   QA returned it — read QA's REPORT.md BEFORE re-reading the spec.
5. **Definition-of-Ready gate (machine-checked):**
   `python3 .vteam/scripts/dor_check.py <TICKET>` must be GREEN — G/W/T AC + spec
   citation + out-of-scope section + design link (if UI) + original estimate + not
   blocked by an un-Done ticket. RED → the ticket returns to the BA lane
   (`raci.md` §2); do NOT start coding. Sole exception: the user orders ad-hoc
   work that skipped /ba — the waiver must become a DURABLE trace: a ticket
   comment `DoR waived by <user> — reason` (a scratchpad dies with the session; a
   comment doesn't).
6. **CLAIM the ticket here**: transition to In Progress **+ comment
   `claimed <timestamp> · branch feat/<TICKET>-<slug>`** — a claim without a
   timestamp leaves the next session unable to tell working from orphaned.
7. **ANNOUNCE before any work** (one block); if the ticket was auto-picked, wait
   for the go:
   ```
   ▶ Task <TICKET> — <summary>
     assignee: <name> | status: <status> | type: <Story|Bug|Task> | priority: <p>
     branch plan: feat|fix/<TICKET>-<slug>
   ```

## T1 — READ: ticket + spec + schema + code (build the task-sheet)

**Who is working:** read `docs/team/competencies/dev/dev-identity.md` first —
the senior engineer this lane runs as (decision posture, what a senior never
does) — then `docs/team/roles/dev.md`, the professional baseline. The lane
below says WHEN each thing happens; the competencies say HOW a senior does it.

**KB preflight (index-only — never read the whole file):** read
`docs/qa/knowledge-base.md` §0 + its INDEX table, open ONLY lessons whose tags
match this ticket's area, and answer them in the task-sheet (cite by TITLE). Same
for `docs/qa/known-issues.md` headings. Over the cleanup threshold (§0) →
propose a consolidation pass.

**Read the change ledger BEFORE the shard:** `docs/specs/changes.md` — filter
CH-nn rows touching this ticket's shard/screen. The shard is VERBATIM source; all
decided requirement deltas live in the change ledger. A NEW spec contradiction
discovered mid-work → add a CH-nn row with status `proposed` (PM/BA arbitrate
later); don't just narrate it in the task-sheet.

**Context via the code map — BEFORE reading the directory tree:**
`python3 .vteam/scripts/code_map.py query <TICKET> <2-4 domain terms>` (e.g.
`query PROJ-42 wallet topup balance`). It prints PATHS + line ranges only — read
those files plus `docs.task_context` below, and let the returned paths fill the
task-sheet's **Code map** bullet. It says `MAP IS STALE` or `NO CODE MAP` → run
`python3 .vteam/scripts/code_map.py build` first (one command, seconds) and
re-query. The map is **advisory and lexical** (python is really parsed; js/ts
symbols come from regexes, and there is no data-flow) — a file you know matters
but the map missed gets read anyway **and named in the task-sheet** as
`code map MISSED: <path> — <why it matters>`, so the next session (and the map's
scan roots, `git.code_paths`) can be corrected. Reading the whole tree "to be
safe" is the behavior this step exists to replace.

**Task context (only when config `docs.task_context` exists):** read the files it
maps for THIS ticket — `always:` first, then the `by_label:` lists matching the
ticket's labels and its issue type. This is the project background the owner
already wrote down (created by `/docs` on undocumented repos); reading it is
cheaper than rediscovering it in review. **A listed file that does not exist is
said LOUDLY in the task-sheet** — one line, `task context MISSING: <path> (mapped
by <always|label:<name>>)` — never silently skipped and never replaced by a
guess: a stale mapping means either the config or the repo moved, and the owner
needs to know which.

Write `evd/<TICKET>/dev/tasksheet.md` BEFORE touching code (it
carries Impact + assumptions + self-review results; it commits with the code so
the next session can resume the work):
- **Requirement** in one paragraph, plus acceptance criteria as the ticket states them.
- **`CODE-SCOPE:`** one line, the paths this ticket may touch (e.g.
  `CODE-SCOPE: src/auth/ src/lib/session.ts`) — graph_check reds any commit
  whose subject LEADS with this ticket's key and strays outside them (MAST 2.3:
  self-expansion). Scope grew mid-ticket? Widen the line DELIBERATELY in the same
  commit and say why in the task-sheet — or split the ticket.
  - **Bookkeeping homes are never CODE-SCOPE.** `docs/pm` (coordination log,
    ledger, minutes), `evd` (your own evd/) and `docs/qa`
    (knowledge base, known-issues) are shared by every lane by design, so they
    prove nothing about disjointness — `parallel_check` discounts them and
    graph_check already lets every ticket touch them. List the CODE paths only.
  - **In parallel mode (`team.parallel` > 1) COMMIT the tasksheet FIRST**,
    before the first code edit. Your worktree is not your siblings' worktree, so
    their `parallel_check`/`coord_check` read your `CODE-SCOPE` out of the shared
    object store (`git show <branch>:<path>`) — a sheet that exists only in your
    working tree makes your territory invisible and reds their gates with
    `tasksheet missing on <branch>, not committed`. See
    `docs/team/parallel-transport.md`.
- **Spec check**: the governing spec sections — quote them. Spec silent on a
  detail → list it under "assumptions to confirm" and ask.
- **Design check (UI tickets)**: the design oracle, in priority order — ① design
  link on the ticket (record file + node ids) → ② search the project's design
  index / frame matcher and attach the matching frame to the ticket, then use it
  as ①. Neither exists → report to /pm (design lane / decision queue); don't
  design ad-hoc inside a dev ticket. **The design source rules the looks, the
  spec rules behavior** — on conflict, spec text (verbatim messages/validation)
  wins over the picture; note the correction.
- **Data model**: exact models/fields touched (read the schema — never assume
  names). Schema change needed → plan the migration + client regeneration per the
  stack profile.
- **Code map**: routes/components/lib files involved; what exists vs what's new.
- **Impact**: who else uses what I'll change (search each touched symbol),
  auth/role implications, external sandbox notes if relevant.

## T2 — PLAN (minimal change, stated out loud)

**Load the `guidelines` workflow NOW, before writing the plan** — its defaults
(think first, surgical diff, surface assumptions, verifiable success criteria)
govern T2–T4; planning without it is a pipeline violation.

**Load the competencies this ticket needs** — from
`docs/team/competencies/dev/INDEX.md` (read the index, not the tree): every
row whose `Applies` says `always` and whose `Loads at` is T2, plus every row
where a token matches this ticket — `label:<x>` against the ticket's labels,
`path:<prefix>` against the task-sheet's CODE-SCOPE, `profile:<name>` against
`stack.profile`, `term:<word>` against the ticket + spec text. Rows marked T3
load at T3. Write the loaded list in the task-sheet under **Competencies:** —
a data ticket that loaded nothing about data modeling is a planning error, and
the reviewers will look for exactly that line. Each file's **Decide** table is
the plan's vocabulary: name the row you followed when the choice was non-obvious.

In the task-sheet, before editing: the minimal file-by-file change list ·
migration yes/no · test plan (which tests prove the AC — expected values cite
spec/schema) · what is explicitly OUT of scope. Present the plan to the user only
when a decision is genuinely theirs (schema change, new dependency, ambiguous
spec); otherwise proceed.

## T3 — IMPLEMENT

- **Competencies marked T3 load now** (INDEX `Loads at` = T3): error handling
  and security basics on every ticket, the stack file when `stack.profile`
  matches, debugging the moment anything is red and the cause is not proven.
  Append them to the task-sheet's **Competencies:** line.
- `git fetch && git switch -c <type>/<TICKET>-<slug> origin/<protected>` (never
  commit on the protected branch).
- **Work like a developer, visibly.** Before editing a file, put it on the
  owner's screen: `bash .vteam/scripts/open_files.sh <file[:line]> …` (config
  `app.open_files`; `none` or a missing editor CLI skips with one line — it
  never blocks). Bring the app up per the Environment block (`app.start` in a
  background terminal → `bash .vteam/scripts/app_check.sh --wait 60`) and keep
  the screen you are changing in view while you build — watch it headed via
  `.vteam/scripts/browser.mjs`; a dev who never saw the screen ships blind.
  API/backend tickets skip the browser, not the editor.
- **UI work — design from the design source, consistency from the design
  language, quality from the UI rules:**
  0. Read the design language FIRST (docs/design/design-language.md —
     generated from the design source at install; if absent, say so in the
     task sheet rather than inventing tolerances). Write
     `evd/<TICKET>/dev/fidelity.json` AS you build the layout
     (selectors + expected values from the design node data) — know what the
     screen will be measured on before coding it.
  1. Download the ticket's design frames to `evd/<TICKET>/design/`
     and read the node data for exact values — colors/spacing/fonts/text come
     from the API data, never eyeballed from a screenshot.
  2. Read `docs/design/design-language.md` (tokens generated from the
     project's own design source at install/refresh time): shared colors /
     type-scale / radii / components. Anything your screen needs that the frame
     doesn't specify comes from HERE, not from taste. Where the design source
     provides no spacing system, spacing has exactly one source: the frame's node
     data.
  3. Apply the framework's UI quality rules (a11y, touch targets ≥44px, WCAG AA
     contrast, responsive) ON TOP of both — a design drawn with 3px touch targets
     still ships with 44px.
  Skipping any of these on a UI ticket is a pipeline violation; API/backend
  tickets skip all three.
- Follow repo conventions (aliases, generated-code locations, auth mechanism,
  styling system — from the project docs). Match surrounding style; comments only
  for constraints the code can't show.
- Schema change: edit the schema → run the profile's migration command → 
  regenerate the client. Commit the migration with the code. Hand-naming a
  migration folder → timestamps in **UTC** (local-time timestamps have reordered
  migrations and killed clean-DB replays).
- Side finding (unrelated bug/dead code) → note it in the task-sheet + report at
  T6; do NOT fix it here.

## T4 — VERIFY with the /verify gate

- Run the /verify workflow (or its gate directly). Record the exact closing lines
  in the task-sheet. New behavior needs a new test whose expected value cites
  spec/schema.
- **UI change → PROPER EVIDENCE, machine-guarded:**
  1. Bring the app up (Environment block: `app.start` in a background terminal,
     then quote `bash .vteam/scripts/app_check.sh --wait 60`'s `APP: UP` line in
     the task-sheet), and capture with the stack profile's evidence script —
     `node .vteam/profiles/generic/scripts/ui-evidence.mjs` — it signs
     in through the app's REAL auth flow (the profile's auth strategy), no
     forged cookies, so the images show what a real user sees. The run is
     **HEADED by default** — the browser visibly opens and walks each screen at
     a human-followable pace, so the owner can WATCH the app being used like a
     real user (the same standard the QA lane holds). Pass `--headless` only on
     machines with no display (CI sets it automatically; config `app.headed:
     never` does the same for unattended shifts). Base URL defaults from config
     `app.url` (`EVD_BASE_URL` still overrides). A profile that ships no
     evidence script → capture through `.vteam/scripts/browser.mjs` journeys
     under the SAME rules (real sign-in, one image per criterion). Images go to
     `evd/<TICKET>/dev/` — the root layer belongs to QA; two lanes,
     two directories, so their gates never red each other. One image per
     criterion, named `NN_<description>.png`.
  2. Ticket has a design oracle → add `design_vs_app.png` (design beside app) with
     a line stating what matches and what differs **intentionally**.
  3. `manifest.md` must contain a **CRITERION → IMAGE** table.
  4. **Mandatory:** `python3 .vteam/scripts/evd_ui_check.py <TICKET>` GREEN. It
     checks images open / are big enough / are **not blank or error pages**
     (dominant-color ratio) / follow naming / are referenced in the manifest /
     `design_vs_app.png` exists when the ticket has a design oracle. Red = not
     done, non-negotiable.
  5. **Images per STATE, not only per criterion:** with data, empty, error (and
     loading if skeletons exist) — the manifest carries a `STATE:` line listing
     captured states; inapplicable states say `N/A because <reason>`.
- **API/backend change → its own evidence standard, not "some curl":**
  `evd/<TICKET>/dev/api.md` with one REAL request→response pair per
  criterion — full command (token masked), status code, body, and one line
  "proves which AC". Plus at least one failing case (401/403/422) per
  write endpoint. No images needed.
- **Bug ticket (fix/) → BEFORE–AFTER evidence mandatory:** reproduce on the old
  code (`before_*`), same steps on the fix branch (`after_*`), side by side in
  the manifest. A fix that can't reproduce the original bug proves nothing.
  Machine check: `evd_ui_check.py <TICKET> --bug` — missing pair = RED.
- Any red → fix or report honestly; never deliver on a red gate.

## T4a — SELF-REVIEW (reviewer #0 is the author)

Most review findings are things the author could have caught by putting their
screen next to the design and re-reading the diff as a stranger (provenance: one
ticket burned 6 review rounds mostly on self-catchable findings). Do all 3 —
NOT DONE = NO REVIEWERS YET:

1. **Re-read your own diff as a reviewer:** `git add -A && git diff --cached`
   (an unstaged diff is a diff reviewers can't see — same protocol as T4b), hunk
   by hunk — every hunk answers "which AC does this serve?"; a hunk with no
   answer is scope creep, remove it. Quick sweep: dead code / debug prints /
   forgotten TODOs / rushed names.
2. **UI ticket — measure fidelity by machine, not by eye** (proportionality: a
   diff touching ≤1 component or copy-only may declare `NARROW-SCOPE:` in the
   manifest instead of paying the full measurement tax):
   - `fidelity.json` — key elements' selectors + expected values **taken from the
     design node data** (never from your own code — measuring code with code is
     self-grading).
   - `node .vteam/profiles/generic/scripts/ui_fidelity.mjs <TICKET>` → generates `fidelity.md`.
     WRONG deviations → fix code, re-measure. Justified deviations → declare an
     `intent` from the CLOSED list (`a11y:` / `spec:` / `responsive:` + reason) —
     the tool rejects intents outside the list.
   - Put `design_vs_app.png` beside the frame and walk the measurable-beauty
     checklist (spacing rhythm, alignment, hierarchy, empty/error/loading). What
     you can see wrong, fix NOW — don't save it for reviewers.
3. **Record self-review results at the end of the task-sheet** (3–6 lines): what
   you caught and fixed, what deviates intentionally and why — reviewers read
   this to NOT re-dig measured ground.

## T4b — TWO-AGENT REVIEW (mandatory gate BEFORE commit/push/PR/comment)

No delivery until 2 fresh agents (config `review.reviewers`;
spawned in the SAME message — parallel, empty context, never forked) have all
reviewed the diff and approved. **Model routing
(`docs/team/model-routing.md`):** R1 = `workhorse`, R2 = `standard`; if the
diff matches `review.high_stakes_terms` → BOTH `workhorse`. **Every reviewer
brief MUST include `docs/team/review-standard.md`**: findings are
CONFIRMED-with-evidence or QUESTION; APPROVE carries a tried-to-break list; a
CONFIRMED that doesn't reproduce voids the card and spawns a replacement.

**A brief is a prioritised attack list, not an open invitation.** Open every
brief with the 3–5 things most likely to be wrong in THIS diff, in order — from
the T4a self-review, the competencies' Reviewer lens and the high-stakes map.
"Review this" costs tens of minutes per card and comes back with preference
findings; a ranked list comes back in minutes with findings that reproduce
(provenance: the 2026-09-03 benchmark arm learned this on its third ticket).
Brief reviewers with the SELF-REVIEW results (T4a) + `fidelity.md` if UI —
reviewers verify measured numbers instead of re-measuring, and focus where the
machine can't measure. **Paste the `## Reviewer lens` block of every competency
the task-sheet lists** into BOTH briefs — those bullets are the "what to try to
break" list the craft itself asks for (an unauthorized id, the same write twice,
a FK without an index, a `catch` that swallows). A card that ignores a listed
lens item without saying why is returned.

- **R1 — spec reviewer:** briefed with task-sheet + diff + spec/schema citations.
  Checks: does the change do exactly what the spec says (each AC → code), is it
  MINIMAL (flag any unrelated edit), migrations/regenerated client consistent?
- **R2 — challenger:** briefed with the diff + repo map, NOT the task-sheet
  reasoning. Job: FALSIFY — bugs, edge cases (empty/duplicate/unauthorized role),
  regressions in callers of changed code, security (auth gates, input
  validation), UI a11y if applicable.
- **R3 — architecture & future (CONDITIONAL — only when the diff touches
  `review.high_stakes_paths` or matches `review.high_stakes_terms`; skip for
  screen-only tickets):** `workhorse`, briefed with the diff + roadmap + ADRs +
  sprint plan. Its card must answer: optimal or merely working? will it survive
  the features already planned? and for every major design point: **"option A
  (as built) vs option B — why A"** — an approve-only card without comparisons is
  INVALID, send it back.

Each returns a verdict card (APPROVE / REQUEST-CHANGES + findings with file:line;
major findings as A-vs-B comparisons). Record all cards in
`evd/<TICKET>/dev/review.md` — this file COMMITS with the code, and
`review_check.py` at pre-push demands it: valid R1+R2 APPROVE cards
(tried-to-break ≥3 bullets, ≥2 command/file:line traces), plus R3 when triggered.
Any REQUEST-CHANGES → fix, re-run the T4 gate, then re-submit to the SAME concern
(a targeted re-review, not a fresh full pass). Only when ALL required cards say
APPROVE does the pipeline proceed to T5. Unresolvable disagreement → the user.

**Round ceiling — `review.max_rounds` (init sets 1; read by `review_check.py`,
not just rendered here).** The initial cards are round 1; each re-submit after
REQUEST-CHANGES is a further round and is recorded under a `## Round N` heading
in `review.md`. When the next round would exceed the ceiling, do NOT open it:
answer every remaining finding in the dossier under **Answered, not fixed** with
the reason (cosmetic · preference · out of scope → the follow-up ticket key) and
proceed — the reviewer's card stands as written, the answer stands next to it.
The ceiling lifts for a finding tagged `SECURITY` (a security defect gets as many
rounds as it needs) and for a diff that touches `review.high_stakes_paths` or
matches `review.high_stakes_terms`. A gate rerun (CI red, a flaky suite) is not a
review round — record it as `## Gate rerun`, not `## Round N`. Knob absent = no
ceiling, and the green line says so. Provenance: one ticket of the 2026-09-03
benchmark arm took three rounds and ~2.5 h; the arm cut itself to one fix round
per ticket mid-run and finished the spec.

**Cross-model reviewers — `review.external.<card>`.** A card is a FILE, so any
tool that can write a conforming one can hold that seat — and two agents on the
same model share their blind spots. When `review.external.r2` is configured (any
card id), that card comes from the external CLI instead of a spawned agent:

```
node .vteam/scripts/external_review.mjs <TICKET> R2
```

The runner pipes the brief (`docs/team/review-standard.md` verbatim + the card
contract + the diff) to the tool on stdin, validates what it prints against
review_check's own bar, and only then writes `## R2 — external (<model>)` into
the dossier — stamped `MODEL:` / `TOOL: external`, replacing that card and no
other. Exit 0 = APPROVE filed, 2 = REQUEST-CHANGES filed (round still open),
1 = nothing written and stdout says what was missing.

Then **STILL run `review_check.py`** — the gate does not care who wrote the card.
Everything else is unchanged: the reviewer COUNT is still `review.reviewers`,
high-stakes still adds R{N+1}, any REQUEST-CHANGES still reopens the round, and
the remaining cards are still fresh Claude agents spawned in one message. An
external card that fails validation is NOT written — no card, so the push fence
blocks exactly as it does for a missing Claude card. The external CLI is
installed and authenticated by YOU; a missing binary is a RED run, never a
silent skip to one fewer reviewer.

**Answering a reviewer — before typing any sentence containing "fixed":**
1. `git add -A` then `git status --porcelain` filtered for unstaged changes —
   must be **0 lines**; reviewers read `git diff --cached`, a fix outside staging
   means they approved the old version.
2. Every finding closes with ONE command proving it closed, **output pasted into
   the message** — never a bare "fixed".
3. **Checks must be as WIDE as the change:** renamed an identifier → grep the OLD
   name repo-wide and classify every hit; changed shared behavior → find every
   caller, not just the one you edited.

## T5 — DELIVER: commit + PR

1. Commit on the branch: code + migration + tests + **the text layer of the
   evidence dir (review.md, manifest.md, fidelity.json/md — images/binaries stay
   out of git)** — pre-push blocks if review.md is missing on a code diff.
   Message: `<type>(<TICKET>): <what>` — follow the project's commit-authorship
   rules in its own instructions file.
2. Push and open the PR into the protected branch, titled
   `<type>(<TICKET>): <what>`, ticket key + summary + test-result lines in the
   body.
3. **Self-merge (only at `autonomy.level: full`):** when ALL 4 machine-checkable
   conditions hold — every review card APPROVE + the PR's CI green + the /verify
   gate green + **no unanswered human comment on the PR** (a human comment is
   priority input: handle it via /pm's PR-FEEDBACK protocol FIRST, then merge) —
   merge per `git.merge_strategy` without waiting (on squash/rebase the
   VERIFIED-AT anchor keeps the QA verdict alive — qa workflow V5b). Any
   condition missing (or autonomy below full)
   → leave the PR open + record why in the session minutes.
   `git switch <protected> && git pull` after merging.
4. List every side finding from T3 and what was done with it.

**Optional human report (BDD).** Beside the 7-part comment you MAY write
`evd/<TICKET>/dev/REPORT.bdd.md` — what you built as
Given/When/Then scenarios in plain words (`docs/team/bdd-report.md`;
`bdd_report_check` guards completeness + conciseness + no code-speak).

## T6 — TRACKER CLOSE LOOP (report comment is REQUIRED)

1. Write the **7-part report comment** — sentinel-tagged sections
   `[R1] What was done · [R2] Impact scope · [R3] Technical · [R4] Tested ·
   [R5] Evidence · [R6] Notes for QA · [R7] Open issues` — plain language,
   readable by a non-programmer (jargon only inside the evidence lines). Impact
   scope copies the task-sheet's Impact section, never rewritten from memory.
   **UI tickets: attach images by command, not by hand:**
   `python3 .vteam/scripts/evd_ui_check.py <TICKET> --attach` — it re-validates
   the images, uploads them, then **re-reads the ticket's attachment list to
   confirm every filename actually landed** — attaching without read-back doesn't
   count as attached.
2. **Post it** — the ticket is NOT done until this comment is on the tracker.
   **Then machine-verify:** `python3 .vteam/scripts/comment_check.py <TICKET>` —
   re-reads the comment from the tracker and checks all 7 markers; posting
   without read-back doesn't count as posted. Print the exact posted text in the
   final summary. Tracker unreachable → say so, deliver the text locally, mark
   the close-out PENDING.
3. **Status transition (at `autonomy.level: full`):** after comment + PR merged →
   transition to **In Review** (QA verify next; Done belongs to /qa after a PASS
   verdict).
3b. **Time tracking is part of closing** (when the tracker supports worklogs):
   post a worklog with real elapsed session time, and verify the ticket carries
   an original estimate. A closed ticket without worklog + estimate is not closed
   — if the provider lacks worklog support, the gate skips LOUDLY with a note in
   the summary.
4. Final summary — plain language first (what a non-dev needs), then the
   technical block: gate results, review cards, PR link, side findings,
   task-sheet path.
5. **Close the learning loop** — append a lesson (+ one INDEX line) to
   `docs/qa/knowledge-base.md` or state "no new lesson". Prefer GRADUATION
   over accumulation (§0): machine-checkable → into a gate; unconditional → into
   this workflow; recurring env pattern → known-issues — then delete from KB.

## Stopping mid-ticket (budget hit, owner interrupt, context lost, end of day)

A stop is not a failure. An UNRECORDED stop is: the 2026-09-03 benchmark run ended with 11
uncommitted files, a red unit suite and no closing entry, and the ticket sat "In Progress"
for two weeks. Before the session ends with work in flight, do BOTH:

1. **Leave the tree explainable** — either commit WIP with a `wip(<TICKET>): <what is
   half-done>` message on the ticket branch, or leave the tree dirty; either way run
   `bash .vteam/scripts/stop_state.sh` (Claude Code runs it for you from the SessionEnd
   hook). It writes `evd/<TICKET>/dev/STOP-STATE.md` — branch, HEAD, the
   uncommitted files, the last gate line — and appends a `- stop-state:` line to the
   task-sheet. Never leave a stop that only `git status` can describe.
2. **Name the state on the ticket** — a normal hand-off (you or a teammate resume within
   days) keeps `In Progress`; anything else (blocked on an answer, a budget cut, a
   dead end) sets the status to `Blocked` with a one-line reason and, when the reason is
   a question, a `blocked-by: Qn` edge onto the decision queue.
   `graph_check` reds a STOP-STATE.md older than 7 days on a ticket that is neither Done,
   In Review (handed off) nor Blocked — silent abandonment, not a hand-off.

## Definition of Done
- [ ] T0: ticket announced; assignee = configured person (or user overrode)
- [ ] T0: `dor_check.py <TICKET>` GREEN (or a waiver commented on the ticket —
      durable trace); ticket claimed (In Progress + `claimed <timestamp> · branch`)
      before coding
- [ ] `evd/<TICKET>/dev/tasksheet.md` exists with spec/schema
      citations BEFORE the first edit, and COMMITS with the code
- [ ] T1: change ledger filtered for this ticket's shard/screen; a newly found
      spec contradiction got a `proposed` CH-nn row
- [ ] T1: `docs.task_context` files read (`always:` + this ticket's labels/type)
      when configured; any missing mapped file named loudly in the task-sheet
- [ ] Work on a `feat|fix/<TICKET>-*` branch — zero commits on the protected branch
- [ ] Schema change (if any) has a committed migration + regenerated client
- [ ] /verify gate green, exact result lines recorded
- [ ] UI ticket: the UI quality rules were applied before designing/coding
- [ ] T4a self-review ran: own diff re-read; UI has `fidelity.json` (expecteds
      from design node data) + `ui_fidelity.mjs` GREEN (0 wrong deviations;
      intentional ones carry closed-list intents); results recorded in task-sheet
- [ ] UI: `evd_ui_check.py <TICKET>` GREEN (images in `…/dev/`, correctly named,
      no blank pages, manifest complete, `design_vs_app.png` + `fidelity.md`
      when a design oracle exists)
- [ ] UI: manifest has the `STATE:` line (data/empty/error/loading — N/A with reason)
- [ ] API/backend: `api.md` — one real request→response pair per AC + ≥1 failing case
- [ ] Bug ticket: `evd_ui_check.py <TICKET> --bug` GREEN (`before_*`/`after_*` pair)
- [ ] UI: images attached via `--attach` and the read-back confirmed all names
- [ ] T4b: all required cards APPROVED (R1+R2, +R3 when triggered); cards in
      `review.md` COMMITTED — pre-push runs `review_check.py`
- [ ] PR opened with ticket key; side findings reported, not smuggled in
- [ ] 7-part report comment POSTED and `comment_check.py <TICKET>` GREEN (or
      explicitly PENDING with reason); exact text shown to the user
- [ ] Status transition: In Review after comment + merge (full autonomy); Done is /qa's
- [ ] Every phase narrated with a ▶ line; final summary passes the plain-language bar
- [ ] KB read at T1; lesson appended at T6 (or "no new lesson" stated)
- [ ] T1: code map queried BEFORE the tree read; any map miss named in the task-sheet
- [ ] T2/T3: task-sheet carries **Competencies:** — `dev-identity` + every INDEX
      row matching this ticket; the loaded Reviewer lens blocks went into the R1/R2 briefs
- [ ] T1: tasksheet declares `CODE-SCOPE:` (arms the derailment gate)

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.