146 lines
8.4 KiB
Markdown
146 lines
8.4 KiB
Markdown
# 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.
|