Drive the ticket skill through the live ticket page
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
# The ticket page
|
||||
|
||||
Every ticket this skill works has a **ticket page**, and every epic has an **epic index**. The
|
||||
page is where Gib follows the work: the ticket as Jira has it, the plan, live progress, proof
|
||||
beside the mocks, and the review. It updates while you work, so a write you skip is a gap he
|
||||
sees. It is a personal working file, exempt from the prose bar like the rest of `.claude/docs/`.
|
||||
|
||||
```
|
||||
.claude/docs/epics/
|
||||
_site/site.css, site.js # shared renderer, refreshed from templates/site/ on every write
|
||||
<EPIC-KEY>/
|
||||
index.html, epic.data.js # the epic index, in build order
|
||||
<TICKET-KEY>/
|
||||
index.html, ticket.data.js # the ticket page
|
||||
resources/ proof/ deliverables/ mr.md
|
||||
tickets/<TICKET-KEY>/ # same shape, for a ticket with no epic, and no index
|
||||
```
|
||||
|
||||
## Write through `ticket-page`, always
|
||||
|
||||
`~/.agents/skills/ticket/scripts/ticket-page` is the only writer of the data files. It validates
|
||||
before every write and refuses a broken one, writes atomically so the open page never reads half
|
||||
a file, appends each change to the page's live log, and keeps the ticket's row on the epic index
|
||||
current. Editing a `.data.js` file by hand skips all four. `ticket-page help` lists every
|
||||
command and its flags.
|
||||
|
||||
It finds the ticket by key under the current repo's `.claude/docs/epics/`, so run it from inside
|
||||
the repo.
|
||||
|
||||
## What to record, and when
|
||||
|
||||
| Moment | Command |
|
||||
|---|---|
|
||||
| Issue fetched to a scratch path | `init <KEY> --issue <issue.raw.json>`. Prints the ticket folder, then any populated Jira fields the page does not show. |
|
||||
| Attachments downloaded, a video transcribed, frames extracted | `scan <KEY>` |
|
||||
| Ticket branch resolved, ticket classified | `meta <KEY> --branch <name> --classified bounded` |
|
||||
| Research notes worth keeping: what a video says, what a spreadsheet holds, a check against prod | `note <KEY> "<Title>" --file notes.html` |
|
||||
| Plan written | `plan <KEY> --file plan.json`, then one `mock` per artboard |
|
||||
| Plan approved, Phase 2 begins | `approve <KEY>` |
|
||||
| Starting a step | `step <KEY> <n> running` |
|
||||
| A step's commit exists | `step <KEY> <n> done --commit <sha>`, one `--commit` per commit |
|
||||
| A criterion is met | `criterion <KEY> <ID> done --evidence "<what shows it>"` |
|
||||
| Proof captured, or dropped from `proof/` | `proof <KEY> --file proof/<name> --proves AC1,AC3 --caption "<test case>" [--mock <id>]`, `proof <KEY> --test "<name>" ...`, `unproof <KEY> <file>` |
|
||||
| Reviewer finding, and its resolution | `finding <KEY> add "<text>" --severity CONFIRMED --where <file:line>`, then `finding <KEY> F1 fixed --commit <sha>` or `rejected --reason "<why>"` |
|
||||
| pre-mr-review audit read | `verdict <KEY> <verdict text> --recommendation <R> --head <sha>` |
|
||||
| A Jira field PUT and verified | `jira <KEY> "<field name>"` |
|
||||
| `mr.md` written | `mr <KEY>` |
|
||||
| Anything else Gib would want to see happen: suite green, a surprise, a blocker | `event <KEY> "<text>"` |
|
||||
|
||||
A step is done when its commit exists and `ticket-page show <KEY>` lists that commit beside it.
|
||||
`step done` refuses without `--commit`. A step with nothing to commit, such as a verification
|
||||
pass, takes `--no-commit`.
|
||||
|
||||
## `plan.json`
|
||||
|
||||
The plan is one JSON file, written with the Write tool and loaded with `ticket-page plan`. Prose
|
||||
fields are HTML fragments: `<p>`, `<b>`, `<code>`, `<ul><li>`. `plan` replaces any earlier plan
|
||||
and clears its progress and proof, because a rewritten plan is a restart. To change a plan
|
||||
mid-build (a new step, a reworded criterion), print it with `plan-json <KEY> > plan.json`, edit
|
||||
that, and load it with `plan --amend`: steps whose number and text are unchanged, and
|
||||
criteria whose id remains, keep their progress, and proof keeps the criteria that still exist.
|
||||
|
||||
```json
|
||||
{
|
||||
"criteria": [
|
||||
{ "id": "AC1", "text": "Every company can carry a five character canonical ID.", "steps": [1, 2] },
|
||||
{ "id": "AC2", "text": "A duplicate canonical ID is rejected with a readable message.", "steps": [3] }
|
||||
],
|
||||
"questions": [],
|
||||
"approach": "<p><b>Company.canonicalId</b> is the only new state. The engagement ID is derived by <code>formatEngagementCanonicalId</code>, so the two cannot drift.</p>",
|
||||
"decisions": [["Engagement canonical ID", "Derived at read time", "Matches the spreadsheet formula, with no second column to backfill."]],
|
||||
"steps": [
|
||||
{ "n": 1, "text": "Add the canonicalId module, tests first.", "tdd": true },
|
||||
{ "n": 2, "text": "Schema, migration and backfill." },
|
||||
{ "n": 3, "text": "Map the unique violation to CONFLICT.", "tdd": true },
|
||||
{ "n": 4, "text": "Canonical ID field on the company form.", "kind": "mock" }
|
||||
],
|
||||
"risks": [
|
||||
{ "risk": "Two companies given the same code", "handling": "The unique index blocks it and step 3 returns a readable CONFLICT.", "criteria": ["AC2"], "fromTicket": true }
|
||||
],
|
||||
"tests": [
|
||||
{ "kind": "integration", "text": "companies.update with a taken code throws CONFLICT.", "criteria": ["AC2"] }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
- Steps are numbered 1 to N in order. `kind` is `code` (the default), `mock`, or `deliverable`.
|
||||
- Every criterion names the steps that satisfy it. Risks and tests name the criteria they cover.
|
||||
- A risk or test that comes from the ticket's own table carries `"fromTicket": true`. Your own
|
||||
additions leave it off, so the page shows which rows the ticket asked for.
|
||||
- `questions` holds only what genuinely needs Gib's answer, each as a direct question. Empty
|
||||
means none.
|
||||
|
||||
## Mocks
|
||||
|
||||
When a step changes what a user sees (a new screen, a changed layout, a new control, copy a
|
||||
user reads), the plan carries mock artboards:
|
||||
|
||||
```
|
||||
ticket-page mock <KEY> <id> --title "<screen>" --criteria AC3,AC8 --note "<what the build will not do>" --file artboard.html
|
||||
```
|
||||
|
||||
- An artboard is a complete small HTML document with its own `<style>`, rendered in a sandboxed
|
||||
frame beside the proof. Draw the screen state the plan introduces, with the app's real
|
||||
navigation and density around it rather than a wireframe of boxes.
|
||||
- One artboard per new screen state. When the direction is Gib's call, draw each candidate as
|
||||
its own artboard (`option-a`, `option-b`) and ask the choice in `questions`, naming the
|
||||
artboards. This is how the house rule of several static mocks before touching real components
|
||||
is met inside the ticket flow.
|
||||
- `--criteria` names what the artboard illustrates. The Progress tab shows it under those
|
||||
criteria, and replaces the empty half with the proof once a `proof ... --mock <id>` lands.
|
||||
- `--note` states what the artboard shows that the implementation will not do.
|
||||
- A spike deliverable's polished mocks (see **Mocks and datamodel changes**) can start from the
|
||||
approved artboard. The built screens are still screenshotted for real.
|
||||
|
||||
## The epic index
|
||||
|
||||
The index lists the epic's stories in build order: the order they should be completed in, which
|
||||
is not key order and not always the Jira link graph. Each worked ticket keeps its own row current.
|
||||
The rest of the index is yours to seed and keep true.
|
||||
|
||||
- **Seed it** the first time a ticket under the epic is worked, and refresh it on later runs.
|
||||
Search the epic's children (`parent = <EPIC> ORDER BY rank`). For each, record the title, the
|
||||
estimate as `--hours`, the Story Risk Level as `--risk`, the stories it is blocked by as
|
||||
`--after`, and `--status done` if Jira says Done: `ticket-page epic <EPIC> story <KEY> ...`.
|
||||
Closed spikes go in with `epic <EPIC> closed <KEY> --title T`.
|
||||
- **Set the order** with `ticket-page epic <EPIC> order <KEY> <KEY> ...`, listing every story. If
|
||||
the epic already records a build order (a `summary.md` or plan in its folder), that order wins.
|
||||
Otherwise order by the blocked-by links, then Jira rank. Write the reasons the order is what it
|
||||
is with `epic <EPIC> why --file reasons.txt`, one reason per line.
|
||||
- **Gib reorders by asking.** When he does, rerun `order` and update `why`.
|
||||
- A story is marked done only by `--status done`, once it has merged or Jira says Done. The index
|
||||
never guesses that.
|
||||
|
||||
## Reading it as an agent
|
||||
|
||||
`ticket-page md <KEY>` prints the ticket and the plan as markdown. Use it when you resume a
|
||||
ticket, and hand it to the fresh reviewer as the ticket and plan in its reading order.
|
||||
|
||||
## Tickets from before the page
|
||||
|
||||
Tickets planned before the page existed have `resources/ticket.md` and `plan.md` and no
|
||||
`ticket.data.js`. Leave those files alone. When Phase 0 resumes such a ticket, convert it
|
||||
first: `init` from `resources/issue.raw.json`, `plan` from the plan's content, then `approve` and
|
||||
`step ... done` for each step `git log` shows committed. From then on the page is the record.
|
||||
+156
-230
@@ -1,14 +1,14 @@
|
||||
---
|
||||
name: ticket
|
||||
description: End-to-end Jira ticket workflow — fetch a ticket into .claude/docs/epics/, write a plan and its plan.html review page, 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, 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.
|
||||
disable-model-invocation: true
|
||||
---
|
||||
|
||||
# Ticket Workflow
|
||||
|
||||
Turns a Jira ticket key into: a saved ticket record, a reviewed plan, implemented and
|
||||
committed code, a converged `pre-mr-review` audit, and an MR doc ready to paste into
|
||||
GitLab/GitHub. This skill is user-level (`~/.agents/skills/ticket/`) and works the same
|
||||
Turns a Jira ticket key into: a live ticket page carrying the ticket, a reviewed plan,
|
||||
progress, and proof, implemented and committed code, a converged `pre-mr-review` audit, and
|
||||
an MR doc ready to paste into GitLab/GitHub. This skill is user-level (`~/.agents/skills/ticket/`) and works the same
|
||||
way in any repo that has a `.claude/docs/` directory and a `pre-mr-review` skill.
|
||||
|
||||
Invoked as `/ticket KACP-11111`. The ticket key is passed as the skill's arguments. Called
|
||||
@@ -19,38 +19,48 @@ Jira story, the estimate, risk level, and testing tables, as part of authoring a
|
||||
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.
|
||||
|
||||
## The ticket page
|
||||
|
||||
Every ticket gets a **ticket page**, a web page Gib keeps open while you work: the ticket as
|
||||
Jira has it, the plan with its mocks, live progress, proof beside the mocks, and the review.
|
||||
Every epic gets an **epic index** listing its stories in build order. Both render from data
|
||||
files that only `ticket-page` writes, and both update themselves as it writes.
|
||||
|
||||
**Read [SITE.md](SITE.md) before the first write of every run.** It holds the command for each
|
||||
moment the phases below name, the plan's JSON shape, how to draw mocks, and how the epic order
|
||||
is seeded. Record each moment when it happens, not in a batch at the end, because Gib is
|
||||
watching the page change.
|
||||
|
||||
## Directory layout this skill maintains
|
||||
|
||||
```
|
||||
.claude/docs/epics/
|
||||
_site/ # the shared renderer, refreshed by ticket-page
|
||||
<EPIC-KEY>/
|
||||
epic.md # brief epic context, written once, best-effort
|
||||
index.html, epic.data.js # the epic index
|
||||
<TICKET-KEY>/
|
||||
index.html, ticket.data.js # the ticket page
|
||||
resources/
|
||||
ticket.md # title, description, dev review instructions
|
||||
issue.raw.json # the fetched issue, kept for re-imports
|
||||
<attachments...> # images, videos, other files as downloaded
|
||||
<video>.transcript.txt # only for videos that got transcribed
|
||||
<video>.transcript.srt
|
||||
plan.md
|
||||
plan.html # the plan as a page, with mocks when a step changes what a user sees
|
||||
deliverables/ # only for tickets whose output is documents, not code
|
||||
<video>.frames/
|
||||
deliverables/ # only for tickets whose output is documents, not code
|
||||
<deliverable-slug>/
|
||||
<deliverable-slug>.md
|
||||
<deliverable-slug>.typ
|
||||
<deliverable-slug>.pdf
|
||||
proof/ # captured working feature proof, uploaded to Jira by the user
|
||||
proof/ # captured working feature proof, uploaded to Jira by the user
|
||||
mr.md # the MR description only, written once pre-mr-review says Ready to Open MR
|
||||
tickets/
|
||||
<TICKET-KEY>/ # same shape, for tickets with no epic
|
||||
resources/...
|
||||
plan.md
|
||||
plan.html
|
||||
deliverables/...
|
||||
mr.md
|
||||
<TICKET-KEY>/ # same shape, for tickets with no epic, and no index
|
||||
```
|
||||
|
||||
## Scripts this skill uses
|
||||
|
||||
- `~/.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/jira-fetch-issue.sh <KEY> <OUT.json>` — fetches one
|
||||
issue (`fields=*all`, rendered HTML description, field-name map) via `JIRA_BASE_URL` /
|
||||
`JIRA_CREDENTIALS`.
|
||||
@@ -101,8 +111,8 @@ rerun it, and verify the device log instead of accepting the fallback transcript
|
||||
## House style (applies to everything this skill writes or commits)
|
||||
|
||||
- No code comments unless the user explicitly asks for one in that spot.
|
||||
- No em dashes, en dashes, semicolons, or arrow glyphs in commit messages, `ticket.md`,
|
||||
`plan.md`, or `mr.md`. Plain punctuation only.
|
||||
- No em dashes, en dashes, semicolons, or arrow glyphs in commit messages, the ticket page,
|
||||
or `mr.md`. Plain punctuation only.
|
||||
- Commits are `git commit -m "<short imperative message>"` only — no body, no
|
||||
co-author line, no `Claude` / `Codex` / `AI` trailer of any kind.
|
||||
- Never `git push`. Never open an MR/PR. This skill prepares everything needed to open
|
||||
@@ -161,19 +171,18 @@ the document.** Being aligned first is the point, and the writing should read as
|
||||
you always were.
|
||||
|
||||
This governs `mr.md`, `customfield_10260` and `10261`, every other Jira field, and PM
|
||||
deliverables. It does not govern files only he reads. `plan.md`, `bugs.md`, audits and
|
||||
deliverables. It does not govern files only he reads. The ticket page, `bugs.md`, audits and
|
||||
working notes can name him and record who decided what, because that history is useful.
|
||||
|
||||
The House style punctuation rule above is the stricter one where the two overlap. Keep
|
||||
it. Personal working files (`plan.md`, `plan.html`, `ticket.md`) are exempt, nobody else
|
||||
reads them.
|
||||
it. The ticket page is a personal working file and exempt, nobody else reads it.
|
||||
|
||||
## Verification tools available
|
||||
|
||||
The goal isn't "a plausible-sounding plan" or "code that compiles" — it's a plan and
|
||||
an implementation that are actually correct, checked against the real system rather
|
||||
than assumed from the ticket text. Use whichever of these actually verify the thing
|
||||
in question, before writing `plan.md` (Phase 1) and again whenever Phase 2's
|
||||
in question, before writing the plan (Phase 1) and again whenever Phase 2's
|
||||
implementation makes a claim that's checkable:
|
||||
|
||||
- **The codebase itself.** Don't take the ticket's description of "how things work
|
||||
@@ -199,7 +208,7 @@ implementation makes a claim that's checkable:
|
||||
about explicitly rather than assume the file's DB credential is fair game by default.
|
||||
|
||||
If something would need access you don't have (a different repo, a system you can't
|
||||
reach), say so explicitly in `plan.md`'s Open questions instead of silently skipping
|
||||
reach), say so explicitly in the plan's open questions instead of silently skipping
|
||||
the check.
|
||||
|
||||
**How to write what you found, in a deliverable.** State it as a plain confirmed
|
||||
@@ -213,7 +222,7 @@ codebase equally.
|
||||
|
||||
Some tickets (spikes, research, migration proposals, the KACP-22764 kind of ticket)
|
||||
don't produce code, they produce documents for a PM or another engineer to read. When
|
||||
a `plan.md` Step produces a document rather than a code change, it becomes its own
|
||||
a plan step produces a document rather than a code change, it becomes its own
|
||||
subfolder under `<target-dir>/deliverables/<deliverable-slug>/` with three files:
|
||||
|
||||
- `<slug>.md` — the source of truth for content. Write this first, get the content
|
||||
@@ -228,11 +237,10 @@ subfolder under `<target-dir>/deliverables/<deliverable-slug>/` with three files
|
||||
- `<slug>.pdf` — compiled from the `.typ` file.
|
||||
|
||||
**Write for the actual audience, not for yourself.** The reader is a PM or another
|
||||
engineer who has never seen `.claude/docs/`, doesn't know what `plan.md` or
|
||||
`ticket.md` are, and doesn't have this repo (or any other local repo) checked out.
|
||||
Never reference `.claude/docs/` or any local file path in a deliverable's content.
|
||||
Never say "see plan.md" or "see ticket.md", those are personal working files, not
|
||||
things a reader can open. Refer to "this ticket" or a plain Jira link, not a local
|
||||
engineer who has never seen `.claude/docs/` or the ticket page, and doesn't have this
|
||||
repo (or any other local repo) checked out. Never reference `.claude/docs/` or any local
|
||||
file path in a deliverable's content. Never point the reader at the ticket page or the
|
||||
plan, those are personal working files, not things a reader can open. Refer to "this ticket" or a plain Jira link, not a local
|
||||
path. If a fact came from another repo on this machine, state the fact, don't cite
|
||||
the local checkout path it came from.
|
||||
|
||||
@@ -318,7 +326,7 @@ describe it only as a quick UI mockup.
|
||||
|
||||
When a ticket calls for mocks or datamodel changes (a spike proposing new screens or a
|
||||
new schema, for instance), don't stop at wireframes or a schema proposal document.
|
||||
Build it for real, on the ticket's branch. Mark these steps `(mock)` in `plan.md`.
|
||||
Build it for real, on the ticket's branch. Give these steps `"kind": "mock"` in the plan.
|
||||
|
||||
A mock deliverable is **two artifacts**, not one, and they answer different questions.
|
||||
The code proves the thing is buildable and surfaces the problems a picture hides. The
|
||||
@@ -351,7 +359,7 @@ what was quick to wire up. Ship both, and don't let either stand in for the othe
|
||||
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
|
||||
screenshotted and evaluated. If doing it for real would take significantly longer
|
||||
than a static mock would, say so in `plan.md` rather than silently scoping it down
|
||||
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 a browser automation tool (e.g. `claude-in-chrome`) to capture
|
||||
@@ -372,41 +380,6 @@ Reach for it when the spike's real open question is which of several directions
|
||||
build. Once a direction is settled, the deliverable is the two artifacts above, and both
|
||||
ship with the ticket.
|
||||
|
||||
## The plan page (`plan.html`)
|
||||
|
||||
`plan.md` is the plan. `plan.html` is the same plan as a page, saved beside it, so Gib
|
||||
reads the plan in a browser before approving it instead of scrolling a markdown file. It
|
||||
opens from `file://`, ticks acceptance criteria and steps as he reviews them, and shows
|
||||
the mocks in place. It is the review artifact, and it exists to be opened.
|
||||
|
||||
- **Fill the template.** Copy `~/.agents/skills/ticket/templates/plan.html` to
|
||||
`<target-dir>/plan.html` and fill every slot its header comment lists, in the order
|
||||
`plan.md` carries them: the same criteria, the same open questions, the same Approach,
|
||||
the same steps with the same `(mock)` and `(deliverable)` marks as badges, the same
|
||||
risks, the same test plan. Fill the slots only. The CSS and script ship as they are, so
|
||||
every plan page looks and behaves the same. Done when a reader of either file learns
|
||||
nothing the other omits.
|
||||
- **Mocks, when a step changes what a user sees.** A new screen, a changed layout, a new
|
||||
control, or copy a user reads means the page keeps its Mocks section: one artboard per
|
||||
screen state the plan introduces, drawn in plain HTML and CSS inside its own
|
||||
`<template>`, with the app's real navigation and density around it rather than a
|
||||
wireframe of boxes. When the direction is Gib's call, draw each candidate as its own
|
||||
artboard (Option A, Option B) and name the choice in Open questions, pointing at the
|
||||
artboards. When the direction is settled, one artboard per screen. Each artboard's
|
||||
`data-note` states what it shows that the implementation will not do. This is how the
|
||||
house rule about several static mocks before touching real components is satisfied
|
||||
inside the ticket flow, so no separate mock server is needed. When no step changes
|
||||
what a user sees, delete the Mocks section and its nav link.
|
||||
- **Open it.** After saving, run `xdg-open <target-dir>/plan.html` so it lands in the
|
||||
browser, and give both paths in the Phase 1 wrap-up.
|
||||
- **`plan.md` stays the source of truth.** When Phase 0 routes to rewriting the plan,
|
||||
rewrite `plan.html` with it. Phase 2 checks steps off in `plan.md` only. The page is a
|
||||
snapshot for the review and is left alone once the plan is approved.
|
||||
- **Relation to spike mocks.** The plan page's artboards are design intent drawn before
|
||||
any code exists. A deliverable's polished `mocks/` (see Mocks and datamodel changes)
|
||||
can start from the approved artboard, and the built screens are still screenshotted
|
||||
for real.
|
||||
|
||||
---
|
||||
|
||||
## Branch setup — run this before any repo work in Phase 1 or Phase 2
|
||||
@@ -450,7 +423,7 @@ through, and the branch needs to already exist when that happens.
|
||||
|
||||
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 `ticket.md`/`plan.md`/`mr.md` directly — this is about making sure any
|
||||
doesn't affect the ticket page or `mr.md` directly — this is about making sure any
|
||||
actual code (mockup prototypes, spike code, real implementation) lands in the right
|
||||
place from the start.
|
||||
|
||||
@@ -460,21 +433,23 @@ place from the start.
|
||||
correct key.
|
||||
2. Look for an existing directory for this ticket without hitting the network:
|
||||
`find .claude/docs/epics -mindepth 2 -maxdepth 2 -type d -name "<KEY>"`
|
||||
(this matches both `epics/<EPIC>/<KEY>` and `epics/tickets/<KEY>`).
|
||||
(this matches both `epics/<EPIC>/<KEY>` and `epics/tickets/<KEY>`). If it holds a
|
||||
`plan.md` but no `ticket.data.js`, it predates the ticket page: convert it first, as
|
||||
[SITE.md](SITE.md) describes under **Tickets from before the page**, then continue.
|
||||
`ticket-page show <KEY>` says where the ticket stands.
|
||||
3. Branch on what you find:
|
||||
- **Nothing found** — this is a fresh ticket. Go to **Phase 1**.
|
||||
- **Directory exists, no `plan.md`** — a previous run was interrupted before writing
|
||||
a plan. Go to **Phase 1** and regenerate from scratch (re-fetch, overwrite
|
||||
`ticket.md`, re-check attachments); it's idempotent and cheap.
|
||||
- **`plan.md` exists, no `mr.md`** — ask the user (AskUserQuestion) what they want:
|
||||
- Re-fetch the ticket and rewrite the plan (`plan.md` and `plan.html`) from scratch
|
||||
(they want to start over)
|
||||
- Proceed to implementing the existing `plan.md` as-is (they reviewed and approved it)
|
||||
- Resume implementation (some plan steps are already checked off / some commits
|
||||
already exist on the ticket branch — pick up from the first unchecked step)
|
||||
- **A page with no plan** — a previous run was interrupted before writing a plan. Go
|
||||
to **Phase 1** and regenerate from scratch (re-fetch, re-import, re-check
|
||||
attachments); it's idempotent and cheap.
|
||||
- **A plan, no `mr.md`** — ask the user (AskUserQuestion) what they want:
|
||||
- Re-fetch the ticket and rewrite the plan from scratch (they want to start over)
|
||||
- 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)
|
||||
Route to **Phase 1** or **Phase 2** accordingly.
|
||||
- **Both `plan.md` and `mr.md` exist** — this ticket looks finished. Tell the user
|
||||
- **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
|
||||
(e.g. they made more changes since) or leave it alone. Only re-enter Phase 2's
|
||||
verification/pre-mr-review loop if they say the code changed since `mr.md` was
|
||||
@@ -485,83 +460,39 @@ place from the start.
|
||||
## Phase 1 — fetch, scaffold, and plan
|
||||
|
||||
1. Do **Branch setup** above first, unconditionally.
|
||||
2. Run `jira-fetch-issue.sh <KEY> <tmp-path>` (a scratch path is fine here — you don't
|
||||
yet know the final directory). Read the resulting JSON.
|
||||
3. Determine the epic: `fields.parent.key`, if present. If absent, this ticket has no
|
||||
epic.
|
||||
4. Resolve the target directory:
|
||||
- With epic: `.claude/docs/epics/<EPIC-KEY>/<KEY>/`
|
||||
- Without epic: `.claude/docs/epics/tickets/<KEY>/`
|
||||
Create it and its `resources/` subdirectory.
|
||||
5. Move/copy the fetched JSON to `<target-dir>/resources/issue.raw.json` for your own
|
||||
reference while writing `ticket.md` — this raw file is scratch, not part of the
|
||||
deliverable; feel free to leave it (it's harmless context for later) or delete it
|
||||
once `ticket.md` is written, your call.
|
||||
6. If there's an epic and `.claude/docs/epics/<EPIC-KEY>/epic.md` doesn't already exist:
|
||||
best-effort fetch the epic issue too (`jira-fetch-issue.sh <EPIC-KEY> <tmp>`) and
|
||||
write a short `epic.md` (title + description, converted to markdown, a couple
|
||||
paragraphs at most). If this fetch fails for any reason, skip it and continue — it's
|
||||
context, not a blocker.
|
||||
7. Write `resources/ticket.md` by reading the fetched issue JSON yourself:
|
||||
- Title, type, status, priority, assignee, epic key (or "None"), and a link
|
||||
(`<JIRA_BASE_URL>/browse/<KEY>`).
|
||||
- Description: convert `renderedFields.description` (HTML) to clean markdown. If
|
||||
empty, say so.
|
||||
- Developer review instructions: the field name varies by project and isn't a fixed
|
||||
custom field ID. Look at the `names` map in the response for any field whose name
|
||||
matches something like "dev review instructions" / "review instructions"
|
||||
(case-insensitive substring match), then render that field's value the same way as
|
||||
the description. If nothing matches, write "None provided" — don't guess a field.
|
||||
- Test cases: same approach for any field whose name matches something like
|
||||
"test cases" / "test table" / "working feature proof" / "qa" (case-insensitive
|
||||
substring match), e.g. KACP's "Test Cases & Working Feature Proof" field. This
|
||||
is part of the ticket's testing section and MUST be captured into `ticket.md`
|
||||
whenever it holds anything beyond an empty template. Often it's just the bare
|
||||
instruction panel and empty table, note that and move on. But when it has real
|
||||
content, that content is part of the implementation and has to be known from
|
||||
the start: render every row verbatim as a markdown table under its own
|
||||
`## Test cases and working feature proof` heading, keeping the ticket's own
|
||||
column headers, and carry any prose or instructions in the field alongside the
|
||||
table. These are the scenarios the developer must prove, so Phase 1's plan must
|
||||
already say how each row gets proven, Phase 2's verification must actually
|
||||
prove each row, and Phase 2 step 9 fills the proof column back into the Jira
|
||||
field itself. If nothing matches, write "None provided".
|
||||
- Risk mitigation: same approach for any field whose name matches something like
|
||||
"risk mitigation" / "risk management" / "risks" (case-insensitive substring
|
||||
match), e.g. KACP's "Risk Mitigation" field. Same rule as test cases: an empty
|
||||
template gets noted, real content gets captured in full because it shapes the
|
||||
implementation from the start. Render it as a markdown table under its own
|
||||
`## Risk mitigation` heading, keeping the ticket's own column headers and
|
||||
every row verbatim. The PM and Lead Developer write the risks and mitigation
|
||||
strategies; implementing those strategies and proving each one is the developer's
|
||||
job, so every row needs a real mitigation in the code and its proof filled into
|
||||
the Jira field in Phase 2 step 9. If nothing matches, write "None provided".
|
||||
- Developer fill-in tables, in general: any ticket table with a column the developer
|
||||
is meant to complete (Working Feature Proof, Mitigation Proof, and the like) is
|
||||
copied into `ticket.md` in full, with that column left showing where its answer
|
||||
goes rather than dropped. `ticket.md` is the record of what the ticket actually
|
||||
asks for. Never substitute your own invented test cases or risks for the ticket's,
|
||||
in `ticket.md` or in the Jira fields. Your own additional cases are welcome, but
|
||||
they go alongside the ticket's rows, clearly marked as additional, never in place
|
||||
of them.
|
||||
- Sweep for anything else populated: list every key in the `names` map whose field
|
||||
actually has a non-null, non-empty value on this issue (jq over `.fields` joined
|
||||
with `.names`), and skim any populated field not already captured above. Capture
|
||||
the ones relevant to implementing or verifying the ticket; ignore workflow
|
||||
plumbing (ranks, sprints boards, reviewer assignments, rich-field duplicates).
|
||||
This exists because real content sometimes hides in per-project custom fields
|
||||
with unpredictable names — a name-pattern miss must not silently drop content.
|
||||
- Any other fields on the ticket that look clearly relevant to implementing it
|
||||
(acceptance criteria field, story points, labels, components) are worth a short
|
||||
line each; don't dump every custom field verbatim.
|
||||
8. Run `jira-download-attachments.sh <issue.raw.json> <target-dir>/resources/`. For each
|
||||
2. Run `jira-fetch-issue.sh <KEY> <tmp-path>` (a scratch path is fine here — the next
|
||||
step knows the final directory). Read the resulting JSON.
|
||||
3. Import it: `ticket-page init <KEY> --issue <tmp-path>`. This files the ticket under its
|
||||
epic (or `tickets/` without one), imports every rich-text field verbatim as sanitized
|
||||
HTML, writes the page, and prints the ticket folder. Copy the fetched JSON to
|
||||
`<target-dir>/resources/issue.raw.json`, which later re-imports and the attachment
|
||||
script read. Record the branch from **Branch setup** with `ticket-page meta`, then open
|
||||
the page with `ticket-page open <KEY>` so Gib can follow from here on.
|
||||
4. `init` ends by listing populated Jira fields the page does not show. Read each one and
|
||||
add any that bear on implementing or verifying the ticket as a note. This sweep exists
|
||||
because real content sometimes hides in per-project custom fields with unpredictable
|
||||
names, and a name-pattern miss must not silently drop it.
|
||||
5. Read what the Ticket tab now holds, and treat its tables as the ticket's contract.
|
||||
- **Test cases** (KACP's "Test Cases & Working Feature Proof") and **risk mitigation**
|
||||
are imported with every row verbatim. Often a field is just the bare instruction
|
||||
panel and an empty table, which needs no further thought. When it has real rows,
|
||||
those are the scenarios the developer must prove and the mitigations the developer
|
||||
must implement: the plan names each one (`"fromTicket": true`), Phase 2 proves each
|
||||
one, and Phase 2 step 9 fills its proof column back into the Jira field. The PM and
|
||||
Lead write the risks. Implementing and proving each is the developer's job.
|
||||
- Never substitute your own invented test cases or risks for the ticket's, in the plan
|
||||
or in the Jira fields. Your own additional cases are welcome alongside the ticket's
|
||||
rows, never in place of them.
|
||||
6. If the ticket has an epic, seed or refresh its epic index as [SITE.md](SITE.md)
|
||||
describes under **The epic index**. This is best-effort context: if the epic search
|
||||
fails, say so and continue.
|
||||
7. Run `jira-download-attachments.sh <issue.raw.json> <target-dir>/resources/`. For each
|
||||
attachment with a `video/*` mime type, check whether another attachment already looks
|
||||
like its transcript (same base filename with `.txt`/`.srt`/`.vtt`, or a filename
|
||||
containing "transcript"). Collect any videos with no matching transcript.
|
||||
9. If there are untranscribed videos, ask the user (AskUserQuestion, one question,
|
||||
8. If there are untranscribed videos, ask the user (AskUserQuestion, one question,
|
||||
multiSelect if more than one video) whether to transcribe them now. For each they
|
||||
approve, run `transcribe.sh <video-path> <target-dir>/resources/`. Note in `ticket.md`
|
||||
under Attachments which videos have a transcript and which were skipped.
|
||||
approve, run `transcribe.sh <video-path> <target-dir>/resources/`.
|
||||
For every video that gets transcribed, also extract frames — ticket videos are
|
||||
almost always screen recordings, and the transcript alone misses what was on
|
||||
screen (the UI being pointed at, the annotation, the row that's wrong). Extract to
|
||||
@@ -574,6 +505,10 @@ place from the start.
|
||||
and treat what's visible on screen as part of the ticket's content the same way
|
||||
the transcript is. Skip frame extraction only when the video is confirmed
|
||||
audio-only or the user says the visuals don't matter.
|
||||
9. Run `ticket-page scan <KEY>` so the page carries the attachments, each video with its
|
||||
transcript and frames. When a video, spreadsheet, or linked document holds the
|
||||
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
|
||||
@@ -588,54 +523,33 @@ place from the start.
|
||||
**architectural** is a new subsystem, a schema change other stories depend on, or
|
||||
anything that alters an interface neighbouring work relies on. Bounded is the common
|
||||
case and goes straight to step 11. For architectural, call the Skill tool with
|
||||
"grilling" and resolve its frontier with Gib BEFORE writing `plan.md` — those
|
||||
"grilling" and resolve its frontier with Gib BEFORE writing the plan — those
|
||||
questions get answered in conversation, not deferred into the plan's Open questions
|
||||
section, because an architectural plan built on a wrong assumption is the expensive
|
||||
one to discover in Phase 2. Bounded measures the repo, not your familiarity: if the
|
||||
flow being changed isn't already there to read, it isn't bounded. In doubt, take the
|
||||
heavier path.
|
||||
11. Write `plan.md` in `<target-dir>/plan.md` (a sibling of `resources/`, not inside
|
||||
it). Structure:
|
||||
```
|
||||
# Plan: <KEY> — <short title>
|
||||
heavier path. Either way, record the classification with `ticket-page meta`.
|
||||
11. Write the plan as `plan.json` in a scratch path, in the shape [SITE.md](SITE.md) gives,
|
||||
and load it with `ticket-page plan <KEY> --file plan.json`. Its parts: acceptance
|
||||
criteria restated precisely from the ticket, each naming the steps that satisfy it;
|
||||
open questions that genuinely need Gib's answer, empty if there really aren't any
|
||||
(don't manufacture questions to look thorough); the approach, meaning what you're
|
||||
going to do and why, which files, modules and functions are involved, and how it fits
|
||||
the existing patterns; decisions already settled with Gib; steps, each roughly one
|
||||
commit's worth of work, with `"kind": "deliverable"` for a step that produces a
|
||||
document via **Deliverable documents** and `"kind": "mock"` for a real schema or UI
|
||||
change built to demonstrate a mock (see **Mocks and datamodel changes**); risks and
|
||||
edge cases, each with how the plan handles it; and the test plan, meaning how each
|
||||
criterion gets verified, the existing suites to run, and any new tests.
|
||||
|
||||
## Acceptance criteria
|
||||
- [ ] <criterion from the ticket, restated precisely>
|
||||
...
|
||||
|
||||
## Open questions
|
||||
<Anything genuinely blocking or ambiguous that needs the user's answer before or
|
||||
during implementation. "None" if there really aren't any — don't manufacture
|
||||
questions to look thorough.>
|
||||
|
||||
## Approach
|
||||
<Narrative: what you're going to do and why, which files/modules/functions are
|
||||
involved, how it fits the existing patterns in this codebase.>
|
||||
|
||||
## Steps
|
||||
- [ ] <step 1, roughly one commit's worth of work — mark it `(deliverable)` if it
|
||||
produces a document via the Deliverable documents process instead of code, or
|
||||
`(mock)` if it's a real schema/UI change built to demonstrate a mock rather than
|
||||
ship a finished feature, see Mocks and datamodel changes>
|
||||
- [ ] <step 2>
|
||||
...
|
||||
|
||||
## Risks and edge cases considered
|
||||
- <edge case> — <how the plan handles it>
|
||||
...
|
||||
|
||||
## Test plan
|
||||
- <how you'll verify each acceptance criterion, including existing test suites to
|
||||
run and any new tests to add>
|
||||
```
|
||||
Be thorough: address every acceptance criterion, resolve as many open questions as
|
||||
you reasonably can by reading the code first, and don't leave logic gaps. Steps
|
||||
should be concrete enough that Phase 2 can execute them without re-deriving the
|
||||
approach. The Test plan must name every test case `ticket.md` captured and say how
|
||||
that exact case gets proven, and the Risks section must name every risk
|
||||
`ticket.md` captured and say which code enforces its mitigation. Read the notes
|
||||
column of a ticket test case as part of the case, not as commentary: a note like
|
||||
"confirm the certificate matches the emailed version" is its own thing to prove.
|
||||
approach. The test plan must name every test case on the Ticket tab and say how
|
||||
that exact case gets proven, and the risks must name every risk on the Ticket tab
|
||||
and say which code enforces its mitigation. Read the notes column of a ticket test
|
||||
case as part of the case, not as commentary: a note like "confirm the certificate
|
||||
matches the emailed version" is its own thing to prove.
|
||||
|
||||
**Where the shape is in question, borrow the vocabulary.** When the plan has to
|
||||
decide how deep a module should be, where a seam belongs, or what an interface
|
||||
@@ -645,7 +559,7 @@ place from the start.
|
||||
written for real.
|
||||
|
||||
**The Test plan is a design decision, not a formality.** Beyond the cases
|
||||
`ticket.md` already captured, call the Skill tool with "tdd" to decide which
|
||||
the ticket already carries, call the Skill tool with "tdd" to decide which
|
||||
additional tests are worth writing, where the seam under test goes, and whether a
|
||||
mock is warranted. That judgment is what keeps this section focused instead of
|
||||
padded: a test plan listing one case per changed file is slop, and three tests that
|
||||
@@ -662,13 +576,14 @@ place from the start.
|
||||
step stays green because the old form still exists until the last one. Say in the
|
||||
Approach that this is what you're doing and why, since the step count looks inflated
|
||||
otherwise.
|
||||
12. Write `plan.html` beside it, per **The plan page** above, and open it with
|
||||
`xdg-open`.
|
||||
13. Stop here. Tell the user `plan.md` and `plan.html` are ready at their paths and that
|
||||
the page is open in the browser, summarize the approach in a couple of sentences, and
|
||||
mention any open questions that need their input before you'd implement it. Do not
|
||||
start implementing in this same run — wait for them to review the plan (editing
|
||||
`plan.md` directly if they want) and invoke `/ticket <KEY>` again.
|
||||
12. When a step changes what a user sees, draw its mock artboards with `ticket-page mock`,
|
||||
as [SITE.md](SITE.md) describes under **Mocks**.
|
||||
13. Stop here. Tell the user the plan is on the ticket page, give its path from
|
||||
`ticket-page path <KEY>`, summarize the approach in a couple of sentences, and mention
|
||||
any open questions that need their input before you'd implement it. Do not start
|
||||
implementing in this same run — wait for them to review the plan and invoke
|
||||
`/ticket <KEY>` again. They change the plan by asking, and you rewrite it with
|
||||
`ticket-page plan`.
|
||||
|
||||
## Phase 2 — implement, verify, and hand off
|
||||
|
||||
@@ -677,14 +592,16 @@ Entered only when the user has confirmed (per Phase 0) that the plan is approved
|
||||
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
|
||||
user may have switched branches between runs).
|
||||
2. Read `plan.md` fresh — the user may have hand-edited it.
|
||||
3. Work through `plan.md`'s Steps checklist in order. For each step: implement it (a
|
||||
step marked `(deliverable)` follows the **Deliverable documents** process above
|
||||
instead of writing code; a step marked `(mock)` follows **Mocks and datamodel
|
||||
changes** — real schema/UI work, not a static wireframe), then check it off
|
||||
(`- [x]`) in `plan.md`, then make one commit for it (or a few, if the step
|
||||
naturally splits into independent units). Commit messages are short and imperative,
|
||||
describing what changed, following House style above.
|
||||
2. Read the plan fresh with `ticket-page md <KEY>`, then mark it approved with
|
||||
`ticket-page approve <KEY>`.
|
||||
3. Work through the plan's steps in order. For each step: implement it (a
|
||||
`deliverable` step follows the **Deliverable documents** process above instead of
|
||||
writing code; a `mock` step follows **Mocks and datamodel changes** — real schema/UI work, not a static wireframe), and make one commit for it (or
|
||||
a few, if the step naturally splits into independent units). Commit messages are short
|
||||
and imperative, describing what changed, following House style above. Mark the step
|
||||
running on the page when you start it and done with its commits when they exist, and
|
||||
mark each acceptance criterion met the moment it is (SITE.md has the commands). A step
|
||||
is done when `ticket-page show <KEY>` lists its commit.
|
||||
|
||||
**Write the test first for steps that carry real logic**, meaning a router
|
||||
procedure, a derivation, a permission or authorization check, a migration, or a
|
||||
@@ -696,11 +613,13 @@ Entered only when the user has confirmed (per Phase 0) that the plan is approved
|
||||
House style rejects. When unsure whether a step qualifies, ask whether the test could
|
||||
ever fail for a reason worth knowing about. If it couldn't, skip it.
|
||||
|
||||
If a step fails in a way `plan.md` didn't predict, and the cause isn't obvious within
|
||||
If a step fails in a way the plan didn't predict, and the cause isn't obvious within
|
||||
a couple of minutes, call the Skill tool with "diagnosing-bugs" rather than trying
|
||||
fixes to see what sticks. Note anything it turns up that changes the plan.
|
||||
fixes to see what sticks. Note anything it turns up that changes the plan as an event on
|
||||
the page. When it changes the steps, amend the plan as [SITE.md](SITE.md) describes, which
|
||||
keeps the progress already made.
|
||||
4. Do not run the full verification suite after every commit (checks-at-the-end mode).
|
||||
Once every step is implemented and checked off, find and run this project's standard
|
||||
Once every step is implemented and marked done, find and run this project's standard
|
||||
verification (check `package.json` scripts for something like `ci:check`,
|
||||
`typecheck`, `lint`, `test`, or fall back to whatever the repo's README documents).
|
||||
Fix anything broken, committing fixes as their own commits, until it's clean. If you
|
||||
@@ -736,8 +655,9 @@ Entered only when the user has confirmed (per Phase 0) that the plan is approved
|
||||
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 this ticket's `resources/` and
|
||||
`plan.md`, then `AGENTS.md`, and only then the diff. Give it the exact commit range.
|
||||
(`.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,
|
||||
@@ -748,12 +668,13 @@ Entered only when the user has confirmed (per Phase 0) that the plan is approved
|
||||
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
|
||||
`ticket.md` and `plan.md` rather than the diff alone: what the ticket asked for that
|
||||
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.md` line each finding traces to.
|
||||
the plan step each finding traces to.
|
||||
|
||||
Then respond to the review, in writing:
|
||||
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
|
||||
@@ -785,7 +706,7 @@ Entered only when the user has confirmed (per Phase 0) that the plan is approved
|
||||
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.
|
||||
3. 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
|
||||
@@ -811,8 +732,8 @@ Entered only when the user has confirmed (per Phase 0) that the plan is approved
|
||||
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
|
||||
`resources/ticket.md` and `plan.md`. This is the cheapest thing that reduces
|
||||
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
|
||||
@@ -836,7 +757,7 @@ Entered only when the user has confirmed (per Phase 0) that the plan is approved
|
||||
- New ENVs: list any env vars actually introduced; "None" if none.
|
||||
- Additional Notes: a bulleted checklist of the changes you actually made, not a
|
||||
dumping ground. Between Summary and this section, every acceptance criterion from
|
||||
`plan.md` (or, for a bug ticket, the bug itself) needs to be directly addressed,
|
||||
the plan (or, for a bug ticket, the bug itself) needs to be directly addressed,
|
||||
not just gestured at. If there's genuinely unrelated work worth mentioning (e.g.
|
||||
an incidental fix along the way), it goes after everything ticket-relevant, still
|
||||
as short bullets. Five bullet points max total, ticket-relevant and incidental
|
||||
@@ -876,7 +797,8 @@ Entered only when the user has confirmed (per Phase 0) that the plan is approved
|
||||
(`customfield_10260`, "For The Engineer: Patch Notes"). Step 9 writes it.
|
||||
Scattered coverage across notes does not count as having answered a named
|
||||
requirement, and neither does burying it in the MR description.
|
||||
Save this as `<target-dir>/mr.md` (next to `plan.md`, not under `resources/`).
|
||||
Save this as `<target-dir>/mr.md` (next to `index.html`, not under `resources/`), and
|
||||
record it with `ticket-page mr <KEY>`.
|
||||
|
||||
**`mr.md` is the template plus the pasted handoff, and NOTHING ELSE.** This is a
|
||||
hard shape, not a starting point. Its only headings are the template's own numbered
|
||||
@@ -897,7 +819,8 @@ Entered only when the user has confirmed (per Phase 0) that the plan is approved
|
||||
9. Fill the Jira ticket fields directly, by issue type. Rich text fields are ADF:
|
||||
render markdown with `python3 ~/.agents/skills/review-ticket/scripts/review2adf.py
|
||||
render <file.md>` and PUT via `{"fields": {...}}` to `/rest/api/3/issue/<KEY>`.
|
||||
After every PUT, re-fetch and verify the field landed (compare extracted text,
|
||||
After every PUT, re-fetch and verify the field landed, then record it with
|
||||
`ticket-page jira <KEY> "<field name>"` (compare extracted text,
|
||||
treating empty `attrs` objects and `localId`/`colwidth`/`width` as noise). The
|
||||
field-to-type map below is verified against the project's edit screens, don't PUT
|
||||
a field to a type that doesn't carry it.
|
||||
@@ -910,7 +833,8 @@ Entered only when the user has confirmed (per Phase 0) that the plan is approved
|
||||
yourself wherever possible: run the app (`run` skill) and screenshot the real
|
||||
feature with browser automation, or capture test output for behavior with no UI.
|
||||
Save artifacts under `<target-dir>/proof/` with names that match the test-case
|
||||
rows they prove. A proof cell references its artifact by filename plus "attached"
|
||||
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"
|
||||
(Gib uploads every attachment, this skill NEVER uploads files to Jira) or names
|
||||
the passing test. When proof genuinely can't be captured here (needs prod, a real
|
||||
inbox, a flag flip), the cell says exactly what's needed and step 10 lists it for
|
||||
@@ -920,7 +844,8 @@ Entered only when the user has confirmed (per Phase 0) that the plan is approved
|
||||
**Cap the proof at five files, and aim for two or three.** Gib uploads every
|
||||
attachment by hand, so each file has a real cost and a wall of near-duplicate
|
||||
screenshots buries the two that matter. Before filling the proof column, pick the
|
||||
smallest set that actually carries the evidence and delete the rest from `proof/`.
|
||||
smallest set that actually carries the evidence, delete the rest from `proof/`, and
|
||||
drop them from the page with `ticket-page unproof`.
|
||||
|
||||
- One screenshot can prove several rows at once. A company page that shows the
|
||||
navigation, the tabs, and the absent section proves three criteria in one image,
|
||||
@@ -976,12 +901,13 @@ Entered only when the user has confirmed (per Phase 0) that the plan is approved
|
||||
ticket, Drive, or both, per the ticket's instructions). Fill `customfield_10260`
|
||||
only if the spike actually shipped code.
|
||||
|
||||
Before moving on, re-read `ticket.md` row by row: every test case and every risk
|
||||
the ticket carries now has its developer column filled in Jira. Leave none
|
||||
Before moving on, re-read the Ticket tab's test case and risk tables row by row: every
|
||||
test case and every risk the ticket carries now has its developer column filled in
|
||||
Jira. Leave none
|
||||
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), and `mr.md` is ready at
|
||||
its path. Then the manual list, which should only ever be:
|
||||
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:
|
||||
- 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
|
||||
@@ -989,8 +915,8 @@ Entered only when the user has confirmed (per Phase 0) that the plan is approved
|
||||
|
||||
## Resuming mid-implementation
|
||||
|
||||
If Phase 0 routes here because some steps in `plan.md` are already checked off: check
|
||||
`git log` on the current branch against the plan's steps to sanity-check they actually
|
||||
If Phase 0 routes here because some steps are already done on the page: check
|
||||
`git log` on the current branch against the page's step commits to sanity-check they actually
|
||||
match reality (a checked-off step should have a corresponding commit), then continue
|
||||
from the first unchecked step. If the plan and the git history disagree, stop and ask
|
||||
from the first open step. If the plan and the git history disagree, stop and ask
|
||||
the user rather than guessing which one is right.
|
||||
|
||||
Reference in New Issue
Block a user