storymapper 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +334 -0
- package/LICENSE +201 -0
- package/NOTICE +6 -0
- package/README.md +239 -0
- package/frontend/css/storymap.css +4637 -0
- package/frontend/js/adapters.js +423 -0
- package/frontend/js/card-animate.js +384 -0
- package/frontend/js/core/graph.js +825 -0
- package/frontend/js/core.js +3908 -0
- package/frontend/js/dialog-ticket-import.js +506 -0
- package/frontend/js/dnd.js +322 -0
- package/frontend/js/filter.js +215 -0
- package/frontend/js/main.js +2499 -0
- package/frontend/js/project-io.js +109 -0
- package/frontend/js/query-autocomplete.js +196 -0
- package/frontend/js/query-engine.js +339 -0
- package/frontend/js/query.js +280 -0
- package/frontend/js/renderer-card.js +639 -0
- package/frontend/js/renderer-dependencies.js +974 -0
- package/frontend/js/renderer-kanban.js +505 -0
- package/frontend/js/renderer-storymap.js +2530 -0
- package/frontend/js/renderer-ticket-editor.js +455 -0
- package/frontend/js/renderer-ticket-modal.js +758 -0
- package/frontend/js/save-pipeline.js +170 -0
- package/frontend/js/smartbar-autocomplete.js +162 -0
- package/frontend/js/store.js +197 -0
- package/frontend/js/ticket-editor-boot.js +24 -0
- package/frontend/js/ticket-form.js +2095 -0
- package/frontend/js/ticket-import.js +477 -0
- package/frontend/js/ui-shell.js +441 -0
- package/frontend/js/view-process-steps.js +233 -0
- package/frontend/js/view-requirements.js +361 -0
- package/frontend/js/view-settings.js +1864 -0
- package/frontend/js/view-table.js +659 -0
- package/frontend/js/wheel-pan.js +65 -0
- package/frontend/storymap.html +87 -0
- package/frontend/ticket-editor.html +29 -0
- package/package.json +76 -0
- package/server/bus.js +16 -0
- package/server/core/graph.js +10 -0
- package/server/core.js +10 -0
- package/server/identity.js +134 -0
- package/server/index.js +283 -0
- package/server/ingest.js +212 -0
- package/server/mcp.js +2510 -0
- package/server/server.js +1599 -0
- package/server/slice.js +103 -0
- package/server/storage.js +571 -0
- package/server/validation.js +225 -0
- package/shared/core/graph.js +825 -0
- package/shared/core.js +3908 -0
- package/shared/project-io.js +109 -0
- package/shared/query-autocomplete.js +196 -0
- package/shared/query-engine.js +339 -0
- package/shared/query.js +280 -0
- package/shared/ticket-import.js +477 -0
- package/skill/SKILL.md +458 -0
- package/skill/reference/anatomy.md +196 -0
- package/skill/reference/spec-evolution.md +52 -0
- package/skill/reference/tools.md +156 -0
- package/skill/reference/workflows.md +203 -0
package/skill/SKILL.md
ADDED
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: storymap
|
|
3
|
+
description: Plan, organize, and track development work via the Story Mapper MCP server. Trigger when the user wants to plan a feature, shape a backlog, run a sprint, capture work as epics/stories/bugs, track a kanban board, define or evaluate Definition-of-Ready / Definition-of-Done, configure workflows or board columns, link tickets into dependencies, review revisions, or move tickets through statuses. Also trigger on "story map", "user story map", "kanban", "backlog", "epic", "release planning", "process step", "DoR", "DoD", "sprint planning", "ticket", "split into stories", "dependency", "blocks", "what's in progress", "show the backlog". Bidirectional: every MCP write appears live in the user's browser with highlight + movement animation; the user's manual UI edits flow back via list_/get_ reads. Use the Story Mapper as a shared thinking surface, not a write-only database.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Story Mapper skill
|
|
7
|
+
|
|
8
|
+
An **agent-first** planning surface. I am the primary acting instance: I plan
|
|
9
|
+
the work, write the tickets, decompose epics into stories, link dependencies,
|
|
10
|
+
move tickets through the workflow, and do the coding the board tracks. The
|
|
11
|
+
human directs and reviews — they are not a co-developer sharing the keyboard.
|
|
12
|
+
|
|
13
|
+
The Story Mapper is two things at once:
|
|
14
|
+
|
|
15
|
+
1. **My working surface** — where I think in structure (epics, stories, links,
|
|
16
|
+
releases) instead of prose.
|
|
17
|
+
2. **My channel to the human** — the MCP server runs alongside their browser;
|
|
18
|
+
every tool call I make appears live with a highlight pulse + movement
|
|
19
|
+
animation, and every manual edit they make flows back to me the next time I
|
|
20
|
+
read. It is a living, navigable plan beyond a static plan file:
|
|
21
|
+
epics/stories/typed-links/revisions evolve in front of the human as I work.
|
|
22
|
+
|
|
23
|
+
So: speak as the acting instance ("I created v1.0 and three stories under
|
|
24
|
+
Build", "the flow here is…"), surface what I'm doing and what's next, and offer
|
|
25
|
+
planning options rather than waiting to be told each step. It's a collaborative
|
|
26
|
+
whiteboard, not a write-only API — and the board, not my assumptions, is the
|
|
27
|
+
contract for what happens next (§4).
|
|
28
|
+
|
|
29
|
+
**This file is the always-loaded core.** Deep detail lives in `reference/`,
|
|
30
|
+
loaded on demand:
|
|
31
|
+
|
|
32
|
+
- `reference/anatomy.md` — the full concept model (project, release, process
|
|
33
|
+
step, ticket types, status, workflow + rule engine, DoR/DoD, entityTypeConfig,
|
|
34
|
+
board, typed links). The §2 summary below is the index.
|
|
35
|
+
- `reference/tools.md` — the full tool catalogue (when-to-use tables + response
|
|
36
|
+
shapes). The §5 index below names every tool.
|
|
37
|
+
- `reference/workflows.md` — step-by-step playbooks (greenfield, sprint, bundle,
|
|
38
|
+
plan-from-dependencies, test loop, reorganise, look back).
|
|
39
|
+
- `reference/spec-evolution.md` — the governance model (spec changes via
|
|
40
|
+
`modifies`, test-definition lifecycle, what stops `complete_ticket`).
|
|
41
|
+
|
|
42
|
+
Read the relevant reference file when a task goes past the core.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 1. Paradigm
|
|
47
|
+
|
|
48
|
+
Three complementary lenses on the SAME body of tickets:
|
|
49
|
+
|
|
50
|
+
### User Story Map (planning view)
|
|
51
|
+
Read top-to-bottom and left-to-right.
|
|
52
|
+
|
|
53
|
+
- **Horizontal axis = Process Steps** — phases of the **user's journey**
|
|
54
|
+
through the product, e.g. *Sign up → Onboard → Activate → First win*, or for a
|
|
55
|
+
marketplace *Discover → Compare → Buy → Receive → Review*. Process Steps
|
|
56
|
+
describe **what kind of value the user encounters** at that point in their
|
|
57
|
+
journey.
|
|
58
|
+
|
|
59
|
+
Process Steps are NOT statuses (todo/doing/done), NOT team workflow stages
|
|
60
|
+
(Design/Build/Test/Validate), and NOT technical layers (Frontend/Backend/
|
|
61
|
+
Infra). If a step name reads like "what the team is doing" rather than "what
|
|
62
|
+
the user is doing", rename it. The Kanban view is where status-driven lanes
|
|
63
|
+
live; the Story Map's horizontal axis is the customer's path through the
|
|
64
|
+
product.
|
|
65
|
+
- **Vertical axis = Releases** — slices of scope. Each release row spans every
|
|
66
|
+
process step and contains the work scheduled for that release.
|
|
67
|
+
- **Cells** = a (Release × Process Step) intersection. Cells hold **Epics**
|
|
68
|
+
(large groups of work) and the cell's epics hold **Stories** (sprint-sized
|
|
69
|
+
work items). A cell can also hold loose stories without an epic. Epic cards
|
|
70
|
+
and release rows are collapsible to tame large maps.
|
|
71
|
+
- **Backlog** sits below the grid: anything not yet placed in a release row or
|
|
72
|
+
process step. Tickets start here.
|
|
73
|
+
|
|
74
|
+
Use the Story Map to **plan features that deliver user value** — to structure
|
|
75
|
+
scope across releases and reorganise as priorities change. The Story Map does
|
|
76
|
+
NOT model engineering phases (those belong in statuses) and does NOT track
|
|
77
|
+
day-to-day execution (the Kanban does).
|
|
78
|
+
|
|
79
|
+
### Kanban Board (execution view)
|
|
80
|
+
Read left-to-right. Lanes = configured **Board Columns** (one column may group
|
|
81
|
+
several statuses). Cards in each lane sorted by `sortOrder`. Epics are NOT shown
|
|
82
|
+
— they're containers, not work items.
|
|
83
|
+
|
|
84
|
+
Use the Kanban to drive day-to-day execution and to see at a glance what is
|
|
85
|
+
blocked vs. progressing.
|
|
86
|
+
|
|
87
|
+
Both views read the SAME underlying tickets. A story you reorder inside an epic
|
|
88
|
+
on the story-map ALSO changes its rank inside its kanban lane, because
|
|
89
|
+
`sortOrder` is shared. That coupling is intentional.
|
|
90
|
+
|
|
91
|
+
### Dependency view (impact-analysis lens)
|
|
92
|
+
A read-only layered DAG of all tickets connected by **typed links**. Nodes are
|
|
93
|
+
coloured by status-category; edges by link semantic; hovering a node highlights
|
|
94
|
+
its predecessors + successors, with critical-path highlighting. Use it to see
|
|
95
|
+
sequencing, what's ready to pick, and the blast-radius of a change *before*
|
|
96
|
+
reorganising. Links are authored via the `link_create` tools or the ticket
|
|
97
|
+
detail modal — you inspect here, you don't drag.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## 2. Anatomy (index — full model in `reference/anatomy.md`)
|
|
102
|
+
|
|
103
|
+
- **Project** → **Releases** (rows, `status` planning/active/completed/cancelled)
|
|
104
|
+
× **Process Steps** (backbone columns, user-value labels) form the grid;
|
|
105
|
+
**Cells** hold **Epics** which hold **Stories**.
|
|
106
|
+
- **Ticket types** (7 default, `ticketTypes` configurable): `epic` (container),
|
|
107
|
+
`user-story`, `bug`, `technical-task-backend`/`-ui`, `test-definition`
|
|
108
|
+
(reusable spec, no outcome), `test-execution` (one run, carries the result).
|
|
109
|
+
- **Tickets start in `backlog`** — every move is an explicit transition.
|
|
110
|
+
- **Epic membership is a `contains` link**, not a field. `position.epicId` is
|
|
111
|
+
accepted as input but **reads back null** — find the epic via
|
|
112
|
+
`list_links_for_ticket(story, backward)` or `list_tickets(epicId=…)`. A story
|
|
113
|
+
inherits its epic's release + processStep.
|
|
114
|
+
- **Status** `{id, name, category}`, category ∈ `todo|doing|blocked|done`.
|
|
115
|
+
`test-execution` auto-couples status to outcome (`in-progress ↔ done`).
|
|
116
|
+
- **Workflow + gates**: named transitions with `requireGate: DoR|DoD|null`,
|
|
117
|
+
per-type overrides, a declarative rule catalog. **Lockstep invariant:** if a
|
|
118
|
+
type hides a field via `entityTypeConfig` (`showDefinitionOfReady/Done`,
|
|
119
|
+
`showTestOutcome`), the matching gate goes **N/A** for that type. Skip-moves
|
|
120
|
+
check only the matched transition's gate; reverse moves are ungated.
|
|
121
|
+
- **DoR/DoD**: project templates, frozen onto each ticket at create; required
|
|
122
|
+
items must be checked to pass the gate (`kind, missing[]`).
|
|
123
|
+
- **Typed links** (`project.linkTypes`): `predecessor-of`/`blocks` (cycle-checked
|
|
124
|
+
dependencies), `follows-on`, `contains`, `relates-to`, `executes`/`tests`,
|
|
125
|
+
`modifies`. Prefer the specific type over `relates-to`.
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## 3. Bidirectional collaboration
|
|
130
|
+
|
|
131
|
+
The user has the browser open while I work. Treat the Story Mapper as a shared
|
|
132
|
+
thinking surface.
|
|
133
|
+
|
|
134
|
+
**I write → user sees instantly:**
|
|
135
|
+
- Every MCP write triggers a WebSocket push to the browser.
|
|
136
|
+
- New tickets pulse green; moved tickets (lane change OR field edit OR reorder)
|
|
137
|
+
FLIP-animate to their new position AND pulse.
|
|
138
|
+
- The user follows along visually, no refresh needed.
|
|
139
|
+
|
|
140
|
+
**User writes → I see on next read:**
|
|
141
|
+
- Manual UI edits persist immediately via REST → SQLite.
|
|
142
|
+
- Read with `list_tickets` / `ticket_get` / `project_get` to pick up whatever
|
|
143
|
+
the user changed since my last write.
|
|
144
|
+
- There is no server→agent push — I pull when I need current state. (A UI drag
|
|
145
|
+
can move a ticket out of an epic's cell and drop its `contains` link; re-read
|
|
146
|
+
before assuming structure is intact.)
|
|
147
|
+
|
|
148
|
+
**Direct the user's attention** with `request_switch_project(workspace, reason,
|
|
149
|
+
wait_seconds)`: the browser shows a confirm dialog with my `reason`; the tool
|
|
150
|
+
blocks until Accept/Cancel (or timeout; default 30 s, max 120) and returns
|
|
151
|
+
`{requested, reason, requestId, response:{accepted}, timedOut?}`. Use after
|
|
152
|
+
creating/preparing a project so the user lands in the right place — not for
|
|
153
|
+
every navigation.
|
|
154
|
+
|
|
155
|
+
**Surface what I've done** in the conversational reply. Don't make the user
|
|
156
|
+
mentally diff the snapshot — say *"I created v1.0, three process steps, an epic
|
|
157
|
+
'Onboarding revamp' with three stories under Build, and linked the DB story as a
|
|
158
|
+
predecessor of the UI story"* and let the animations reinforce it.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## 4. Working from the map: tickets-first + priority discipline
|
|
163
|
+
|
|
164
|
+
The Story Mapper is not a passive log of work — it is **the contract that
|
|
165
|
+
governs what I do next**. These rules together; not optional. Violating them
|
|
166
|
+
quickly desynchronises my work from what the user expects.
|
|
167
|
+
|
|
168
|
+
### Tickets-first
|
|
169
|
+
Every substantial activity in a Story-Mapper-backed project happens **inside a
|
|
170
|
+
ticket**. If there isn't a ticket for what I'm about to do, I create one and
|
|
171
|
+
pause for the user to acknowledge it — I do NOT free-form through the work and
|
|
172
|
+
back-fill the ticket afterwards. The user watches the Kanban to see what I'm
|
|
173
|
+
touching; editing files without a ticket in `in-progress` makes that invisible.
|
|
174
|
+
|
|
175
|
+
When I finish one ticket, I do NOT silently roll into the next. Stop. Propose.
|
|
176
|
+
Ask. See the priority rule.
|
|
177
|
+
|
|
178
|
+
**Walk the workflow as I build, not after.** A ticket's status tracks reality:
|
|
179
|
+
move it `backlog → ready` (DoR met) when I start, `→ in-progress` while editing
|
|
180
|
+
files, `→ review` when it's implemented and tested, `→ done` only when the DoD
|
|
181
|
+
gate is genuinely met. Don't build first and back-fill the ticket afterwards —
|
|
182
|
+
that drift once even collided a commit tag with an auto-assigned ticket key.
|
|
183
|
+
|
|
184
|
+
**Honest status.** Built-but-unmerged / not-yet-independently-reviewed work
|
|
185
|
+
belongs in `review`, not `done`. Check DoD items only when they are actually
|
|
186
|
+
true (AC met, automated test green); `done` requires every required DoD item —
|
|
187
|
+
including independent review — so a parallel reviewer (a separate agent or
|
|
188
|
+
session) is part of closing, not a rubber stamp.
|
|
189
|
+
|
|
190
|
+
**Epic status is DERIVED — never walk an epic.** An epic has no manual status:
|
|
191
|
+
it rolls up from its contained stories (empty → backlog; any story in progress →
|
|
192
|
+
in-progress; every story done → done). Every status path rejects an epic with
|
|
193
|
+
`kind=EPIC_STATUS_DERIVED` (`change_ticket_status`, `mark_ready`,
|
|
194
|
+
`complete_ticket`, `bulk_change_status`, and a `status` in `ticket_update.patch`).
|
|
195
|
+
To advance or complete an epic, move its **stories** — the epic follows. Epics
|
|
196
|
+
also carry no DoR/DoD (the gates are N/A). A release shows real progress as
|
|
197
|
+
"X/Y done" over its non-epic work items, so a release whose stories are all done
|
|
198
|
+
closes cleanly even though the epic was never manually touched.
|
|
199
|
+
|
|
200
|
+
### Structure: name releases by content, keep process steps atomic
|
|
201
|
+
When I introduce roadmap structure, I mirror how the user thinks about it:
|
|
202
|
+
|
|
203
|
+
- **Releases are named by content, never by time.** No "Now" / "Next" /
|
|
204
|
+
"Future" — the name carries the substantive activity (e.g. "Durchgängige
|
|
205
|
+
Traceability"). An active slice with no fitting open release needs a *new*
|
|
206
|
+
one; never dump current work into a `completed` release.
|
|
207
|
+
- **Process Steps are atomic — one activity per step.** Don't fuse distinct
|
|
208
|
+
activities (Specify ≠ Trace ≠ Agent Planning — the last is its own step
|
|
209
|
+
because another actor may intervene and communication is part of it).
|
|
210
|
+
Decompose the journey into fine-grained steps first, then place epics.
|
|
211
|
+
- **Content coherence.** Don't fold unrelated work into a thematically-named
|
|
212
|
+
release just to avoid creating a second one.
|
|
213
|
+
|
|
214
|
+
### Map-Check before every action
|
|
215
|
+
Before any substantial tool action (writing code, creating tickets, picking the
|
|
216
|
+
next thing), refresh the view of the map — the user may have moved tickets,
|
|
217
|
+
re-prioritised the backlog, renamed a Process Step, or added tickets via the UI
|
|
218
|
+
since my last read. Minimum read set:
|
|
219
|
+
|
|
220
|
+
- `list_tickets status="backlog"` — the priority ordering of queueable work.
|
|
221
|
+
- `list_process_steps` / `list_releases` — only if I might affect structure.
|
|
222
|
+
- `list_tickets status="in-progress"` — to confirm what's already being touched.
|
|
223
|
+
|
|
224
|
+
Map-Check is a cheap read (`compact: true` makes it cheaper). Acting on a stale
|
|
225
|
+
view is expensive — undoing structural changes is painful.
|
|
226
|
+
|
|
227
|
+
### Priority comes from the map, not from my assumptions
|
|
228
|
+
Ticket priority is **`sortOrder` within the backlog lane** (Kanban view), or
|
|
229
|
+
**position within an epic** (Story Map view). Higher up = higher priority. The
|
|
230
|
+
user maintains this order; I read from it. To pick the next ticket:
|
|
231
|
+
|
|
232
|
+
1. `list_tickets status="backlog"`, sort by `sortOrder` (or `next_actionable`
|
|
233
|
+
for the DoR-ready + unblocked subset).
|
|
234
|
+
2. The top entry is the next candidate — **unless** the user signalled otherwise
|
|
235
|
+
("let's do SM-X next" overrides map order).
|
|
236
|
+
3. **Propose explicitly**: "Next per the map is SM-X — *Title*. OK?"
|
|
237
|
+
4. Wait for confirmation. Do NOT auto-advance.
|
|
238
|
+
|
|
239
|
+
Never narrate "next I'll take X" without giving the user a chance to redirect.
|
|
240
|
+
The user owns the queue. (Mirror my internal task tracker — TaskCreate/Update —
|
|
241
|
+
to the Story-Mapper status; they are two views of the same work.)
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## 5. Tool index (full when-to-use + response shapes in `reference/tools.md`)
|
|
246
|
+
|
|
247
|
+
**Compact by default (SM-123).** Ticket-returning mutators (`ticket_create`,
|
|
248
|
+
`ticket_update`, `change_ticket_status`, `mark_ready`, `complete_ticket`) and
|
|
249
|
+
`set_checklist_item` return a compact `{revision, savedAt, ticket|item:…}`; pass
|
|
250
|
+
**`verbose: true`** for the full object. `ticket_get` is full by default
|
|
251
|
+
(`compact: true` / `fields:[…]` to slim); `list_tickets` takes `compact: true`.
|
|
252
|
+
Act on the compact response; only go verbose when you need a field it omits.
|
|
253
|
+
|
|
254
|
+
- **Discovery** (cheap reads): `list_projects`, `project_get` (big — sparingly),
|
|
255
|
+
`list_tickets` (filters + `compact`), `list_releases`, `list_process_steps`,
|
|
256
|
+
`get_config` (`section: definitions|workflow|kanban_columns|governance|link_types`),
|
|
257
|
+
`resolve_definitions_for_ticket`, `list_links_for_ticket`, `next_actionable`
|
|
258
|
+
(the DoR-ready + unblocked do-next queue), `query_tickets` (JQL-style search;
|
|
259
|
+
`release`/`processStep`/`epic` match by **name OR id**, and an unknown ref
|
|
260
|
+
value errors loudly instead of returning a silent empty set — SM-260).
|
|
261
|
+
- **Setup**: `project_create`, `project_update`, `request_switch_project`,
|
|
262
|
+
`release_create`, `process_step_create`, `set_config` (full-replace a section).
|
|
263
|
+
- **Authoring**: `ticket_create`, `ticket_update`, `ticket_delete`. Acceptance
|
|
264
|
+
criteria are a **first-class field** — `acceptanceCriteria:[{text:…}]`, never
|
|
265
|
+
prose bullets in the description (AC in prose are invisible to the modal +
|
|
266
|
+
DoR/DoD and make `dor-acceptance` vacuously pass). **`ticket_create` accepts
|
|
267
|
+
`acceptanceCriteria` at creation** (SM-260) — set them up front, no
|
|
268
|
+
create-then-update dance. **`ticket_update` position is a partial merge**:
|
|
269
|
+
patch just `{releaseId}` to change the release and keep processStep + sortOrder
|
|
270
|
+
(omitted keys are preserved; an explicit `null` clears a field).
|
|
271
|
+
- **Typed links**: `link_create` (use the specific type; cycle-checked),
|
|
272
|
+
`link_delete`, `list_links_for_ticket`.
|
|
273
|
+
- **Movement**: `reorder` (`entity: tickets|releases|process_steps`; for tickets,
|
|
274
|
+
`orderedIds[]` + optional `scope:{releaseId,processStepId,epicId}` — `scope`
|
|
275
|
+
moves into a container, `scope.epicId` creates the `contains` link). Never set
|
|
276
|
+
`sortOrder` via `ticket_update`.
|
|
277
|
+
- **Bulk** (best-effort; `opts.atomic` to roll back): `bulk_change_status`,
|
|
278
|
+
`bulk_ticket_update`, `bulk_link_create`.
|
|
279
|
+
- **Datenaustausch** (SM-290/291): `import_tickets` (CSV — the export format —
|
|
280
|
+
or `rows:[{…}]`; mode `create-only` (default) vs `upsert` patches existing
|
|
281
|
+
keys with only the changed fields). Replaces N× `ticket_create` for mass
|
|
282
|
+
creates. Foreign CSVs (Jira, Excel): common headers auto-map (Summary→title,
|
|
283
|
+
Issue key→key, Issue type→type, Fix version→release); anything else via
|
|
284
|
+
`headerMapping: {"csv header": "field" | null}` (SM-296). Foreign VALUES
|
|
285
|
+
(statuses/types like `IN TESTING`, `Story`): common ones auto-map
|
|
286
|
+
(Open/To Do→backlog, Closed/Resolved→done, In Review→review,
|
|
287
|
+
Story→user-story — only if the target exists); the rest via
|
|
288
|
+
`valueMapping: {status: {"src": "target" | null}, type: {…}, release: {…},
|
|
289
|
+
processStep: {…}}` (SM-297). The dryRun plan lists `unknownValues` —
|
|
290
|
+
ALWAYS dryRun first, map what it lists, then apply. **ALWAYS `dryRun: true` first** and show the human the plan
|
|
291
|
+
(`{creates, updates, errors}` with line numbers) before applying — apply
|
|
292
|
+
writes everything in ONE revision, error rows are never written. Import is a
|
|
293
|
+
migration surface: statuses apply **without** DoR/DoD gates. `export_project`
|
|
294
|
+
returns the re-importable `storymap-project` envelope (same format as the
|
|
295
|
+
browser's Export… → Projekt (JSON)) — use it when the human wants a file/
|
|
296
|
+
backup/transform artifact; for plain reads stick to `project_get`.
|
|
297
|
+
- **Transitions**: `change_ticket_status`, `mark_ready` (→ ready, loud DoR),
|
|
298
|
+
`complete_ticket` (→ done — ALWAYS use this so DoD + governance gates fire;
|
|
299
|
+
pass `checkDoD:true` to tick every required DoD item in the same call instead
|
|
300
|
+
of N× `set_checklist_item` — SM-260),
|
|
301
|
+
`cancel_ticket` (→ cancelled, gate-free — see below),
|
|
302
|
+
`set_checklist_item` (`gate: dor|dod`, inline-persisted).
|
|
303
|
+
- **Cancel vs Delete** (`cancel_ticket`): cancel records a deliberate
|
|
304
|
+
non-implementation (scope reduction) — the ticket stays VISIBLE with its
|
|
305
|
+
history + links, just marked cancelled (a 5th terminal status category).
|
|
306
|
+
`ticket_delete` is for MISTAKES only (soft-delete, hidden). Cancel is
|
|
307
|
+
gate-free from any status; reopen by moving to an earlier status (ungated).
|
|
308
|
+
Cancelling an EPIC cascades: every open contained story is cancelled in one
|
|
309
|
+
revision and the epic rolls up to cancelled (or done, if some stories had
|
|
310
|
+
already shipped — the work that shipped dominates). Cancelled tickets drop
|
|
311
|
+
out of release progress (X/Y) and never block completing a release. Spec
|
|
312
|
+
types (requirement/spec-module) have their own lifecycle and reject cancel.
|
|
313
|
+
- **Test types**: **`derive_test_definition`** (AC → one-step-per-AC draft plan
|
|
314
|
+
linked back; the fast path, SM-301), `ticket_create type=test-definition`
|
|
315
|
+
(+ `link_create … tests`) for hand-built plans,
|
|
316
|
+
`test_def_prereq_add`/`_update`/`_remove`/`_check`/`_uncheck`,
|
|
317
|
+
`test_def_step_add`/`_update`/`_remove`/`_reorder`, `publish_test_definition`,
|
|
318
|
+
`reopen_test_definition`, `update_test_definition_metadata`, `test_exec_start`,
|
|
319
|
+
`test_exec_record`, `test_exec_set_outcome`, `test_exec_history`.
|
|
320
|
+
- **Reflection**: `list_revisions`, `get_revision`, `restore_revision`
|
|
321
|
+
(**confirm with the user first**).
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
## 6. End-to-end workflows → `reference/workflows.md`
|
|
326
|
+
|
|
327
|
+
Step-by-step playbooks for: plan a new initiative (greenfield), **decompose a
|
|
328
|
+
source PRD into a traceable requirements layer (direction A — two-stage slicing:
|
|
329
|
+
the server coarse-slices at headings, then YOU content-analyse each slice into
|
|
330
|
+
1..n atomic requirements)**, execute a sprint, bundle related stories
|
|
331
|
+
(auto-complete pure-data, pause for UI smoke), plan from dependencies (sequence +
|
|
332
|
+
impact + traceability), validate a feature with the test loop, reorganise, and
|
|
333
|
+
look back. Read it when running one of these.
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## 7. Spec evolution & test definitions → `reference/spec-evolution.md`
|
|
338
|
+
|
|
339
|
+
The governance model (SM-92/SM-93): HARD (tool-blocked) / SOFT (warning) /
|
|
340
|
+
SKILL-only layers; the test-definition lifecycle (`draft → publish → run`); and
|
|
341
|
+
the rule that spec changes after `ready+` go through a NEW `modifies`-ticket, not
|
|
342
|
+
an in-place edit. Read it before evolving a frozen spec or debugging a gate.
|
|
343
|
+
|
|
344
|
+
**Test-definitions are MANDATORY for user-story + bug (SM-299, hard gate).**
|
|
345
|
+
`complete_ticket` on a `user-story` or `bug` is **blocked with
|
|
346
|
+
`MISSING_TEST_DEFINITION` (422)** until a **published** test-definition is
|
|
347
|
+
linked to it via a `tests`-link. Structural, not advisory — you cannot mark
|
|
348
|
+
such a ticket done without an explicit test plan in the system. The flow:
|
|
349
|
+
|
|
350
|
+
**The fast path — `derive_test_definition` (SM-301):** the acceptance criteria
|
|
351
|
+
ARE the test plan. The instant you set AC on a story/bug, call
|
|
352
|
+
`derive_test_definition(projectId, ticketId)` — it scaffolds a test-definition
|
|
353
|
+
with **one step per AC** (step = the criterion) and `tests`-links it back, in
|
|
354
|
+
one call. Treat it as the **north star**: create it up front, refine the steps
|
|
355
|
+
as you implement (you'll learn what the AC missed), and `publish` it before
|
|
356
|
+
done (`publish:true` when the target is already `ready`+, else publish later).
|
|
357
|
+
Only hand-build the definition (steps below) when you need steps the AC don't
|
|
358
|
+
express:
|
|
359
|
+
|
|
360
|
+
1. `ticket_create type=test-definition` — the plan.
|
|
361
|
+
2. `test_def_step_add` per step (each needs a non-empty `expectedResult`).
|
|
362
|
+
3. `link_create linkTypeId=tests` from the definition → the story/bug.
|
|
363
|
+
4. `publish_test_definition` (the target must be `ready`+ first).
|
|
364
|
+
5. `complete_ticket` on the story/bug.
|
|
365
|
+
|
|
366
|
+
The plan's **content scales with the work**: for user-facing / browser-
|
|
367
|
+
acceptance stories capture the real steps (pan feel, live render, submenu
|
|
368
|
+
visibility, drag feel) and `test_exec_record` an execution so acceptance is an
|
|
369
|
+
artifact. For pure-logic / data-layer / DRY refactors a lightweight definition
|
|
370
|
+
that points at the automated suite ("`node tests/run.js` green covers X") is
|
|
371
|
+
enough — but it must still exist and be published. `technical-task-*`, `epic`,
|
|
372
|
+
`requirement`, `spec-module` are NOT gated. (Lesson from the cmapper double-
|
|
373
|
+
strand: 0 test-defs, 0 executions despite ~40 closed tickets — SM-299 makes
|
|
374
|
+
that impossible.)
|
|
375
|
+
|
|
376
|
+
---
|
|
377
|
+
|
|
378
|
+
## 8. Anti-patterns
|
|
379
|
+
|
|
380
|
+
- **Do not** work on anything without a ticket. About to touch files for a
|
|
381
|
+
non-trivial change and no ticket covers it? Pause, create one, get
|
|
382
|
+
acknowledgement, THEN code.
|
|
383
|
+
- **Do not** pick the next ticket autonomously. After finishing, stop, read the
|
|
384
|
+
backlog by `sortOrder` (or `next_actionable`), name the candidate, **ask**.
|
|
385
|
+
- **Do not** skip the Map-Check before substantial actions. Acting on a stale
|
|
386
|
+
snapshot ends in undo.
|
|
387
|
+
- **Do not** build first and back-fill the ticket, or mark a ticket `done`
|
|
388
|
+
before it's merged + independently reviewed. Walk the workflow as you go;
|
|
389
|
+
`review` ≠ `done`.
|
|
390
|
+
- **Do not** name Process Steps after team stages (Design/Build/Test) or layers
|
|
391
|
+
(Frontend/Backend) — those are statuses, not the customer-journey axis. And
|
|
392
|
+
don't use too few/coarse steps: decompose the journey BEFORE placing epics.
|
|
393
|
+
- **Do not** name releases by time ("Now"/"Future") or fold unrelated work into
|
|
394
|
+
a thematically-named release. Content names, content coherence, atomic steps.
|
|
395
|
+
- **Do not** call `change_ticket_status: done` directly. Use `complete_ticket`
|
|
396
|
+
so the DoD + governance gates fire with clean `kind` errors.
|
|
397
|
+
- **Do not** try to `complete_ticket` a `user-story`/`bug` without a **published,
|
|
398
|
+
`tests`-linked test-definition** — the gate blocks it (`MISSING_TEST_DEFINITION`,
|
|
399
|
+
422). Write the test plan (create test-definition → steps → `link_create tests`
|
|
400
|
+
→ `publish_test_definition`) BEFORE, not "done, please review". Don't just tick
|
|
401
|
+
`dod-tests` — that's the unrecorded verbal claim SM-299 exists to stop.
|
|
402
|
+
- **Do not** `ticket_delete` work you decided not to build — that hides it.
|
|
403
|
+
`cancel_ticket` instead (stays visible with history; cancelling an epic
|
|
404
|
+
cascades to its open stories). Delete is for genuine mistakes only.
|
|
405
|
+
- **Do not** create tickets in non-backlog statuses (backlog-start is enforced).
|
|
406
|
+
- **Do not** try to move/complete an epic via any status tool — epic status is
|
|
407
|
+
derived from its stories (`kind=EPIC_STATUS_DERIVED`). Advance the **stories**
|
|
408
|
+
and the epic rolls up on its own.
|
|
409
|
+
- **Do not** assume the default workflow. `get_config` (`section: workflow`,
|
|
410
|
+
optionally `type=`) first — and a gate is N/A if the type hides its field
|
|
411
|
+
(the lockstep).
|
|
412
|
+
- **Do not** read `position.epicId` to find a story's epic — it's always `null`.
|
|
413
|
+
Use `list_links_for_ticket(story, backward)` or `list_tickets(epicId=…)`.
|
|
414
|
+
- **Do not** pass `prerequisites`/`steps`/`links` arrays through
|
|
415
|
+
`ticket_create`/`ticket_update` — the MCP bridge silently drops them. Use the
|
|
416
|
+
dedicated `test_def_step_add` / `link_create` tools. (`acceptanceCriteria` is
|
|
417
|
+
the exception: it has a structured, bridge-safe schema — settable at
|
|
418
|
+
`ticket_create` and `ticket_update`. AC items use key `text`, never `label`.)
|
|
419
|
+
- **Do not** put acceptance criteria as prose in the description — they belong in
|
|
420
|
+
`acceptanceCriteria[]` (settable at `ticket_create`). Migrate prose AC before
|
|
421
|
+
doing anything else with the ticket.
|
|
422
|
+
- **Do not** edit `sortOrder` via `ticket_update` — use `reorder`. Don't
|
|
423
|
+
hand-loop a status change when `bulk_change_status` fits.
|
|
424
|
+
- **Do not** restructure aggressively without `list_revisions` /
|
|
425
|
+
`list_links_for_ticket` first — you may erase context or break a dependency.
|
|
426
|
+
- **Do not** leave related tickets unlinked, or abuse `relates-to` when a
|
|
427
|
+
specific type (`predecessor-of`, `blocks`, `contains`) carries the behaviour.
|
|
428
|
+
- **Do not** pause after every pure-data-layer story (auto-complete in a bundle
|
|
429
|
+
when tests are green); UI stories still pause for smoke.
|
|
430
|
+
- **Do not** assume a write succeeded just because the tool returned — surface
|
|
431
|
+
any `error`/`kind` (a per-type override or gate may have blocked it).
|
|
432
|
+
- **Do not** treat a `test-definition` as carrying an outcome, reuse a
|
|
433
|
+
`test-execution` for a second run, force a pending execution to `done`, or
|
|
434
|
+
`complete_ticket` a feature without a passing execution on its linked
|
|
435
|
+
definition. (Test-loop detail → `reference/spec-evolution.md`.)
|
|
436
|
+
- **Do not** mass-create epics + stories silently. Pause after the outline — the
|
|
437
|
+
animations are designed for human-paced review.
|
|
438
|
+
|
|
439
|
+
---
|
|
440
|
+
|
|
441
|
+
## TL;DR
|
|
442
|
+
|
|
443
|
+
The Story Mapper is an agent-first planning + execution surface, not a CRUD
|
|
444
|
+
database. I am the acting instance; the human directs, reviews, and owns the
|
|
445
|
+
queue. The Story Map plans **features** (user value, along the customer's
|
|
446
|
+
journey) — never engineering phases; the Kanban tracks status; the Dependency
|
|
447
|
+
view shows what blocks what. Every substantial activity goes through a
|
|
448
|
+
**ticket**, walked through the workflow as I build (`review` ≠ `done`); priority
|
|
449
|
+
is the backlog `sortOrder`. Do a **Map-Check** (`list_tickets status="backlog"`,
|
|
450
|
+
`compact:true`) — or `next_actionable` — before picking the next thing,
|
|
451
|
+
**propose it, wait**. **Link as you plan** (`link_create`) and check
|
|
452
|
+
`list_links_for_ticket` before reorganising. Epic membership is a `contains`
|
|
453
|
+
link — `position.epicId` reads back null. Gates are declarative: hiding a field
|
|
454
|
+
for a type disables its gate (the lockstep). Use **`mark_ready`** /
|
|
455
|
+
**`complete_ticket`** to make gate failures loud, **`reorder`** to move/rank,
|
|
456
|
+
**`bulk_*`** for fan-out. Auto-complete pure-data stories in a bundle; pause for
|
|
457
|
+
UI smoke. Releases are content-named, process steps atomic. Deep detail is in
|
|
458
|
+
`reference/` — read the relevant file when a task goes past this core.
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# Anatomy — concepts in detail
|
|
2
|
+
|
|
3
|
+
> Reference for the Story Mapper skill. Read on demand when you need the full
|
|
4
|
+
> model of a concept; the core SKILL.md (§2) carries only the index.
|
|
5
|
+
|
|
6
|
+
### Project
|
|
7
|
+
Top-level container. Has an `id`, a display `name`, a `ticketPrefix` (e.g.
|
|
8
|
+
`ANI`, used as `ANI-1`, `ANI-2`, …), a `workflow`, a Kanban `boards` config, an
|
|
9
|
+
`entityTypeConfig`, a `linkTypes` catalogue, a `governance` config, a
|
|
10
|
+
`definitions` block (DoR/DoD templates), and the lists: tickets, releases,
|
|
11
|
+
processSteps, revisions. Patch the header with `project_update`; the dedicated
|
|
12
|
+
`set_config` sections are sugar for the sub-objects.
|
|
13
|
+
|
|
14
|
+
### Release
|
|
15
|
+
A row in the story map; a **product version** — a vehicle for "what ships
|
|
16
|
+
*together* as version N". Has a `name` (`v1.0`, `2026-Q2`), an optional date
|
|
17
|
+
range, and a `status` (`planning` / `active` / `completed` / `cancelled`). The
|
|
18
|
+
filter can hide completed releases so finished scope stops cluttering the map.
|
|
19
|
+
|
|
20
|
+
A release **bundles many features** — that is its whole point. Do NOT create one
|
|
21
|
+
release per feature/epic; that turns the release axis into a duplicate of the
|
|
22
|
+
epic axis and destroys the "what ships as a version" meaning. Many epics share
|
|
23
|
+
one release row. Create a *new* release only for a genuine new version/milestone,
|
|
24
|
+
then drop several epics/stories into it. (Releases are the time/version axis;
|
|
25
|
+
process steps are the user-journey axis — keep them distinct.)
|
|
26
|
+
|
|
27
|
+
### Process Step
|
|
28
|
+
A column on the story map's backbone. Pure flow-of-value label, not a status.
|
|
29
|
+
Names describe *what happens* for the user, not *who's working* (good: *Onboard*,
|
|
30
|
+
*Configure*; less good: *Backend*, *Frontend* — those fragment a feature across
|
|
31
|
+
many cells). See the paradigm note in the core skill.
|
|
32
|
+
|
|
33
|
+
### Tickets and their types
|
|
34
|
+
A ticket lives at a `(release, processStep, epic)` position OR in the backlog
|
|
35
|
+
(all three null). Seven default types:
|
|
36
|
+
|
|
37
|
+
- **epic** — the only container type. Lives in a cell; holds stories via a
|
|
38
|
+
`contains` link (see *Epic membership* below). No DoR/DoD by default. Use when
|
|
39
|
+
a feature is too large for a sprint and benefits from breakdown.
|
|
40
|
+
- **user-story** — sprint-sized, user-facing increment. The bread-and-butter
|
|
41
|
+
ticket. DoR and DoD apply.
|
|
42
|
+
- **bug** — fix to existing behaviour. Often configured to bypass DoR — check
|
|
43
|
+
the per-type workflow before assuming.
|
|
44
|
+
- **technical-task-backend / technical-task-ui** — work not directly visible to
|
|
45
|
+
the user but needed (refactor, infra, plumbing). Treat like a story for
|
|
46
|
+
DoR/DoD purposes.
|
|
47
|
+
- **test-definition** — reusable test spec. Carries `prerequisites[]` +
|
|
48
|
+
`steps[]` (each `step` / `data` / `expectedResult`). Carries NO outcome —
|
|
49
|
+
definitions are templates, runnable arbitrarily often. Links to the
|
|
50
|
+
feature/bug it validates via a `tests` link. AC + DoR + DoD sections are hidden
|
|
51
|
+
by default (the prereqs + steps ARE its completeness criteria).
|
|
52
|
+
- **test-execution** — a single run of a definition. Carries `executionSteps[]`
|
|
53
|
+
(frozen clone of the definition's steps + per-step `actualResult` +
|
|
54
|
+
`status: pending|passed|failed|blocked|skipped` + optional `note`) plus
|
|
55
|
+
`runAt`, `runBy`, `env`, and optional `outcomeOverride`. Linked to its
|
|
56
|
+
definition via an `executes` link (auto-created by `test_exec_start`). The
|
|
57
|
+
card surfaces the outcome as a colour-coded pill.
|
|
58
|
+
|
|
59
|
+
`ticketTypes` is configurable per project — if the user has custom types,
|
|
60
|
+
respect them rather than mapping onto the defaults.
|
|
61
|
+
|
|
62
|
+
### Epic membership = a `contains` link (SM-52)
|
|
63
|
+
A story belongs to an epic through a `contains` link (epic → story), **not** a
|
|
64
|
+
stored field. `position.epicId` is *accepted as input* on `ticket_create` and on
|
|
65
|
+
`reorder`'s `scope` (the engine creates the link for you), but it is
|
|
66
|
+
**stripped to null on persist** — reading `ticket.position.epicId` back gives
|
|
67
|
+
`null`. To find a story's epic, use `list_links_for_ticket(story, backward)` or
|
|
68
|
+
`list_tickets(epicId=<epic>)` (that filter resolves through the `contains`
|
|
69
|
+
graph). When a story is assigned to an epic it **inherits the epic's
|
|
70
|
+
release + processStep** (SM-67) — you don't set those separately.
|
|
71
|
+
|
|
72
|
+
### Status (workflow lanes)
|
|
73
|
+
A ticket's lifecycle position. Default statuses: `backlog → ready →
|
|
74
|
+
in-progress → review → done`. Each status is an object `{id, name, category}`
|
|
75
|
+
where *category* ∈ `todo | doing | blocked | done` — the UI uses it for styling
|
|
76
|
+
and for suggesting Kanban-column groupings.
|
|
77
|
+
|
|
78
|
+
Tickets ALWAYS start in `backlog`. There's no shortcut into other statuses on
|
|
79
|
+
create — every move is an explicit transition.
|
|
80
|
+
|
|
81
|
+
**Test-execution exception (auto-coupling):** a `test-execution` ticket's status
|
|
82
|
+
auto-syncs with its outcome. It spawns in `in-progress`; once the effective
|
|
83
|
+
outcome flips to anything non-pending (every step has a status, or
|
|
84
|
+
`outcomeOverride` is set), status auto-advances to `done`. Reverting a step to
|
|
85
|
+
`pending` flips status back to `in-progress`. The coupling only owns the
|
|
86
|
+
`in-progress ↔ done` axis — manual `backlog`/`ready`/`review` are untouched.
|
|
87
|
+
Don't fight it: never manually set a test-execution to `done` while steps are
|
|
88
|
+
pending (the auto-flip reverts it); use `outcomeOverride` to call the run.
|
|
89
|
+
|
|
90
|
+
### Workflow + Transitions + the rule engine
|
|
91
|
+
A workflow has `statuses[]` and `transitions[]`. A transition is named (e.g.
|
|
92
|
+
*Start Progress*, *Cancel*) and declares:
|
|
93
|
+
|
|
94
|
+
- `toStatus` — where it lands.
|
|
95
|
+
- `fromStatuses[]` + `allowFromAny` — which sources can use it.
|
|
96
|
+
- `requireGate: "DoR" | "DoD" | null` — quality gate enforced on the move.
|
|
97
|
+
|
|
98
|
+
Per-type overrides exist (`workflow.byType[type].transitions`): a bug type can
|
|
99
|
+
disable the DoR gate without affecting stories.
|
|
100
|
+
|
|
101
|
+
Gates run through a **declarative rule catalog** (SM-102). `requireGate` maps to
|
|
102
|
+
catalog rules; two **global rules** apply to every forward transition on top of
|
|
103
|
+
the matched transition's own (each self-limits via the transition context):
|
|
104
|
+
|
|
105
|
+
- a **test-definition** must have ≥1 outbound `tests` link before leaving
|
|
106
|
+
backlog (`kind: "TEST_TARGETS"`);
|
|
107
|
+
- a **test-execution** must have a non-pending outcome before entering a
|
|
108
|
+
`done`-category status (`kind: "TEST_OUTCOME"`).
|
|
109
|
+
|
|
110
|
+
**The lockstep invariant (internalise this):** a gate is **N/A for a type when
|
|
111
|
+
that type hides the backing field** via `entityTypeConfig`. Hiding a field
|
|
112
|
+
doesn't only hide UI — it disables the matching gate:
|
|
113
|
+
|
|
114
|
+
| field hidden (`entityTypeConfig`) | gate that goes N/A |
|
|
115
|
+
|---|---|
|
|
116
|
+
| `showDefinitionOfReady: false` | DoR |
|
|
117
|
+
| `showDefinitionOfDone: false` | DoD |
|
|
118
|
+
| `showTestOutcome: false` | test-execution outcome |
|
|
119
|
+
|
|
120
|
+
So if a `change_ticket_status`/`complete_ticket` you expected to be gated sails
|
|
121
|
+
through, check whether the type hides that field. The read-only **Rules** tab in
|
|
122
|
+
Settings lists which rules are active per type.
|
|
123
|
+
|
|
124
|
+
Two transition rules to internalise:
|
|
125
|
+
|
|
126
|
+
1. **Skip-moves only check the matched transition's gate** — not every crossed
|
|
127
|
+
status's gate. `backlog → done` with gate=DoD checks DoD only. This is the
|
|
128
|
+
"Jira-rein" semantics — the user must define an explicit transition for the
|
|
129
|
+
move to be allowed at all.
|
|
130
|
+
2. **Reverse moves (toStatus index ≤ current index) are ungated** — reopening is
|
|
131
|
+
always permitted.
|
|
132
|
+
|
|
133
|
+
### Definition of Ready / Definition of Done
|
|
134
|
+
Templates on the project; *frozen copies* on each ticket. Items are checklists
|
|
135
|
+
with `required: true/false`. When a transition's `requireGate` fires, ALL
|
|
136
|
+
required items in the relevant block must be checked or the move is blocked with
|
|
137
|
+
`kind: "DoR" | "DoD", missing: [...]`. Project-level template changes do NOT
|
|
138
|
+
retroactively touch open tickets — only newly created tickets pick them up.
|
|
139
|
+
|
|
140
|
+
### entityTypeConfig (per-type field visibility)
|
|
141
|
+
`project.entityTypeConfig[type]` controls which sections a type shows AND, via
|
|
142
|
+
the lockstep above, which gates apply. Flag set (defaults in parentheses):
|
|
143
|
+
|
|
144
|
+
- `showAcceptanceCriteria` (true; false for test types)
|
|
145
|
+
- `showDefinitionOfReady` / `showDefinitionOfDone` (true; false for test types)
|
|
146
|
+
- `allowParentEpic` (true; **always false for `epic`**)
|
|
147
|
+
- `showProcessStep` / `showRelease` / `showLinks` (true)
|
|
148
|
+
- `showPrerequisites` / `showSteps` (test-definition only)
|
|
149
|
+
- `showExecutionSteps` / `showTestOutcome` (test-execution only)
|
|
150
|
+
|
|
151
|
+
Test-flags are hard-locked to their type — you can't switch on
|
|
152
|
+
`showPrerequisites` for a story.
|
|
153
|
+
|
|
154
|
+
### Board (Kanban Columns)
|
|
155
|
+
`project.boards.kanban.columns` is the column layout. Each column has `id`,
|
|
156
|
+
`name`, `statusIds[]` — a column may bundle multiple statuses into one lane
|
|
157
|
+
(e.g. *In Progress* bundling `in-progress` + `review`). Default = 1 column per
|
|
158
|
+
status. Statuses in no column show up as a synthetic trailing "orphan" lane so
|
|
159
|
+
nothing is hidden.
|
|
160
|
+
|
|
161
|
+
### Typed links + the Dependency view
|
|
162
|
+
Beyond the structural epic→story containment, tickets carry **typed links** to
|
|
163
|
+
other tickets. The catalogue lives in `project.linkTypes`. **Semantics matter** —
|
|
164
|
+
the type carries behaviour (cycle-checks, graph direction), it's not just a label:
|
|
165
|
+
|
|
166
|
+
| id | inverse | semantic | cycle-checked | typical use |
|
|
167
|
+
|---|---|---|---|---|
|
|
168
|
+
| `predecessor-of` | Successor of | precedence | ✅ | "must finish before" ordering |
|
|
169
|
+
| `blocks` | Blocked by | blocking | ✅ | "can't start until" hard dependency |
|
|
170
|
+
| `follows-on` | Precedes | sequence | — | softer linear chain |
|
|
171
|
+
| `contains` | Contained by | containment | ✅ | epic → story (canonical, SM-52) |
|
|
172
|
+
| `relates-to` | Relates to | freeform | — | symmetric "see also" |
|
|
173
|
+
| `executes` | Executed by | validation | — | test-execution → definition |
|
|
174
|
+
| `tests` | Tested by | validation | — | test-definition → feature |
|
|
175
|
+
| `modifies` | Modified by | freeform | ✅ | spec-change ticket → original |
|
|
176
|
+
| `supersedes` | Superseded by | supersession | ✅ | newer epic obsoletes the older version (drives the cross-release product-doc fold) |
|
|
177
|
+
| `replaces` | Replaced by | supersession | ✅ | a ticket replaces another |
|
|
178
|
+
| `refines` | Refined by | freeform | ✅ | adds detail without obsoleting |
|
|
179
|
+
| `realises` | Realised by | freeform | — | a ticket realises a PRD requirement/anchor (direction A) |
|
|
180
|
+
|
|
181
|
+
Cycle-checked semantics (precedence, blocking, containment, plus `modifies` via
|
|
182
|
+
an explicit flag) reject an edge that would close a loop (`kind: "LINK_CYCLE"`).
|
|
183
|
+
Containment is created via `position.epicId` at create time, NOT via
|
|
184
|
+
`link_create`; read it via `list_links_for_ticket` or the Dependency view, never
|
|
185
|
+
via `ticket.position.epicId`.
|
|
186
|
+
|
|
187
|
+
**The Dependency view** (third view next to Map and Kanban) renders all tickets
|
|
188
|
+
as a layered DAG. Use it to: see **what depends on this ticket** (downstream
|
|
189
|
+
impact / forward edges); see **what this ticket waits on** (upstream blockers /
|
|
190
|
+
backward edges); trace a feature epic → contained stories → implementing
|
|
191
|
+
tickets (the chain documents WHY each ticket exists); spot orphan tickets (no
|
|
192
|
+
edges — often a smell that something should have been linked). It's read-only.
|
|
193
|
+
|
|
194
|
+
**Link as you plan** — typed links + the Dependency view are the planning
|
|
195
|
+
surface, not an afterthought. Prefer the specific type (`blocks`,
|
|
196
|
+
`predecessor-of`) over generic `relates-to`.
|