compass-st 1.1.2

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.
Files changed (118) hide show
  1. package/README.md +105 -0
  2. package/VERSION +1 -0
  3. package/bin/install +174 -0
  4. package/bootstrap.sh +95 -0
  5. package/cli/Cargo.lock +270 -0
  6. package/cli/Cargo.toml +24 -0
  7. package/cli/src/cmd/context.rs +59 -0
  8. package/cli/src/cmd/dag.rs +133 -0
  9. package/cli/src/cmd/git.rs +148 -0
  10. package/cli/src/cmd/hook.rs +51 -0
  11. package/cli/src/cmd/index.rs +363 -0
  12. package/cli/src/cmd/manifest.rs +34 -0
  13. package/cli/src/cmd/memory.rs +680 -0
  14. package/cli/src/cmd/migrate.rs +790 -0
  15. package/cli/src/cmd/mod.rs +14 -0
  16. package/cli/src/cmd/progress.rs +107 -0
  17. package/cli/src/cmd/project.rs +1700 -0
  18. package/cli/src/cmd/session.rs +64 -0
  19. package/cli/src/cmd/state.rs +317 -0
  20. package/cli/src/cmd/validate/mod.rs +506 -0
  21. package/cli/src/cmd/validate/prd.rs +472 -0
  22. package/cli/src/cmd/version.rs +89 -0
  23. package/cli/src/helpers.rs +40 -0
  24. package/cli/src/main.rs +75 -0
  25. package/cli/tests/fixtures/plan_empty_pointers.json +60 -0
  26. package/cli/tests/fixtures/plan_missing_pointers.json +59 -0
  27. package/cli/tests/fixtures/plan_too_many_pointers.json +92 -0
  28. package/cli/tests/fixtures/plan_v1_valid.json +64 -0
  29. package/cli/tests/fixtures/prd_bad_flow_bullet.md +37 -0
  30. package/cli/tests/fixtures/prd_bad_flow_prose.md +33 -0
  31. package/cli/tests/fixtures/prd_good_flow.md +41 -0
  32. package/cli/tests/fixtures/prd_xref_dangling.md +38 -0
  33. package/cli/tests/fixtures/prd_xref_valid.md +53 -0
  34. package/cli/tests/fixtures/projects/proj_a/.compass/.state/config.json +12 -0
  35. package/cli/tests/fixtures/projects/proj_b/.compass/.state/config.json +12 -0
  36. package/cli/tests/fixtures/projects/proj_c/.compass/.state/config.json +12 -0
  37. package/cli/tests/fixtures/registry/all_dead.json +18 -0
  38. package/cli/tests/fixtures/registry/corrupt.json +1 -0
  39. package/cli/tests/fixtures/registry/empty.json +1 -0
  40. package/cli/tests/fixtures/registry/last_active_dead.json +24 -0
  41. package/cli/tests/fixtures/registry/multi_alive.json +24 -0
  42. package/cli/tests/fixtures/registry/one_alive.json +12 -0
  43. package/cli/tests/fixtures/v0_project/.compass/.state/config.json +5 -0
  44. package/cli/tests/fixtures/v0_project/.compass/.state/sessions/onboarding-redesign/plan.json +29 -0
  45. package/cli/tests/fixtures/v0_project/.compass/.state/sessions/sample-feature/context.json +11 -0
  46. package/cli/tests/fixtures/v0_project/.compass/.state/sessions/sample-feature/plan.json +49 -0
  47. package/core/colleagues/base-rules.md +112 -0
  48. package/core/colleagues/manifest.json +85 -0
  49. package/core/colleagues/market-analyst.md +50 -0
  50. package/core/colleagues/prioritizer.md +53 -0
  51. package/core/colleagues/researcher.md +54 -0
  52. package/core/colleagues/reviewer.md +55 -0
  53. package/core/colleagues/stakeholder-comm.md +59 -0
  54. package/core/colleagues/story-breaker.md +57 -0
  55. package/core/colleagues/ux-reviewer.md +54 -0
  56. package/core/colleagues/writer.md +55 -0
  57. package/core/commands/compass/brief.md +28 -0
  58. package/core/commands/compass/check.md +27 -0
  59. package/core/commands/compass/epic.md +32 -0
  60. package/core/commands/compass/feedback.md +32 -0
  61. package/core/commands/compass/help.md +24 -0
  62. package/core/commands/compass/ideate.md +32 -0
  63. package/core/commands/compass/init.md +30 -0
  64. package/core/commands/compass/plan.md +27 -0
  65. package/core/commands/compass/prd.md +39 -0
  66. package/core/commands/compass/prioritize.md +36 -0
  67. package/core/commands/compass/prototype.md +28 -0
  68. package/core/commands/compass/release.md +32 -0
  69. package/core/commands/compass/research.md +31 -0
  70. package/core/commands/compass/roadmap.md +32 -0
  71. package/core/commands/compass/run.md +28 -0
  72. package/core/commands/compass/setup.md +32 -0
  73. package/core/commands/compass/sprint.md +32 -0
  74. package/core/commands/compass/status.md +32 -0
  75. package/core/commands/compass/story.md +37 -0
  76. package/core/commands/compass/undo.md +33 -0
  77. package/core/commands/compass/update.md +29 -0
  78. package/core/hooks/context-monitor.sh +5 -0
  79. package/core/hooks/manifest-tracker.sh +62 -0
  80. package/core/hooks/statusline.sh +12 -0
  81. package/core/hooks/update-checker.sh +24 -0
  82. package/core/integrations/confluence.md +267 -0
  83. package/core/integrations/figma.md +277 -0
  84. package/core/integrations/jira.md +436 -0
  85. package/core/integrations/vercel.md +170 -0
  86. package/core/manifest.json +172 -0
  87. package/core/shared/SCHEMAS-v1.md +404 -0
  88. package/core/shared/progress.md +145 -0
  89. package/core/shared/project-scan.md +293 -0
  90. package/core/shared/resolve-project.md +136 -0
  91. package/core/shared/ux-rules.md +52 -0
  92. package/core/shared/version-backup.md +38 -0
  93. package/core/templates/prd-template.md +145 -0
  94. package/core/templates/story-template.md +99 -0
  95. package/core/workflows/brief.md +184 -0
  96. package/core/workflows/check.md +436 -0
  97. package/core/workflows/epic.md +177 -0
  98. package/core/workflows/feedback.md +164 -0
  99. package/core/workflows/help.md +79 -0
  100. package/core/workflows/ideate.md +320 -0
  101. package/core/workflows/init.md +524 -0
  102. package/core/workflows/migrate.md +136 -0
  103. package/core/workflows/plan.md +320 -0
  104. package/core/workflows/prd.md +632 -0
  105. package/core/workflows/prioritize.md +301 -0
  106. package/core/workflows/project.md +177 -0
  107. package/core/workflows/prototype.md +174 -0
  108. package/core/workflows/release.md +179 -0
  109. package/core/workflows/research.md +613 -0
  110. package/core/workflows/roadmap.md +152 -0
  111. package/core/workflows/run.md +367 -0
  112. package/core/workflows/setup.md +294 -0
  113. package/core/workflows/sprint.md +187 -0
  114. package/core/workflows/status.md +185 -0
  115. package/core/workflows/story.md +477 -0
  116. package/core/workflows/undo.md +42 -0
  117. package/core/workflows/update.md +127 -0
  118. package/package.json +37 -0
@@ -0,0 +1,477 @@
1
+ # Workflow: compass:story
2
+
3
+ You are the story writer. Mission: produce estimable, testable User Stories with Given/When/Then acceptance criteria.
4
+
5
+ **Principles:** One story = one behavior. ACs must be independently verifiable. Derive personas and scenarios from the PRD, not generic roles. Never create a story the dev team can't estimate.
6
+
7
+ **Purpose**: Write User Stories + Acceptance Criteria (Given/When/Then) at Agile standard, ready to paste into Jira.
8
+
9
+ **Output**:
10
+ - Silver Tiger mode: path from `config.naming.story` (default: `epics/{EPIC}/user-stories/{PREFIX}-STORY-{NNN}-{slug}.md`)
11
+ - Standalone mode: path from `config.naming.story_standalone` (default: `.compass/Stories/STORY-{NNN}-{slug}.md`)
12
+
13
+ **When to use**:
14
+ - You already have a PRD and need to break it into estimate-able stories
15
+ - You need a single standalone story for an ad-hoc task
16
+ - You're refining an existing story
17
+
18
+ ---
19
+
20
+ ## Step 0 — Resolve active project
21
+
22
+ Apply the UX rules from `core/shared/ux-rules.md`.
23
+
24
+ Apply the shared snippet from `core/shared/resolve-project.md`. It sets up `$PROJECT_ROOT`, `$CONFIG`, and `$PROJECT_NAME` for downstream steps and prints the "Using: <name>" banner.
25
+
26
+ `$CONFIG` is already the parsed JSON of `$PROJECT_ROOT/.compass/.state/config.json`. Reuse the variable — do NOT re-read disk.
27
+
28
+ If `$CONFIG` is empty (edge fallback): read `$PROJECT_ROOT/.compass/.state/config.json` directly.
29
+
30
+ Parse `$CONFIG` once and extract all required fields below in a single pass — reuse the parsed variables.
31
+
32
+ Required fields:
33
+ - `lang` — chat language (`en` or `vi`)
34
+ - `spec_lang` — language for the generated artifact (`same` | `en` | `vi` | `bilingual`). When `same`, resolve to `lang`.
35
+ - `mode` — `silver-tiger` or `standalone`
36
+ - `prefix` — project prefix (Silver Tiger only)
37
+ - `templates_path` — path to templates directory
38
+ - `output_paths` — where to write artifacts
39
+ - `naming` — filename patterns (read `naming.story` for Silver Tiger, `naming.story_standalone` for standalone)
40
+
41
+ **Error handling**:
42
+ - If `config.json` does not exist → tell the user: "Config not found. Please run `/compass:init` to set up your workspace first." Stop.
43
+ - If `config.json` exists but cannot be parsed (corrupt/invalid JSON) → tell the user: "Config file appears to be corrupt or contains invalid JSON. Please run `/compass:init` to regenerate it." Stop.
44
+ - If `config.json` is valid but missing required fields → list the missing fields and tell the user to run `/compass:init`.
45
+
46
+ **Naming resolution** (resolve once, use in Steps 5–6):
47
+ - Silver Tiger: use `config.naming.story` if present; fallback to `epics/{EPIC}/user-stories/{PREFIX}-STORY-{NNN}-{slug}.md`
48
+ - Standalone: use `config.naming.story_standalone` if present; fallback to `.compass/Stories/STORY-{NNN}-{slug}.md`
49
+
50
+ **Language enforcement**: ALL chat text in `lang`. Artifact file content in `spec_lang`.
51
+
52
+ Extract `interaction_level` from config (default: "standard" if missing):
53
+ - `quick`: minimize questions — auto-fill defaults, skip confirmations, derive everything from context. Only ask when truly ambiguous.
54
+ - `standard`: current behavior — ask key questions, show options, confirm decisions.
55
+ - `detailed`: extra questions — deeper exploration, more options, explicit confirmation at every step.
56
+
57
+ ---
58
+
59
+ ### Auto mode (interaction_level = quick)
60
+
61
+ If interaction_level is "quick":
62
+ 1. Derive title, user context, size, and ACs from the linked PRD or $ARGUMENTS context — do NOT ask AskUserQuestion for each.
63
+ 2. Auto-select size estimate based on scope inference (default: "M" if ambiguous).
64
+ 3. Generate the complete story with ACs and show it for one final review: "OK? / Edit"
65
+ 4. Total questions: 0-1 (only the final review)
66
+
67
+ If interaction_level is "detailed":
68
+ 1. Run all Steps as normal
69
+ 2. After composing ACs, add extra questions about dependencies, edge cases, and Definition of Done variants
70
+ 3. Total questions: ~10-15
71
+
72
+ If interaction_level is "standard":
73
+ 1. Current behavior — no changes needed
74
+
75
+ ---
76
+
77
+ ## Step 0a: Detect active pipeline session
78
+
79
+ Before scanning for project context, check whether a pipeline session is active:
80
+
81
+ ```bash
82
+ PIPELINE=$(find "$PROJECT_ROOT/.compass/.state/sessions/" -name "pipeline.json" -exec grep -l '"status": "active"' {} \; 2>/dev/null | sort | tail -1)
83
+ ```
84
+
85
+ **If an active pipeline is found:**
86
+
87
+ 1. Read `pipeline.json` — extract the session `id` (slug) and `title` from the sibling `context.json`.
88
+ 2. Show (in `lang`):
89
+ - en: `"Active pipeline detected: <title>. Stories can be saved into this session."`
90
+ - vi: `"Phát hiện pipeline đang hoạt động: <title>. Stories có thể được lưu vào phiên này."`
91
+ 3. Use AskUserQuestion to confirm:
92
+ ```json
93
+ {"questions": [{"question": "Save stories in the active pipeline session?", "header": "Pipeline session", "multiSelect": false, "options": [{"label": "Yes — part of pipeline", "description": "Save stories in the session AND in the normal output folder"}, {"label": "No — standalone", "description": "Save only in the normal output folder, ignore the pipeline"}]}]}
94
+ ```
95
+ Vietnamese version (use when `lang=vi`):
96
+ ```json
97
+ {"questions": [{"question": "Lưu stories vào pipeline session đang hoạt động?", "header": "Pipeline session", "multiSelect": false, "options": [{"label": "Có — thuộc pipeline", "description": "Lưu stories vào session VÀ vào thư mục output bình thường"}, {"label": "Không — standalone", "description": "Chỉ lưu vào thư mục output bình thường, bỏ qua pipeline"}]}]}
98
+ ```
99
+ 4. If **Yes**:
100
+ - Set `pipeline_mode = true` and `pipeline_slug = <id>`.
101
+ - After Step 6 writes each story file, also copy it to `$PROJECT_ROOT/.compass/.state/sessions/<slug>/story-<slug>.md`.
102
+ - Append each story's file path to the `artifacts` array in `pipeline.json`:
103
+ ```json
104
+ { "type": "story", "path": "<output-file-path>", "session_path": "$PROJECT_ROOT/.compass/.state/sessions/<slug>/story-<slug>.md", "created_at": "<ISO>" }
105
+ ```
106
+ - When breaking a PRD into multiple stories (Step 4b), append each story individually as a separate artifact entry.
107
+ 5. If **No** → set `pipeline_mode = false`. Proceed as standalone (current behavior).
108
+
109
+ **If no active pipeline found:** set `pipeline_mode = false`. Continue with current standalone behavior — no change.
110
+
111
+ ---
112
+
113
+ ## Step 0b: Project awareness check
114
+
115
+ Apply the shared project-scan module from `core/shared/project-scan.md`.
116
+ Pass: keywords=$ARGUMENTS, type="story"
117
+
118
+ The module handles scanning, matching, and asking the user:
119
+ - If "Break PRD into stories" → activate Step 4b (parallel story generation from PRD)
120
+ - If "Use as context" → read ALL found files, use their content when writing the story
121
+ - If "Update" → read the existing story, ask what needs changing, update in place
122
+ - If "Ignore" → continue fresh
123
+ - If "Show me" → display files, re-ask
124
+
125
+ > **Note**: The "Break this PRD into stories" option is specific to this workflow and is included in the type="story" question set within the shared module.
126
+
127
+ ---
128
+
129
+ ## Step 1 — Read context
130
+
131
+ **Silver Tiger mode:**
132
+ 1. Read `{templates_path}/user-story-template.md` — the canonical story template.
133
+ 2. List epics by globbing `epics/{prefix}-EPIC-*/epic.md`. Show the list to the user.
134
+ 3. List existing PRDs in `prd/`.
135
+ 4. If Jira is enabled: remember project key. Do NOT auto-create Jira tickets.
136
+
137
+ **Standalone mode:**
138
+ 1. Read `~/.compass/core/templates/story-template.md` (bundled).
139
+ 2. List existing stories in `.compass/Stories/`.
140
+ 3. List PRDs in `.compass/PRDs/`.
141
+
142
+ ## Step 2 — Identify the source
143
+
144
+ Use AskUserQuestion to ask the user what this story is based on.
145
+
146
+ English example question: "What is this story based on?"
147
+ Vietnamese example question: "Story này dựa trên cơ sở nào?"
148
+
149
+ ```json
150
+ {"questions": [{"question": "What is this story based on?\n(Tiếng Việt: Story này dựa trên cơ sở nào?)", "header": "Story source", "multiSelect": false, "options": [{"label": "A PRD", "description": "Point me to the PRD path and I'll break it into stories / Chỉ cho tôi đường dẫn PRD, tôi sẽ chia thành các stories"}, {"label": "A new idea / feature (no PRD yet)", "description": "Start from scratch with a new concept / Bắt đầu từ ý tưởng mới chưa có PRD"}, {"label": "Refining an existing story", "description": "Point me to the story file to refine / Chỉ cho tôi file story cần chỉnh sửa"}]}]}
151
+ ```
152
+
153
+ If (a — PRD) → read the PRD, propose how many stories it could break into, list them. Use AskUserQuestion to let the user pick which to write, or "all".
154
+
155
+ If multiple stories → repeat Steps 3–6 for each (confirm after each).
156
+
157
+ ## Step 3 — Identify epic (Silver Tiger mode only)
158
+
159
+ This step is SKIPPED in standalone mode.
160
+
161
+ Best practice: a story should live under an epic. But users occasionally need to capture an ad-hoc story without an epic container. This step gives them both paths explicitly.
162
+
163
+ ### Step 3a — Offer the choice
164
+
165
+ Build the options array from the epics found in Step 1. If zero epics exist, the existing-epic group is empty. Two terminal options are ALWAYS included at the end:
166
+
167
+ 1. `📚 Create Epic first (recommended)` — invokes `/compass:epic` inline, then returns to Step 3.
168
+ 2. `⏭ Skip Epic — write story directly` — marks the story as epic-less; output goes to the standalone story path (`.compass/Stories/STORY-{NNN}-{slug}.md`), frontmatter `epic: null`, Step 7 (update parent epic.md) is skipped.
169
+
170
+ English example question: "Where should this story live?"
171
+ Vietnamese example question: "Story này thuộc đâu?"
172
+
173
+ ```json
174
+ {"questions": [{"question": "Where should this story live?\n(Tiếng Việt: Story này thuộc đâu?)", "header": "Select epic", "multiSelect": false, "options": [{"label": "{PREFIX}-EPIC-01 — {Epic Name}", "description": "Add the story under this existing epic / Thêm story vào epic này"}, {"label": "📚 Create Epic first (recommended)", "description": "I'll run /compass:epic now, then continue writing this story / Tôi sẽ chạy /compass:epic trước, sau đó quay lại viết story"}, {"label": "⏭ Skip Epic — write story directly", "description": "Write a standalone story under .compass/Stories/ without a parent epic / Viết story đứng riêng trong .compass/Stories/ không thuộc epic nào"}]}]}
175
+ ```
176
+
177
+ ### Step 3b — Route based on choice
178
+
179
+ - **Existing epic picked** → set `EPIC_MODE = "under_epic"`, record `EPIC_PATH = epics/{PREFIX}-EPIC-{NN}-{slug}/`. Continue below.
180
+ - **"📚 Create Epic first"** → set `EPIC_MODE = "pending"`. Load and execute `core/workflows/epic.md` inline as a sub-workflow. When `/compass:epic` finishes and prints its `Done` summary, return here and re-run Step 3a so the user can pick the newly created epic from the refreshed list.
181
+ - **"⏭ Skip Epic — write story directly"** → set `EPIC_MODE = "skipped"`. Skip the rest of Step 3 entirely. The story will be written to the standalone path and Step 7 (epic.md update) will be a no-op.
182
+
183
+ ### Step 3c — Inherit epic frontmatter (when `EPIC_MODE == "under_epic"`)
184
+
185
+ 1. Read `{EPIC_PATH}/epic.md` frontmatter.
186
+ 2. Inherit fields into the story: `jira-project`, `platform`, `priority`, `epic-link` (Jira ID if set).
187
+ 3. List existing stories in `{EPIC_PATH}/user-stories/` to determine the next story number (max + 1, padded to 3 digits).
188
+
189
+ ## Step 4 — Interview to fill one story
190
+
191
+ **Emit progress plan before starting** — apply Pattern 1 from `core/shared/progress.md`:
192
+
193
+ ```
194
+ 📋 Story: <story title or "<slug>">
195
+ Epic: <epic name or "standalone"> Expected: 1-2 min
196
+
197
+ ⏸ Question A — Title
198
+ ⏸ Question B — User context
199
+ ⏸ Question C — Size + Deps + DoD
200
+ ⏸ Question D — Acceptance Criteria
201
+ ```
202
+
203
+ Tick after each question is answered. Final summary in Step 8.
204
+
205
+ ### Question A: Title
206
+
207
+ Use AskUserQuestion. Scan the PRD (if available) for feature name and user roles to generate context-aware suggestions. If no PRD is available, offer generic user story patterns.
208
+
209
+ ```json
210
+ {"questions": [{"question": "What's the story title?", "header": "Story Title", "multiSelect": false, "options": [{"label": "As a <role>, I want to <action>, so that <benefit>", "description": "Standard user story format — replace placeholders with your context"}, {"label": "As an Admin, I want to manage team members, so that I can control workspace access", "description": "Example admin story — adapt to your feature"}, {"label": "As a user, I want to upload files in bulk, so that I can save time on repetitive uploads", "description": "Example end-user story — adapt to your feature"}, {"label": "Type a custom title", "description": "Enter your own title or user story statement"}]}]}
211
+ ```
212
+
213
+ Vietnamese example (used when `lang=vi`):
214
+ ```json
215
+ {"questions": [{"question": "Tiêu đề story là gì?", "header": "Tiêu đề Story", "multiSelect": false, "options": [{"label": "Là một <vai trò>, tôi muốn <hành động>, để <lợi ích>", "description": "Định dạng user story chuẩn — thay thế placeholder bằng ngữ cảnh của bạn"}, {"label": "Là một Admin, tôi muốn quản lý thành viên nhóm, để kiểm soát quyền truy cập workspace", "description": "Ví dụ story admin — điều chỉnh theo tính năng của bạn"}, {"label": "Là một người dùng, tôi muốn tải lên file hàng loạt, để tiết kiệm thời gian cho các lần tải lên lặp lại", "description": "Ví dụ story người dùng cuối — điều chỉnh theo tính năng của bạn"}, {"label": "Nhập tiêu đề tùy chỉnh", "description": "Nhập tiêu đề hoặc phát biểu user story của bạn"}]}]}
216
+ ```
217
+
218
+ ### Question B: User context
219
+
220
+ Derive the user persona from the PRD if one is linked. If a PRD was read in Step 1 or Step 2, extract the primary and secondary user roles from its Section C — do NOT fall back to generic "Admin / End user / Guest" if the PRD has actual personas defined.
221
+
222
+ Areas to explore:
223
+ - Primary user role from the PRD (C1) — their job, access tier, workflow context
224
+ - Secondary user roles if they interact with this story's output (e.g. approvers, viewers)
225
+ - The screen or surface the user is operating on (dashboard, settings, file picker, etc.)
226
+ - The user's goal-in-context (what they are trying to accomplish in this specific story)
227
+
228
+ Use AskUserQuestion. Generate 2–3 persona options DERIVED from the PRD or story title context. For example, if the PRD is about "key rotation" for a KMS product, suggest "Security Admin rotating an expired CMK" and "Workspace Owner reviewing rotation history" — not generic roles.
229
+
230
+ If no PRD is available, scan existing stories in the same epic for user role patterns and surface those as suggestions.
231
+
232
+ Ask one question at a time. Adapt depth to what the PO has told you so far.
233
+
234
+ Generate options in `lang`. If `lang=vi`, generate Vietnamese labels and descriptions from context — do not translate hardcoded English strings.
235
+
236
+ ### Question C: Story scope (1 batched call with size + dependencies + DoD)
237
+
238
+ **Batch size, dependencies, and Definition of Done into a SINGLE AskUserQuestion call with 3 questions.** The Claude Code tool supports up to 4 questions per call — use it to collapse 3 sequential round trips into 1.
239
+
240
+ Before calling, scan existing stories in the same epic to derive dependency candidates (if the project has an auth story, surface it; otherwise drop that option).
241
+
242
+ Batched structure (English):
243
+
244
+ ```json
245
+ {"questions": [
246
+ {"question": "How big is this story?", "header": "Size Estimate", "multiSelect": false, "options": [{"label": "XS", "description": "Tiny, a few hours"}, {"label": "S", "description": "Small, less than a day"}, {"label": "M", "description": "Medium, 1–2 days"}, {"label": "L", "description": "Large — consider splitting"}]},
247
+ {"question": "Does this story depend on any other stories that must finish first?", "header": "Dependencies", "multiSelect": false, "options": [{"label": "None — independent", "description": "Can be picked up without waiting"}, {"label": "<derived candidate 1 from scan>", "description": "..."}, {"label": "<derived candidate 2 from scan>", "description": "..."}, {"label": "Other — I'll name it", "description": "Type the story ID"}]},
248
+ {"question": "When is this story DONE?", "header": "Definition of Done", "multiSelect": false, "options": [{"label": "ACs pass + code reviewed + staging deployed", "description": "Standard team DoD"}, {"label": "ACs pass + code reviewed + production deployed + no smoke-test regressions", "description": "Full production DoD"}, {"label": "ACs pass + PR merged + feature flag on for QA", "description": "Flagged-release DoD"}, {"label": "Custom DoD", "description": "Describe your own"}]}
249
+ ]}
250
+ ```
251
+
252
+ When `lang=vi`, regenerate all labels/descriptions in Vietnamese — do NOT make two separate calls.
253
+
254
+ **XL special case**: if the user picks size "XL" (too large), stop and propose 2–4 sub-stories before continuing to Question D.
255
+
256
+ ### Question D: Acceptance Criteria
257
+
258
+ Derive acceptance criteria approach from the story title (Question A) and user context (Question B). Do not show generic AC pattern options — the suggestions should reflect the actual story.
259
+
260
+ Areas to explore before generating AC options:
261
+ - What is the primary action the user takes? (that becomes the "When")
262
+ - What state must exist for the action to happen? (that becomes the "Given")
263
+ - What outcomes must be observable? (happy path → "Then", edge cases → additional ACs)
264
+ - What permissions or roles are involved? (permission AC if relevant)
265
+ - What can go wrong? (validation errors, empty states, network failure, quota limits)
266
+
267
+ Use AskUserQuestion. Generate 2–3 AC approach options that reflect the story context. For example, if the story is "As a Security Admin, I want to rotate an expired CMK, so that my encryption keys stay current", the options should reference CMK rotation scenarios — not generic "form submit" or "list select" patterns.
268
+
269
+ Good option examples for that story:
270
+ - "Auto-generate: rotation success + already-rotating guard + audit log entry + permission check"
271
+ - "Start with happy path: admin triggers rotation, system confirms completion"
272
+ - "I have specific rotation scenarios in mind — let me describe them"
273
+
274
+ Always include these three structural options (adapted to the specific story context):
275
+ 1. Auto-generate full AC set (happy path + edge + error + permission where relevant)
276
+ 2. Start with happy path only, then build edge cases together
277
+ 3. I have specific scenarios — I'll describe them
278
+
279
+ If PO picks "Auto-generate", draft 4–8 ACs from context (minimum: 1 happy path, 1 edge case, 1 error case, 1 permission AC if relevant), then show for PO review via AskUserQuestion (OK / Edit / Add more).
280
+
281
+ Generate options in `lang`. If `lang=vi`, generate Vietnamese labels and descriptions from context — do not translate hardcoded English strings.
282
+
283
+ ## Step 4b — Parallel story generation (when breaking a PRD)
284
+
285
+ **This step activates ONLY when the PO asked to break a full PRD into stories** (via Step 2 source = "Break a PRD into stories" or via `/compass:brief` → Story Breaker colleague).
286
+
287
+ When a PRD has multiple requirements (e.g. [REQ-01] through [REQ-08]):
288
+
289
+ 1. **Extract all requirements** from the PRD — list each [REQ-xx] with its title
290
+
291
+ 2. **Emit delegation plan** — apply Pattern 2 from `core/shared/progress.md`:
292
+ ```
293
+ 🚀 Delegating to 6 Story Breaker colleagues (parallel):
294
+
295
+ 🔄 Story Breaker: Authentication & Login ← REQ-01
296
+ 🔄 Story Breaker: MFA Setup ← REQ-02
297
+ 🔄 Story Breaker: Password Reset ← REQ-03
298
+ 🔄 Story Breaker: Session Management ← REQ-04
299
+ 🔄 Story Breaker: Account Lockout ← REQ-05
300
+ 🔄 Story Breaker: Audit Logging ← REQ-06
301
+
302
+ Expected: 30-60s (parallel)
303
+ ```
304
+
305
+ 3. **Ask PO to confirm** via AskUserQuestion: "Break into 6 stories?" → [Yes, break all] / [Remove some] / [I'll write one at a time]
306
+
307
+ 4. **Spawn parallel agents** (Task tool, one per requirement):
308
+ - Each agent receives: the specific [REQ-xx] text + full PRD context + story template
309
+ - Each produces: 1 complete story file with title, AC (Given/When/Then), estimate, dependencies
310
+ - Output naming: `{PREFIX}-STORY-{NNN}-{slug}.md` with auto-incremented NNN
311
+
312
+ 5. **As each colleague finishes, tick the line** with elapsed seconds:
313
+ ```
314
+ ✓ Story Breaker: Authentication & Login (34s) STORY-001 M 3 ACs
315
+ ✓ Story Breaker: MFA Setup (28s) STORY-002 S 4 ACs
316
+ 🔄 Story Breaker: Password Reset ...
317
+ ```
318
+
319
+ 6. **Final summary** when all complete:
320
+ ```
321
+ ✅ All 6 stories created (58s total)
322
+
323
+ STORY-001 Authentication & Login M 3 ACs
324
+ STORY-002 MFA Setup S 4 ACs
325
+ STORY-003 Password Reset S 3 ACs
326
+ STORY-004 Session Management M 5 ACs
327
+ STORY-005 Account Lockout S 3 ACs
328
+ STORY-006 Audit Logging XS 2 ACs
329
+ ```
330
+
331
+ 7. **Ask PO to review** via AskUserQuestion: "Stories look good?" → [OK] / [Edit one] / [Regenerate one]
332
+
333
+ **Agent naming**: each agent is named `Story Breaker: <requirement title>` — descriptive, not numbered.
334
+
335
+ **If PO chose to write one at a time** → skip this step, use the normal Steps 3-4 flow for a single story.
336
+
337
+ ---
338
+
339
+ ## Step 5 — Compose the story
340
+
341
+ **Silver Tiger mode:**
342
+ - Use the template from `{templates_path}/user-story-template.md`.
343
+ - Fill frontmatter: `epic` (relative path to epic.md), `jira-project` (from epic), `issue-type: Story`, `platform` (from epic), `epic-link` (from epic), `priority` (from epic or ask), `labels` (from context), `jira-id: ""`, `status: pending-push`.
344
+ - Auto-increment story ID: scan existing files in `epics/{EPIC}/user-stories/`, take the max number found (e.g. STORY-003 → next is 004), pad to 3 digits.
345
+ - Output filename: apply `config.naming.story` pattern (fallback: `epics/{EPIC}/user-stories/{PREFIX}-STORY-{NNN}-{slug}.md`).
346
+
347
+ **Standalone mode:**
348
+ - Use `~/.compass/core/templates/story-template.md`.
349
+ - Auto-increment story ID: scan `.compass/Stories/`, same logic.
350
+ - Output filename: apply `config.naming.story_standalone` pattern (fallback: `.compass/Stories/STORY-{NNN}-{slug}.md`).
351
+
352
+ **AC format** (both modes):
353
+
354
+ ```
355
+ - [ ] **AC<N>: <Short scenario name>**
356
+ - Given <initial state>
357
+ - And <extra precondition if needed>
358
+ - When <single user action>
359
+ - Then <expected outcome>
360
+ - And <extra outcome if needed>
361
+ ```
362
+
363
+ **AC rules**:
364
+ - Each AC tests a single behavior
365
+ - "Given" describes state, not action
366
+ - "When" is a single action
367
+ - "Then" describes an observable outcome, not internal state
368
+ - Don't reference specific UI element IDs — write "click the Submit button", not "click #submit-btn"
369
+ - At least 1 happy + 1 edge + 1 error. Permission AC if relevant.
370
+
371
+ ### AC Flow Diagram (optional)
372
+
373
+ For complex stories with multiple paths, add a Mermaid flowchart showing the AC branches. Derive the nodes and edges from the actual Given/When/Then acceptance criteria written above — not from this example. The example below is illustrative only.
374
+
375
+ ```mermaid
376
+ graph TD
377
+ A[Given: user is authenticated] --> B[When: clicks rotate key]
378
+ B --> C{Key status?}
379
+ C -->|Active| D[Then: rotation starts]
380
+ C -->|Already rotating| E[Then: show "in progress" message]
381
+ D --> F{Rotation success?}
382
+ F -->|Yes| G[Then: show new key ID + audit log]
383
+ F -->|No| H[Then: show error + keep old key active]
384
+ ```
385
+
386
+ Include this diagram when:
387
+ - Story has ≥3 acceptance criteria
388
+ - There are branching conditions (if/else paths)
389
+ - Error handling is part of the AC
390
+
391
+ Skip for simple stories (single happy path, no conditions).
392
+
393
+ ## Step 6 — Write the file
394
+
395
+ Resolve the output path using the naming pattern from Step 0 and `EPIC_MODE` from Step 3.
396
+
397
+ **Silver Tiger mode, `EPIC_MODE == "under_epic"`:**
398
+ - Slug = kebab-case from the title
399
+ - Path: apply `config.naming.story` (fallback: `epics/{EPIC-folder}/user-stories/{PREFIX}-STORY-{NNN}-{slug}.md`)
400
+ - Example: `epics/KMS-EPIC-02-cmk-management/user-stories/KMS-STORY-001-create-cmk.md`
401
+ - Create `user-stories/` directory if it doesn't exist (`mkdir -p`).
402
+
403
+ **Silver Tiger mode, `EPIC_MODE == "skipped"`, OR Standalone mode:**
404
+ - Path: apply `config.naming.story_standalone` (fallback: `.compass/Stories/STORY-{NNN}-{slug}.md`)
405
+ - Example: `.compass/Stories/STORY-001-create-cmk.md`
406
+ - Create `.compass/Stories/` if it doesn't exist.
407
+ - Frontmatter `epic:` field → set to `null`.
408
+
409
+ If `spec_lang` is `bilingual`, write a secondary version with `-vi.md` or `-en.md` suffix.
410
+
411
+ **After writing the file, update the project index:**
412
+ ```bash
413
+ compass-cli index add "<output-file-path>" "story" 2>/dev/null || true
414
+ ```
415
+ This keeps the index fresh for the next workflow — instant, no full rebuild needed.
416
+
417
+ ## Step 7 — Auto-update parent epic (Silver Tiger mode, `EPIC_MODE == "under_epic"` only)
418
+
419
+ This step is SKIPPED in standalone mode AND when `EPIC_MODE == "skipped"` (user chose to write the story outside any epic in Step 3).
420
+
421
+ 1. Read the parent `epic.md`.
422
+ 2. Find the "Tasks" or "User Stories" section (look for `## Tasks` or `## User Stories`).
423
+ 3. Add a new checkbox line linking to the created story:
424
+ ```
425
+ - [ ] [{PREFIX}-STORY-{NNN} {slug title}](user-stories/{PREFIX}-STORY-{NNN}-{slug}.md)
426
+ ```
427
+ 4. Write back the updated `epic.md`.
428
+ 5. If no Tasks/User Stories section exists, create one at the end of the file.
429
+
430
+ ## Step 8 — Confirm
431
+
432
+ Emit the final progress summary (Pattern 1 Step C from `core/shared/progress.md`):
433
+
434
+ ```
435
+ ✅ Done: <output-file-path>
436
+ Estimate: <size> AC count: <N> Total: <elapsed>
437
+ ```
438
+
439
+ Then use AskUserQuestion to offer next actions after showing the summary.
440
+
441
+ English example question: "What would you like to do next?"
442
+ Vietnamese example question: "Bạn muốn làm gì tiếp theo?"
443
+
444
+ Show the summary first (in `lang`):
445
+
446
+ ```
447
+ Story created: <full file path>
448
+
449
+ Title: <title>
450
+ Epic: <epic name> (Silver Tiger) or N/A (standalone)
451
+ Estimate: <size>
452
+ AC count: <N> (happy + edge + error + permission)
453
+
454
+ Notes:
455
+ - Independent? <yes / no — needs <X> first>
456
+ - Estimate >= L → consider splitting
457
+ ```
458
+
459
+ Then use AskUserQuestion:
460
+
461
+ ```json
462
+ {"questions": [{"question": "What would you like to do next?\n(Tiếng Việt: Bạn muốn làm gì tiếp theo?)", "header": "Next step", "multiSelect": false, "options": [{"label": "/compass:story", "description": "Write the next story / Viết story tiếp theo"}, {"label": "/compass:prioritize", "description": "Sort this batch of stories / Sắp xếp thứ tự ưu tiên cho batch stories này"}, {"label": "Done for now", "description": "I'm finished / Tôi đã xong"}]}]}
463
+ ```
464
+
465
+ ## Save session
466
+
467
+ `$PROJECT_ROOT/.compass/.state/sessions/<timestamp>-story-{NNN}/transcript.md`
468
+
469
+ ## Edge cases
470
+
471
+ - **User writes ACs as paragraphs, not Given/When/Then**: convert on their behalf, show the result, ask for confirmation.
472
+ - **Story estimate is XL**: stop and propose 2–4 sub-stories.
473
+ - **ACs contradict each other**: point out the conflict, ask user to resolve.
474
+ - **Story has no clear user role** (internal tool): accept roles like "Admin", "Developer", "System operator".
475
+ - **Epic's user-stories/ folder has stories from different numbering** (e.g. gaps, manual numbering): take max existing number + 1.
476
+ - **PRD has no Epics section** (Silver Tiger): ask user to create an epic first, or write a standalone story linked to the PRD via the `related_prd` frontmatter field.
477
+ - **`config.naming.story` or `config.naming.story_standalone` is present but contains an unrecognized token**: warn the user, fall back to the default pattern, and continue.
@@ -0,0 +1,42 @@
1
+ # Workflow: compass:undo
2
+
3
+ You are the safety net. Mission: restore the previous version of the last modified document.
4
+
5
+ **Principles:** Always show what will be restored before restoring. Never delete the current version — rename it. Confirm with PO before any action.
6
+
7
+ ## Step 0 — Resolve active project
8
+
9
+ Apply the shared snippet from `core/shared/resolve-project.md`. It sets up `$PROJECT_ROOT`, `$CONFIG`, and `$PROJECT_NAME` for downstream steps and prints the "Using: <name>" banner.
10
+
11
+ Extract `lang` from `$CONFIG`.
12
+
13
+ ## Step 1: Find last modified document
14
+ Scan all document folders under `$PROJECT_ROOT`: `prd/`, `epics/`, `research/`, `technical/`, `wiki/`, `.compass/`.
15
+ Find the most recently modified `.md` file (excluding `.v1.md`, `.v2.md`, `.v3.md` backups).
16
+ Also check for `.v1.md`, `.v2.md`, `.v3.md` backup files alongside it.
17
+
18
+ ## Step 2: Show what happened
19
+ Display (in `lang`):
20
+ - Current file: `<path>` (modified `<time>`)
21
+ - Backup available: `<path>.v1.md` (from `<time>`)
22
+
23
+ If no document found → output: "No documents found in tracked folders."
24
+
25
+ ## Step 3: Confirm undo
26
+ AskUserQuestion: "Restore the previous version?"
27
+
28
+ Options:
29
+ - **"Yes — restore backup"** → rename current file to `<path>.v2.md`, rename `<path>.v1.md` to the original filename
30
+ - **"No — keep current"** → do nothing, exit gracefully
31
+ - **"Show diff"** → display a side-by-side or unified diff between current file and backup, then re-ask the question
32
+
33
+ ## Step 4: Confirm result
34
+ After restoring, display (in `lang`):
35
+ - "Restored: `<original-name>` ← was `<path>.v1.md`"
36
+ - "Current version saved as: `<path>.v2.md`"
37
+
38
+ ## Edge cases
39
+ - **No backup exists** → "Nothing to undo — no backup files found for `<path>`"
40
+ - **Multiple backups** → show list of all `.v1.md`, `.v2.md`, `.v3.md` files found; let PO choose which version to restore
41
+ - **Multiple candidates** → if more than one recently-modified file, show top 3 and ask which to undo
42
+ - **Git available** → optionally offer to `git checkout HEAD~1 -- <path>` as an alternative restore method
@@ -0,0 +1,127 @@
1
+ # Workflow: compass:update
2
+
3
+ <!-- update.md does not require project resolve -->
4
+
5
+ You are the update agent. Mission: check for new versions and apply updates safely.
6
+
7
+ **Principles:** Always show what changed before updating. Never update without confirmation. Preserve local modifications.
8
+
9
+ **Purpose**: Update Compass to the latest version from GitHub.
10
+
11
+ **Output**: Status message printed to terminal. No file is created.
12
+
13
+ ---
14
+
15
+ Apply the UX rules from `core/shared/ux-rules.md`. Load `lang` from `.compass/.state/config.json`.
16
+
17
+ > **Additional rule for update**: If `.compass/.state/config.json` is missing, default `lang` to `en`. The update workflow can still run without project config.
18
+
19
+ ---
20
+
21
+ ## Step 0 — Load config & language
22
+
23
+ Read `.compass/.state/config.json`.
24
+ - Extract `lang` (default: `en`).
25
+ - Config missing is OK — update can still run without project config.
26
+
27
+ ---
28
+
29
+ ## Step 1 — Check current version
30
+
31
+ Read `~/.compass/VERSION`.
32
+ - Store as `LOCAL_VERSION`.
33
+ - If the file doesn't exist, treat `LOCAL_VERSION` as `unknown`.
34
+
35
+ ---
36
+
37
+ ## Step 2 — Check for updates
38
+
39
+ Fetch the latest tag from GitHub:
40
+
41
+ ```
42
+ curl -sf "https://api.github.com/repos/mrmandovn/compass/tags"
43
+ ```
44
+
45
+ Extract the first tag name (e.g. `v0.3.0`) using:
46
+
47
+ ```
48
+ python3 -c "import sys,json; tags=json.load(sys.stdin); print(tags[0]['name'] if tags else 'unknown')"
49
+ ```
50
+
51
+ Store as `LATEST_VERSION`.
52
+
53
+ **Edge cases:**
54
+ - No internet / curl fails → show "Could not reach GitHub. Showing local version only." and stop after displaying local version.
55
+ - Response is empty or malformed → treat as "unknown" and warn.
56
+
57
+ ---
58
+
59
+ ## Step 3 — Compare versions
60
+
61
+ - If `LOCAL_VERSION == LATEST_VERSION`: print "✓ Already on latest version (v{LOCAL_VERSION})" and stop.
62
+ - If different: show a summary — current version, latest version.
63
+ - Use AskUserQuestion to confirm update:
64
+ - Option A: "Update now" — proceed to Step 4
65
+ - Option B: "Skip" — exit gracefully
66
+
67
+ ---
68
+
69
+ ## Step 4 — Update
70
+
71
+ Check if `~/.compass` is a git repo:
72
+
73
+ ```
74
+ git -C ~/.compass rev-parse --is-inside-work-tree 2>/dev/null
75
+ ```
76
+
77
+ **If git repo:**
78
+
79
+ ```
80
+ cd ~/.compass && git pull --ff-only origin main
81
+ ```
82
+
83
+ - Show success output.
84
+ - If `git pull` fails with merge conflict → warn: "There are local modifications conflicting with the update. Try: `git stash`, `git pull`, `git stash pop` to resolve."
85
+ - If local modifications detected before pull (`git status --porcelain`): warn the user before proceeding. Use AskUserQuestion to confirm.
86
+
87
+ **If not a git repo (installed via curl):**
88
+
89
+ - Inform the user: "Compass was not installed via git. To get the latest version, re-run the bootstrap:"
90
+ - Print: `curl -fsSL https://raw.githubusercontent.com/mrmandovn/compass/main/bootstrap.sh | bash`
91
+ - Stop here.
92
+
93
+ ---
94
+
95
+ ## Step 5 — Re-install adapters
96
+
97
+ After pulling new code, re-copy adapters to the host so new commands are available:
98
+
99
+ Verify symlinks are intact:
100
+ ```bash
101
+ ls ~/.claude/commands/compass/ 2>/dev/null | wc -l
102
+ ```
103
+ If count doesn't match 21, re-run: `~/.compass/bin/install`.
104
+
105
+ ---
106
+
107
+ ## Step 6 — Verify
108
+
109
+ Read `~/.compass/VERSION` again.
110
+ Print: "✓ Updated to v{NEW_VERSION} (<N> commands)"
111
+
112
+ **IMPORTANT — show this after every successful update:**
113
+
114
+ - en: `"⚠ Close and reopen your AI host to load new commands. Current session only sees commands loaded at startup."`
115
+ - vi: `"⚠ Đóng và mở lại AI host để load commands mới. Session hiện tại chỉ thấy commands đã load lúc khởi động."`
116
+
117
+ ---
118
+
119
+ ## Edge cases summary
120
+
121
+ | Situation | Behavior |
122
+ |---|---|
123
+ | Already on latest | "✓ Already on latest version" — stop |
124
+ | No internet | Show local version, skip update |
125
+ | Not a git repo | Suggest re-running bootstrap.sh |
126
+ | Merge conflict | Warn, show manual resolution steps |
127
+ | Local modifications | Warn before pulling, ask to confirm |