|
| 1 | +One project's `tickets/` backlog as a list of one-line rows, scannable without opening anything, with three agent-starting actions on it: work a ticket, plan a ticket, and bring the whole backlog up to date with GitHub. |
| 2 | + |
| 3 | +## User story |
| 4 | + |
| 5 | +The user wants to read a project's backlog at a glance — what each ticket is, how urgent, whether it is already planned or already being worked, how old — and to put an agent on any of it in one click. On a project with no tickets yet, they want the backlog filled from the repo's GitHub issues rather than a dead end. |
| 6 | + |
| 7 | +## Business logic — TL;DR |
| 8 | + |
| 9 | +- **A ticket is one row** - title, project (in the cross-project list), topics, claim, effort, uncertainty, priority, age, plan, and the GitHub item behind it, all on one line; the row opens the ticket's detail page. |
| 10 | +- **Start work from the row** - a play control on the row's left edge starts an unattended agent on that one ticket and nothing else, with the ticket named on the agent. |
| 11 | +- **The plan column is either a plan or an offer to write one** - a planned ticket links to its plan; an unplanned one offers to start an agent that writes it. |
| 12 | +- **Claimed rows say who holds them** - a ticket an agent has claimed shows a hammer and the holder's name, meaning an agent is planning or implementing it. |
| 13 | +- **Update from GitHub** - one action brings `tickets/` up to date with the repo's issues; on a project with no import on record it brings everything open across. It runs unattended, as the same routine does when the daemon starts it. |
| 14 | +- **Empty is not the same as filtered** - a backlog filtered down to nothing says how many tickets the filters hide and offers to clear them; only a genuinely empty `tickets/` offers the GitHub update. |
| 15 | + |
| 16 | +## Glossary |
| 17 | + |
| 18 | +- **start column** - the row's left-edge control that starts an agent working that ticket. |
| 19 | +- **plan column** - the row's control that either opens the ticket's plan or starts an agent to write it. |
| 20 | + |
| 21 | +## Business logic |
| 22 | + |
| 23 | +### A ticket is one row |
| 24 | + |
| 25 | +#### User story |
| 26 | + |
| 27 | +See `## User story`. |
| 28 | + |
| 29 | +#### Business logic |
| 30 | + |
| 31 | +Every ticket occupies a single line. The title takes whatever width the row has to spare and truncates when it runs out; clicking it opens the ticket's detail page. In the flat cross-project list the row also names its project, since there is no section heading saying it. The rest of the line, from left to right: the ticket's topics, its claim, its effort and uncertainty estimates, its priority — coloured by how urgent it is, and spelled out as "Priority: 8" — and its age, with the exact date and time on hover. Priority, age and the plan column keep fixed widths, and a ticket with no GitHub item still reserves that column's width, so the columns line up down the whole list regardless of what any one ticket carries. |
| 32 | + |
| 33 | +Where the surrounding page supports filtering, a row's topics and its claim marker are clickable: a topic filters the page to that topic, the claim marker filters to claimed tickets. Where the page has no filters, they are plain labels. |
| 34 | + |
| 35 | +### Start work from the row |
| 36 | + |
| 37 | +#### User story |
| 38 | + |
| 39 | +The user reads the backlog, sees the ticket that should be done next, and wants an agent on it immediately. |
| 40 | + |
| 41 | +#### Business logic |
| 42 | + |
| 43 | +The start column asks an agent to work `tickets/<file>` and to start no other ticket. The agent runs unattended — ending when it settles and firing its armed handoff — because one agent on one ticket is exactly the work the queue-draining routine starts, and it should run the same way. The ticket is named on the agent itself, so the agent's record says which ticket it implements. |
| 44 | + |
| 45 | +### The plan column |
| 46 | + |
| 47 | +#### User story |
| 48 | + |
| 49 | +Before committing an agent to a big ticket, the user wants a plan written for it, and afterwards wants to read that plan. |
| 50 | + |
| 51 | +#### Business logic |
| 52 | + |
| 53 | +A planned ticket's plan column links to the rendered plan, marked prominently so planned rows are scannable at a glance. An unplanned ticket's plan column instead starts an agent asked to create the ticket's plan file beside the ticket, and is drawn quietly — an action still available rather than something already there. |
| 54 | + |
| 55 | +The planning agent runs attended, unlike the work agent and the GitHub update: a plan is written for a human to read and act on, so it stays a conversation the user can land in and steer. |
| 56 | + |
| 57 | +### Claimed rows say who holds them |
| 58 | + |
| 59 | +#### User story |
| 60 | + |
| 61 | +The user needs to know a ticket is already being worked before starting a second agent on it. |
| 62 | + |
| 63 | +#### Business logic |
| 64 | + |
| 65 | +A ticket an agent has claimed shows a hammer and the holder's name inline, truncated to keep the row aligned, with the full holder and the explanation on hover: an agent is working on this ticket, planning it or implementing it. Where filtering is available, the hover also says the marker leads to all claimed tickets. |
| 66 | + |
| 67 | +#### Rationale |
| 68 | + |
| 69 | +The holder is named on the row rather than only in the tooltip: a control that only reveals itself after a second of hovering is one nobody discovers. |
| 70 | + |
| 71 | +### Update from GitHub |
| 72 | + |
| 73 | +#### User story |
| 74 | + |
| 75 | +The user's real backlog lives in the repo's GitHub issues and they want `tickets/` to reflect it — the first time, and every time since. |
| 76 | + |
| 77 | +#### Business logic |
| 78 | + |
| 79 | +A bar above the list says when `tickets/` last caught up with GitHub, or that there is no record of an import yet, with the update action beside it. The action asks for `tickets/` to be brought up to date with the issues and comments changed since the last import; with no import on record, everything open comes across instead. It runs unattended, since an update fired by a button is routine work rather than a conversation. |
| 80 | + |
| 81 | +The same instruction sits behind the same label everywhere it is offered, including the onboarding checklist, so one label always means one instruction. |
| 82 | + |
| 83 | +### Starting anything hands the user to the agent |
| 84 | + |
| 85 | +#### User story |
| 86 | + |
| 87 | +The user presses a button and wants to watch the work, not stare at a list that has not changed yet. |
| 88 | + |
| 89 | +#### Business logic |
| 90 | + |
| 91 | +Whenever any of the three actions starts an agent, the dashboard shell is told, so the user lands on the agent doing the work rather than on a panel showing stale rows until files land. Every action is blocked while another start is in flight, and a failed start leaves its reason in the panel: the update, the planning agent, or the work agent could not be started. |
| 92 | + |
| 93 | +### Empty is not the same as filtered |
| 94 | + |
| 95 | +#### User story |
| 96 | + |
| 97 | +See `## User story`. |
| 98 | + |
| 99 | +#### Business logic |
| 100 | + |
| 101 | +A panel whose tickets were all hidden by the surrounding page's filters says how many are hidden and, where the page allows it, clears the filters from right there. It never offers the GitHub update in that state. |
| 102 | + |
| 103 | +A genuinely empty backlog explains that tickets live in `tickets/` and are what the agent plans from, and offers the GitHub update as the way to fill it. Until the project's tickets have been read, the panel says it is loading. |
| 104 | + |
| 105 | +#### Rationale |
| 106 | + |
| 107 | +Offering an import to a user who has merely filtered their backlog away would ask for work that has already been done. |
| 108 | + |
| 109 | +## Before modifying/creating SPEC.md files |
| 110 | + |
| 111 | +You must always read and respect https://raw.githubusercontent.com/brillout/sdd/refs/heads/main/sdd.md |
0 commit comments