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
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Spec evolution & test definitions (governance)
|
|
2
|
+
|
|
3
|
+
> Reference for the Story Mapper skill. The governance model (SM-92/SM-93): how
|
|
4
|
+
> spec changes flow, when test-definitions become runnable, what stops
|
|
5
|
+
> `complete_ticket`. Three layers, each with a different enforcement mode:
|
|
6
|
+
|
|
7
|
+
| Layer | What it does | Who enforces |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| **HARD** (tool-blocked) | Returns `isError` with `{kind, errors[], message:{title, reason, suggestion, skillRef}}`. The call doesn't go through. | `publish_test_definition`, `reopen_test_definition`, `test_exec_start`, `complete_ticket`, `ticket_update` (frozen-def case). |
|
|
10
|
+
| **SOFT** (warning) | Response includes `warnings:[{kind, context, message:{…}}]`. The write happens. | `ticket_update` on a `ready+` ticket with a spec patch (acceptanceCriteria / description / definitionOfReady). |
|
|
11
|
+
| **SKILL-only** (this section) | Not enforced by code. Respect it regardless. | Me. |
|
|
12
|
+
|
|
13
|
+
### Test-definition lifecycle
|
|
14
|
+
A `test-definition` is a feature-bound catalog artifact, not a work item. Two states:
|
|
15
|
+
|
|
16
|
+
- `draft` — being authored. NOT runnable (`test_exec_start` → `DEFINITION_DRAFT`).
|
|
17
|
+
- `published` — locked in. Runnable. `ticket_update` rejects step/prereq edits
|
|
18
|
+
(`DEFINITION_FROZEN`); use `update_test_definition_metadata` for cosmetic
|
|
19
|
+
fields, or the `modifies` path below to evolve the spec.
|
|
20
|
+
|
|
21
|
+
Promote via `publish_test_definition` (gates: ≥1 step, ≥1 `tests`-link, every
|
|
22
|
+
step has `expectedResult`, target ≥ `ready`). Revert via
|
|
23
|
+
`reopen_test_definition` (blocks with `ACTIVE_EXECUTION` if a run is in-progress).
|
|
24
|
+
|
|
25
|
+
### Spec changes via `modifies`-tickets, not in-place edits
|
|
26
|
+
When you need to change a ticket's spec AFTER it reached `ready+`:
|
|
27
|
+
|
|
28
|
+
1. Create a NEW ticket describing the change.
|
|
29
|
+
2. `link_create({sourceTicketId: newTicket, targetTicketId: original, linkTypeId: "modifies"})`.
|
|
30
|
+
3. Work the new ticket.
|
|
31
|
+
4. Linked test-definitions become `derivedHealth: stale`, so the next
|
|
32
|
+
`complete_ticket` on the original surfaces `STALE_LINKED_DEF` until you re-run
|
|
33
|
+
the affected definitions via `test_exec_start`.
|
|
34
|
+
|
|
35
|
+
`modifies` is cycle-checked, giving full traceability of which tickets reshape
|
|
36
|
+
which features.
|
|
37
|
+
|
|
38
|
+
### Workflow shorthand
|
|
39
|
+
```
|
|
40
|
+
Story (ready+, AC frozen)
|
|
41
|
+
↓ derive
|
|
42
|
+
test-definition (draft) → publish_test_definition → published
|
|
43
|
+
↓ test_exec_start
|
|
44
|
+
test-execution (in-progress) → record steps → auto-flip to done
|
|
45
|
+
↑
|
|
46
|
+
Spec changes? → new modifies-ticket → linked definitions go stale
|
|
47
|
+
→ re-run before complete_ticket
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
When a gate fires, read `message.suggestion` — it spells out the next MCP
|
|
51
|
+
call(s). `get_config` / `set_config` (`section: "governance"`) read/replace the
|
|
52
|
+
config (full replace; unknown predicate names are rejected with `UNKNOWN_PREDICATE`).
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# Tool catalogue — when to use what (full detail)
|
|
2
|
+
|
|
3
|
+
> Reference for the Story Mapper skill. The core SKILL.md (§5) carries a compact
|
|
4
|
+
> one-line index; this file has the full when-to-use tables + response shapes.
|
|
5
|
+
|
|
6
|
+
**Response shapes — compact by default (SM-123).** To keep token cost low, the
|
|
7
|
+
write tools and reads return a **compact** payload by default and let you opt
|
|
8
|
+
into the full object only when you need it:
|
|
9
|
+
|
|
10
|
+
- **Ticket-returning mutators** (`ticket_create`, `ticket_update`,
|
|
11
|
+
`change_ticket_status`, `mark_ready`, `complete_ticket`) return
|
|
12
|
+
`{revision, savedAt, ticket: {id, ticketKey, type, status, title, position}}`.
|
|
13
|
+
Pass **`verbose: true`** to get the full ticket (frozen DoR/DoD, AC, links).
|
|
14
|
+
- **`set_checklist_item`** returns just `{revision, savedAt, item: {id, checked}}`;
|
|
15
|
+
`verbose: true` for the full ticket.
|
|
16
|
+
- **`ticket_get`** returns the full ticket by default; pass `compact: true` for
|
|
17
|
+
the summary, or `fields: [...]` to pick named fields. **`list_tickets`** takes
|
|
18
|
+
`compact: true`.
|
|
19
|
+
- `reorder` (tickets), the bulk tools, the link tools, and the test-definition /
|
|
20
|
+
test-execution step+prereq tools are already compact. The test-definition
|
|
21
|
+
lifecycle tools (`publish_test_definition`, `reopen_test_definition`,
|
|
22
|
+
`update_test_definition_metadata`) and `test_exec_start` return the full
|
|
23
|
+
ticket because their meaningful fields (lifecycle, steps, executionSteps)
|
|
24
|
+
aren't in the summary.
|
|
25
|
+
|
|
26
|
+
Rule of thumb: act on the compact response (it carries `id`/`ticketKey`/`status`/
|
|
27
|
+
`position`); only add `verbose: true` when you must read a field the summary
|
|
28
|
+
doesn't carry.
|
|
29
|
+
|
|
30
|
+
### Discovery — "what is here?"
|
|
31
|
+
Cheap reads, no side effects. Call before acting in an unfamiliar project.
|
|
32
|
+
|
|
33
|
+
| Tool | When |
|
|
34
|
+
|------|------|
|
|
35
|
+
| `list_projects` | "Show me all projects" / orient yourself first. |
|
|
36
|
+
| `project_get` | Full snapshot of one project. Use sparingly — big payload. |
|
|
37
|
+
| `list_tickets` | Just the tickets. Filters (AND-combined): `status`, `type`, `releaseId`, `processStepId`, `epicId` (resolves via `contains`). Pass `"none"` or `""` for *absence* (backlog tickets, orphans). Pass `compact: true` for `{id, ticketKey, type, status, title, position}` only — shrinks an ~80-ticket project from ~400 KB to ~10 KB. The right read for most "what's in progress" / Map-Check questions. |
|
|
38
|
+
| `list_releases`, `list_process_steps` | Layout dimensions of the story map. |
|
|
39
|
+
| `get_config` | Read a project config section: `section ∈ definitions \| workflow \| kanban_columns \| governance \| link_types`. Returns `{section, value}`. For `section: "workflow"`, pass `type=` for the effective per-ticket-type workflow. |
|
|
40
|
+
| `resolve_definitions_for_ticket` | Effective DoR/DoD for a *specific* ticket (after byType merge + current checked-state). |
|
|
41
|
+
| `list_links_for_ticket` | Links touching a ticket. `direction: forward` (owned) / `backward` (pointing here) / `both`. The impact-analysis workhorse. |
|
|
42
|
+
| `next_actionable` | "What can I start NOW?" — the do-next queue: work items that are `todo`, DoR-met (or already `ready`), and not blocked by an unresolved blocking/precedence predecessor. Optional `releaseId` / `type`. Prefer this over eyeballing `list_tickets` when picking the next task. |
|
|
43
|
+
| `generate_product_doc` | "Describe the product as it stands." Folds the tickets into a Markdown product description — each epic is a feature with its release, derived status (shipped/in-progress/planned), realising stories + AC, and (with `includeTests`) its linked test-definitions + health. Optional `releaseId` scopes to one release; optional `types` is an allowlist of content types — pass e.g. `["epic","user-story","technical-task-backend","technical-task-ui"]` for a PRD so bugs + tests are excluded. It's the deterministic, traceable skeleton (direction B) — narrate/refine the prose yourself. Pass `saveAsAttachment: true` (+ optional `attachmentFilename`) to write the rendered doc back as a project-level attachment — the SM-182 round-trip. |
|
|
44
|
+
| `get_trace_coverage` | Direction-A coverage (mirror of the fold): per requirement, counts incoming `realises` + `tests` and classifies `covered` / `over-covered` / `orphan` / `suspect`. Optional `moduleId` scope. "Is the PRD fully covered, what's missing?" |
|
|
45
|
+
| `get_drift_report` | Round-trip / drift between the PRD and the tickets (SM-182): `orphanRequirements`, `suspectRequirements`, `danglingLinks` (realises/tests anchor whose target was deleted or isn't a requirement), `supersededTrace` (realises anchored on a superseded feature version). `summary.clean=true` = no drift. Run after structural ticket changes, then re-`generate_product_doc` to close the loop. |
|
|
46
|
+
|
|
47
|
+
### Setup — "let's start"
|
|
48
|
+
| Tool | When |
|
|
49
|
+
|------|------|
|
|
50
|
+
| `project_create` | Brand-new initiative. Pass `id`, `name`, `ticketPrefix`. Optionally seed `workflow`, `definitions`, `ticketTypes`, `entityTypeConfig`. |
|
|
51
|
+
| `project_update` | Patch the project header (name, description, definitions, workflow, boards). |
|
|
52
|
+
| `request_switch_project` | After `project_create`, ask the browser to switch so the user lands on it. |
|
|
53
|
+
| `release_create` | Add a release row. Use real names (`v1.0`, `Beta`). |
|
|
54
|
+
| `process_step_create` | Add a backbone column. Names describe *user-visible value*, not job-titles. |
|
|
55
|
+
| `set_config` | Replace a config section (full replace, no merge): `section ∈ definitions \| workflow \| kanban_columns \| governance \| link_types`, `value` = the new block (object for definitions/workflow/governance, array for kanban_columns/link_types). workflow needs ≥1 status; governance rejects unknown predicates; definitions only affect FUTURE tickets. |
|
|
56
|
+
|
|
57
|
+
### Authoring tickets — "capture this work"
|
|
58
|
+
| Tool | When |
|
|
59
|
+
|------|------|
|
|
60
|
+
| `ticket_create` | New ticket. Specify `type` + `title`. `position.{releaseId, epicId, processStepId}` to land it in a cell; omit to drop in the backlog. Never go past `status: backlog` on create. **`acceptanceCriteria:[{text}]` IS settable at creation** (SM-260) — no create-then-update. Do NOT pass `prerequisites`/`steps`/`links` arrays here — they no-op through the MCP bridge; use the dedicated tools. |
|
|
61
|
+
| `ticket_update` | Change title, description, labels, `acceptanceCriteria`, type, position, `definitionOfReady`/`definitionOfDone`. AC items use key **`text`**. **Position is a partial merge** (SM-260): patch `{releaseId}` to move the release only — omitted keys are kept, explicit `null` clears. Same array caveat: don't patch `prerequisites`/`steps`/`links` here. |
|
|
62
|
+
| `ticket_delete` | Soft-delete. Stays in revision history; restorable. |
|
|
63
|
+
|
|
64
|
+
**Acceptance criteria are a first-class field, never inline prose.** Every
|
|
65
|
+
testable expectation goes into `acceptanceCriteria[]` as a discrete item — NOT
|
|
66
|
+
bullets inside `description`. Reasons:
|
|
67
|
+
|
|
68
|
+
- The Ticket-Detail Modal renders `acceptanceCriteria[]` as a sortable,
|
|
69
|
+
individually-editable list. AC in prose are invisible to that UI and to the
|
|
70
|
+
DoR/DoD machinery.
|
|
71
|
+
- The DoR-item *"Acceptance criteria are defined"* is meant to be satisfied by
|
|
72
|
+
the array being populated. AC in prose make the DoR check vacuously true while
|
|
73
|
+
the ticket is actually unready.
|
|
74
|
+
- AC are the contract for `complete_ticket` — a reviewer reads them as a
|
|
75
|
+
checklist; a wall of prose can't serve that.
|
|
76
|
+
|
|
77
|
+
Pass `acceptanceCriteria` as objects `{text: "..."}` (the system fills `id` and
|
|
78
|
+
`completed: false`). Keep the description for *context* (the why, the symptom,
|
|
79
|
+
constraints). When you meet an older ticket with AC in the description, migrate
|
|
80
|
+
them into the array, trim the prose section, then check `dor-acceptance`.
|
|
81
|
+
|
|
82
|
+
### Typed links — "express dependencies + traceability"
|
|
83
|
+
| Tool | When |
|
|
84
|
+
|------|------|
|
|
85
|
+
| `link_create` | Add `source --linkTypeId--> target`. Cycle-checked for precedence/blocking/containment/`modifies`. Throws `LINK_SELF`, `LINK_TARGET_MISSING`, `LINK_DUPLICATE`, `LINK_CYCLE`. Use the specific type. |
|
|
86
|
+
| `link_delete` | Remove a link by `linkId` (no-op if gone). |
|
|
87
|
+
| `list_links_for_ticket` | Read links (see Discovery). Use before structural edits — every backward link is something you may break. |
|
|
88
|
+
| `get_config` / `set_config` (`section: "link_types"`) | Read / replace the catalogue. |
|
|
89
|
+
|
|
90
|
+
Containment (epic→story) is set via `position.epicId` at create time, NOT
|
|
91
|
+
`link_create`.
|
|
92
|
+
|
|
93
|
+
### Movement — "reorganise"
|
|
94
|
+
| Tool | When |
|
|
95
|
+
|------|------|
|
|
96
|
+
| `reorder` (`entity: "tickets"`) | Pure ordering OR bulk move into a cell/epic. `orderedIds[]` + optional `scope: {releaseId, processStepId, epicId}`. With `scope`, every listed ticket moves into that container (setting `scope.epicId` creates the `contains` link); without it, only `sortOrder` changes. The tool for "drag this story into that epic", "shuffle backlog priorities", "move the whole epic into another release". |
|
|
97
|
+
| `reorder` (`entity: "releases"` / `"process_steps"`) | Same idea for the story-map dimensions (no `scope`). |
|
|
98
|
+
|
|
99
|
+
### Bulk operations — "do this to many at once"
|
|
100
|
+
Best-effort by default (per-item failures reported, the rest proceed); pass
|
|
101
|
+
`opts.atomic: true` to roll back all on any failure.
|
|
102
|
+
|
|
103
|
+
| Tool | When |
|
|
104
|
+
|------|------|
|
|
105
|
+
| `bulk_change_status` | Move many tickets to one `targetStatus`. Per-item gate validation; failures return their `kind`/`missing`. |
|
|
106
|
+
| `bulk_ticket_update` | Apply one `patch` to many tickets. Respects spec-frozen gates; collects `SPEC_FROZEN_EDIT` warnings. |
|
|
107
|
+
| `bulk_link_create` | Create the same `linkTypeId` from many `sourceTicketIds[]` to one `targetTicketId` (e.g. tag many tickets as `modifies` one feature). |
|
|
108
|
+
|
|
109
|
+
### Workflow transitions — "advance this ticket"
|
|
110
|
+
| Tool | When |
|
|
111
|
+
|------|------|
|
|
112
|
+
| `change_ticket_status` | Generic status change. Respects DoR/DoD gates if the transition has them. |
|
|
113
|
+
| `mark_ready` | Shortcut for `→ ready`. Surfaces a clear `kind: "DoR", missing[]` on gate failure. |
|
|
114
|
+
| `complete_ticket` | Shortcut for `→ done`. ALWAYS use this (not `change_ticket_status: done`) so the DoD + governance gates fire explicitly. Coding-agent contract. Pass `checkDoD:true` (SM-260) to tick every required DoD item in the same call instead of N× `set_checklist_item` — but only when those items are genuinely true (don't auto-tick an "independent review" item that didn't happen). |
|
|
115
|
+
| `set_checklist_item` | Check/uncheck a single DoR/DoD item: `gate: "dor"\|"dod"`, `checked: true\|false`. Inline-persisted. Compact response by default (`{item:{id,checked}}`); pass `verbose:true` for the full ticket. |
|
|
116
|
+
|
|
117
|
+
### Test types — "specify once, run repeatedly"
|
|
118
|
+
The **definition** is reusable and carries the spec; the **execution** is
|
|
119
|
+
per-run and carries the result.
|
|
120
|
+
|
|
121
|
+
| Tool | When |
|
|
122
|
+
|------|------|
|
|
123
|
+
| `ticket_create type=test-definition` | New test spec. After create, `link_create … tests …` to the feature it validates (the gate enforces this before it can leave backlog). |
|
|
124
|
+
| `test_def_prereq_add` / `test_def_prereq_update` / `test_def_prereq_remove` | Manage the prerequisites list. |
|
|
125
|
+
| `test_def_prereq_check` / `test_def_prereq_uncheck` | Tick a prereq on the definition itself (rare — usually checked on the execution). |
|
|
126
|
+
| `test_def_step_add` / `test_def_step_update` / `test_def_step_remove` / `test_def_step_reorder` | Manage the 3-tuple steps (`step` / `data` / `expectedResult`). Use `_reorder`, never `ticket_update`. |
|
|
127
|
+
| `publish_test_definition` | Promote `draft → published` (runnable). Fires gates (≥1 step, ≥1 `tests`-link, every step has `expectedResult`, target ≥ `ready`). |
|
|
128
|
+
| `reopen_test_definition` | Demote `published → draft`. Blocks (`ACTIVE_EXECUTION`) if a run is in-progress. |
|
|
129
|
+
| `update_test_definition_metadata` | Edit title/description/labels on a published definition (spec stays frozen). |
|
|
130
|
+
| `test_exec_start` | Spawn an execution from a published definition. Clones steps, links `executes` → definition, starts `in-progress`. |
|
|
131
|
+
| `test_exec_record` | Record one step: `{status, actualResult, note?}`. Status auto-flips to `done` when the outcome settles. |
|
|
132
|
+
| `test_exec_set_outcome` | Manual outcome override. Pass `"auto"` to clear. Status syncs. |
|
|
133
|
+
| `test_exec_history` | Past runs of a definition, reverse-chrono. "Did this ever pass?" |
|
|
134
|
+
|
|
135
|
+
### Attachments — "binary reference docs (PRDs, designs)"
|
|
136
|
+
Files live on disk next to the DB; the agent reads/writes them over the channel
|
|
137
|
+
(base64 for small, a downloadUrl for large) — never via filesystem paths.
|
|
138
|
+
|
|
139
|
+
Two scopes: **project-level** (omit `ticketId`) for an initiative-wide source
|
|
140
|
+
doc like a PRD/PLD, and **ticket-level** (pass `ticketId`) for an item-specific
|
|
141
|
+
doc. There are no free-floating attachments — every one belongs to a project,
|
|
142
|
+
optionally to a ticket.
|
|
143
|
+
|
|
144
|
+
| Tool | When |
|
|
145
|
+
|------|------|
|
|
146
|
+
| `attachment_put` | Upload a binary (base64): `{projectId, filename, contentBase64, mimeType?, ticketId?}`. Max 25 MB. **OMIT `ticketId` for a project-level source PRD/PLD** — that's how you bring a spec into the tool to read + decompose it. Pass `ticketId` only to attach to one specific ticket. |
|
|
147
|
+
| `attachment_list` | Metadata only (no content). `ticketId` scopes to one ticket; `ticketId:"none"` lists project-level attachments only; omit for everything. |
|
|
148
|
+
| `attachment_get` | Always returns metadata + `downloadUrl`; inlines `contentBase64` for files ≤256 KB. For a big PDF, fetch the URL out-of-band instead of bloating the context. |
|
|
149
|
+
| `attachment_delete` | Remove an attachment by id. |
|
|
150
|
+
|
|
151
|
+
### Reflection — "look back"
|
|
152
|
+
| Tool | When |
|
|
153
|
+
|------|------|
|
|
154
|
+
| `list_revisions` | Reverse-chrono history. Each entry has an `op` label + `actor`. |
|
|
155
|
+
| `get_revision` | Inspect a single revision's snapshot. |
|
|
156
|
+
| `restore_revision` | Roll back to a revision. Creates a NEW revision (itself undoable). **Confirm with the user first.** |
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# End-to-end workflows
|
|
2
|
+
|
|
3
|
+
> Reference for the Story Mapper skill. The core SKILL.md (§4) carries the
|
|
4
|
+
> discipline rules; this file has the step-by-step playbooks.
|
|
5
|
+
|
|
6
|
+
### Plan a new initiative (greenfield)
|
|
7
|
+
1. `project_create` with a kebab-case `id`, a human `name`, a `ticketPrefix`.
|
|
8
|
+
2. `request_switch_project` so the user lands on it.
|
|
9
|
+
3. `release_create` at least one release (a v1, or "MVP").
|
|
10
|
+
4. **Decompose the user's journey FIRST**, then `process_step_create` one step
|
|
11
|
+
per *distinct phase* the user (or agent) passes through, in order. Err toward
|
|
12
|
+
MORE, finer phases — coarse catch-all steps (e.g. just 3 buckets) cram many
|
|
13
|
+
unrelated epics into one column and lose the journey's shape. Each step =
|
|
14
|
+
"what kind of value happens here", never the team's org chart. Decompose the
|
|
15
|
+
journey before placing any epics/stories, so each lands at the right phase.
|
|
16
|
+
5. Optionally `set_config` (`section: "workflow"` / `"definitions"`) if the defaults don't fit.
|
|
17
|
+
6. Capture top-level features as `ticket_create type=epic`, drop into cells via
|
|
18
|
+
`reorder` with `scope`.
|
|
19
|
+
7. Decompose each epic into 2–6 stories (`ticket_create type=user-story`,
|
|
20
|
+
created in backlog), then `reorder` with
|
|
21
|
+
`scope: {releaseId, processStepId, epicId}` to land them under the epic.
|
|
22
|
+
8. **Link as you go** — `link_create` `predecessor-of` / `blocks` between
|
|
23
|
+
stories with real ordering or dependency. This powers the Dependency view and
|
|
24
|
+
sprint sequencing.
|
|
25
|
+
9. Pause. Let the user see the structure. Talk through it.
|
|
26
|
+
|
|
27
|
+
### Decompose a source PRD/PLD into tickets (direction A) — the requirements layer
|
|
28
|
+
When the starting point is a written spec (a PRD/PLD), the doc precedes the
|
|
29
|
+
tickets. Don't decompose straight into epics/stories — first turn the document
|
|
30
|
+
into a **traceable requirements layer** (DOORS/ReqIF-style): the source is
|
|
31
|
+
sliced into atomic `requirement` SpecObjects that become the addressable truth,
|
|
32
|
+
and implementation tickets anchor back to them. The doc itself stays as
|
|
33
|
+
provenance; the slice chain is what you trace against.
|
|
34
|
+
|
|
35
|
+
**Slicing is two-stage, and the second stage is yours.** The server does a
|
|
36
|
+
*structural* coarse-slice at headings; you do the *content* analysis that turns
|
|
37
|
+
each coarse slice into the atomic requirements it actually contains. Don't
|
|
38
|
+
mistake one heading section for one requirement — a single section usually
|
|
39
|
+
bundles several testable assertions. One coarse slice → **1..n** requirements.
|
|
40
|
+
|
|
41
|
+
1. **Bring the spec in.** `project_create` → `attachment_put` with the PRD **and
|
|
42
|
+
no `ticketId`** (omitting it = project-level). In the browser the user can do
|
|
43
|
+
the same: the New-project dialog has a dropzone, and Project ▸ Attachments…
|
|
44
|
+
manages project-level docs.
|
|
45
|
+
2. **Stage 1 — coarse-slice (the server, structural).**
|
|
46
|
+
`ingest_slice_candidates` on the attachment id → the server converts it to
|
|
47
|
+
Markdown (officeparser-free stack: md/txt native, docx via fflate, pdf via
|
|
48
|
+
pdf2json — no OCR, no CDN) and pre-slices at headings into an ordered list of
|
|
49
|
+
candidate sections, each with a DOORS-style `sectionPath` ("2.1") + char
|
|
50
|
+
range. This is purely structural — every heading becomes one candidate, so
|
|
51
|
+
nothing is silently dropped. There is **no H1 special-case**: the numbering is
|
|
52
|
+
structural (depth-based), and a document with a single H1 wrapper is fine —
|
|
53
|
+
the generalisation to "what is actually a requirement" happens in stage 2, not
|
|
54
|
+
by reshaping the slice tree.
|
|
55
|
+
3. **Open a spec module.** `spec_module_create` with `title` +
|
|
56
|
+
`sourceAttachmentId` — the per-document container (DOORS module). Its
|
|
57
|
+
requirements are board-excluded and ordered by sectionPath.
|
|
58
|
+
4. **Stage 2 — content analysis (you, the agent).** Read each coarse slice's
|
|
59
|
+
prose and identify the individual atomic requirements inside it — **one
|
|
60
|
+
`requirement_create` per testable assertion**, not one per heading. A slice
|
|
61
|
+
that says "the user can log in with email+password, reset a forgotten
|
|
62
|
+
password, and stay signed in for 30 days" is **three** requirements, not one.
|
|
63
|
+
For every requirement you extract from a slice:
|
|
64
|
+
- pass the **slice's `sectionPath`** (all requirements distilled from the same
|
|
65
|
+
coarse slice share it — that is what groups them under the source section in
|
|
66
|
+
View ▸ Requirements);
|
|
67
|
+
- pass `sourceAnchor` `{attachmentId, sectionId, charStart, charEnd}` pointing
|
|
68
|
+
at the **specific span** that requirement came from (the n requirements of
|
|
69
|
+
one slice differ here — distinct char-ranges within the slice). `sectionId`
|
|
70
|
+
is provenance only; set it to the slice's `sectionPath` for consistency.
|
|
71
|
+
Grouping into the document section is driven by the requirement's own
|
|
72
|
+
`sectionPath`, never by `sectionId` — so the span is what distinguishes the
|
|
73
|
+
n requirements, and `sectionPath` is what keeps them together.
|
|
74
|
+
The requirement IS the unit of truth — not the doc, and not the coarse slice.
|
|
75
|
+
A coarse slice with only boilerplate/intro prose may yield **zero**
|
|
76
|
+
requirements — that's a legitimate gap, not a miss.
|
|
77
|
+
5. **Build + anchor traceability.** As you implement, `link_create` **`realises`**
|
|
78
|
+
from the implementing story/epic → the requirement (DOORS *satisfies*), and
|
|
79
|
+
`tests` from a test-definition → the requirement (*validates*). Anchor as you
|
|
80
|
+
create, not after.
|
|
81
|
+
6. **Check completeness + correctness.** `get_trace_coverage` (optionally
|
|
82
|
+
`moduleId`-scoped) classifies every requirement: `covered` (1 realises) /
|
|
83
|
+
`over-covered` (>1) / `orphan` (none) / `suspect` (tested, not implemented).
|
|
84
|
+
The user reviews in **View ▸ Requirements** — a full-page DOORS module view:
|
|
85
|
+
source prose next to each slice (verify the slicing is faithful), un-sliced
|
|
86
|
+
sections flagged as gaps (verify completeness), coverage badge + clickable
|
|
87
|
+
realising/testing tickets per requirement, inline-editable statements, and a
|
|
88
|
+
"create implementing ticket" action on orphans.
|
|
89
|
+
7. **Keep it a living document — round-trip + drift (SM-182).** As the tickets
|
|
90
|
+
evolve after the first slice, the doc and the code drift apart. `get_drift_report`
|
|
91
|
+
(optionally `moduleId`-scoped) surfaces four signals on the trace graph:
|
|
92
|
+
`orphanRequirements` (a requirement no ticket realises), `suspectRequirements`
|
|
93
|
+
(only `tests`, no implementer), `danglingLinks` (a realises/tests anchor whose
|
|
94
|
+
target was deleted or isn't a requirement), and `supersededTrace` (a realises
|
|
95
|
+
anchored on a superseded/historical feature version — the implementation moved
|
|
96
|
+
on but the anchor stayed). `summary.clean=true` means no drift. Run it after
|
|
97
|
+
structural ticket changes; fix the anchors; then **regenerate the doc** with
|
|
98
|
+
`generate_product_doc { saveAsAttachment: true }` to write the current
|
|
99
|
+
description back as a project-level attachment next to the source PRD — the
|
|
100
|
+
loop closes.
|
|
101
|
+
8. **Pause before mass-creating** — same rule as greenfield. Slice + propose the
|
|
102
|
+
requirement chain, let the user see it, then build.
|
|
103
|
+
|
|
104
|
+
`tests/mcp-prd-slicing-demo.js` drives this whole round from an example PRD
|
|
105
|
+
(`npm run prd-demo`); pass `--data-dir=./.storymap-data --http-url=…` to watch
|
|
106
|
+
it populate a live browser via `request_switch_project`.
|
|
107
|
+
|
|
108
|
+
### Execute a sprint
|
|
109
|
+
1. **Map-Check first.** `list_tickets status="backlog"` (add `compact:true`)
|
|
110
|
+
sorted by `sortOrder` — the user may have shuffled since my last read.
|
|
111
|
+
2. Propose the next-priority ticket to the user. Wait for confirmation.
|
|
112
|
+
3. Once confirmed: check DoR via `resolve_definitions_for_ticket`.
|
|
113
|
+
4. `set_checklist_item` (gate `"dor"`, checked:true) for each required item that's met.
|
|
114
|
+
5. `mark_ready` to graduate the story. (Gate failure tells you which items are
|
|
115
|
+
missing — relay them.)
|
|
116
|
+
6. As the user picks it up: `change_ticket_status → in-progress`.
|
|
117
|
+
7. When up for review: `→ review`.
|
|
118
|
+
8. `set_checklist_item` (gate `"dod"`, checked:true) for each met item.
|
|
119
|
+
9. `complete_ticket` — DoD + governance gates fire, ticket lands in *Done*.
|
|
120
|
+
10. After done: stop. Go back to step 1 (Map-Check) before the next ticket —
|
|
121
|
+
**unless** the bundle rule below applies.
|
|
122
|
+
|
|
123
|
+
For a batch of already-ready stories, `bulk_change_status` moves them together.
|
|
124
|
+
|
|
125
|
+
### Bundle related stories — don't pause after every data-layer ticket
|
|
126
|
+
Within an epic (or a logical implementation sequence), implement **related
|
|
127
|
+
stories in one bundle** instead of stopping after every ticket. Stopping after
|
|
128
|
+
every "done" shreds multi-story work into pauses with no signal value.
|
|
129
|
+
|
|
130
|
+
**Auto-complete criteria** (decide per-story):
|
|
131
|
+
|
|
132
|
+
- **Pure data-layer / MCP-tool / core-op / validation story** — no UI change,
|
|
133
|
+
no visible browser effect, AC fully covered by automated tests, all green →
|
|
134
|
+
check DoD + `complete_ticket` directly, then continue to the next story.
|
|
135
|
+
Surface the auto-complete decision in the reply + commit message.
|
|
136
|
+
- **UI story** — ALWAYS pause for the user to smoke. The visible effect IS the
|
|
137
|
+
verification; without a human in the loop the DoD-review item has no signal.
|
|
138
|
+
- **Hybrid story** — auto-complete the data-layer sub-steps; the final pause
|
|
139
|
+
comes for the UI smoke at the end.
|
|
140
|
+
|
|
141
|
+
**Bundle flow**: pick the lead story → Map-Check → walk all stories, deciding
|
|
142
|
+
auto-complete vs. user-smoke per story → mid-bundle commits (especially before a
|
|
143
|
+
UI-touching story, for a clean rollback point) → pause at the bundle end (or
|
|
144
|
+
when the next story needs UI smoke). The **first** ticket of a bundle is still
|
|
145
|
+
proposed + confirmed; only *subsequent purely-automatable* stories skip the
|
|
146
|
+
user-pause while their tests are green.
|
|
147
|
+
|
|
148
|
+
### Plan from dependencies — sequence + impact + traceability
|
|
149
|
+
- **Sequence + ready-pick**: capture the work as tickets, add typed links for
|
|
150
|
+
the relationships you know (`predecessor-of` when B depends on A's outcome,
|
|
151
|
+
`blocks` when A gates B, `relates-to` for soft cross-refs). The Dependency
|
|
152
|
+
view shows which tickets are ready (no unresolved upstream) — pick from the
|
|
153
|
+
ready set, preferring nodes that unblock the most downstream work. (`next_actionable`
|
|
154
|
+
computes this ready set directly.)
|
|
155
|
+
- **Impact analysis** (before a structural change): `list_links_for_ticket` on
|
|
156
|
+
the ticket you're about to touch — every **backward** link depends on current
|
|
157
|
+
behaviour and may break. Do this before renames, type changes, deletions,
|
|
158
|
+
API-surface changes.
|
|
159
|
+
- **Traceability**: from a goal (epic) walk `contains` into stories, then
|
|
160
|
+
domain links into the tickets that realise it. Answers "is feature X covered?"
|
|
161
|
+
- **Link as you create**: when a ticket depends on another, add the link
|
|
162
|
+
*immediately* — hidden dependencies become surprise blockers.
|
|
163
|
+
|
|
164
|
+
### Validate a feature with the test loop
|
|
165
|
+
Tests are tickets in the same workflow you already manage.
|
|
166
|
+
|
|
167
|
+
1. **Define once.** `ticket_create type=test-definition` with a clear title;
|
|
168
|
+
`link_create … tests …` to the feature; fill prereqs + steps
|
|
169
|
+
(`step` / `data` / `expectedResult`) via `test_def_prereq_add` /
|
|
170
|
+
`test_def_step_add`. The definition has NO outcome.
|
|
171
|
+
`publish_test_definition` when complete.
|
|
172
|
+
2. **Run.** `test_exec_start(definitionId, env?)` clones steps into a new
|
|
173
|
+
test-execution (status `in-progress`), links `executes` → definition. Cloned
|
|
174
|
+
steps are frozen — they reflect the definition at run time.
|
|
175
|
+
3. **Record.** Walk steps: `test_exec_record(execId, stepId, {status,
|
|
176
|
+
actualResult, note?})`.
|
|
177
|
+
4. **Auto-coupling.** Once every step is non-pending (or `outcomeOverride` set),
|
|
178
|
+
the execution auto-flips to `done`; the browser pill updates live.
|
|
179
|
+
5. **Iterate on failure.** Fix the code, then `test_exec_start` AGAIN — a NEW
|
|
180
|
+
execution. The failed run stays in history as a permanent record.
|
|
181
|
+
6. **Close the feature.** Only `complete_ticket(featureId)` after a passing
|
|
182
|
+
execution exists. Check via `test_exec_history(definitionId)`.
|
|
183
|
+
|
|
184
|
+
Don't skip the loop because the change "feels small" — even pure-data tickets
|
|
185
|
+
benefit from a 2-step definition (does it parse? does it round-trip?), a
|
|
186
|
+
permanent regression-net contribution.
|
|
187
|
+
|
|
188
|
+
### Reorganise
|
|
189
|
+
- *"Split this epic"* → `ticket_create` smaller stories, `reorder` them
|
|
190
|
+
under the original epic, optionally `ticket_delete` the original if it's now
|
|
191
|
+
just a label. (A native split-epic tool is roadmap, not built — do it by hand.)
|
|
192
|
+
- *"Move epic A into another release"* → `reorder` with
|
|
193
|
+
`scope: {releaseId: newR, processStepId: <epic's step>, epicId: null}`.
|
|
194
|
+
- *"Bump this story up the backlog"* → `reorder` with the new
|
|
195
|
+
`orderedIds[]`, no scope.
|
|
196
|
+
- Before any of these, `list_links_for_ticket` / the Dependency view to see what
|
|
197
|
+
depends on what.
|
|
198
|
+
|
|
199
|
+
### Look back
|
|
200
|
+
- `list_revisions` to see what happened since the last meeting.
|
|
201
|
+
- `get_revision` on an entry to compare snapshots.
|
|
202
|
+
- `restore_revision` to roll back. **Always confirm first** — it clobbers
|
|
203
|
+
current state (though it's itself undoable).
|