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.
- package/README.md +105 -0
- package/VERSION +1 -0
- package/bin/install +174 -0
- package/bootstrap.sh +95 -0
- package/cli/Cargo.lock +270 -0
- package/cli/Cargo.toml +24 -0
- package/cli/src/cmd/context.rs +59 -0
- package/cli/src/cmd/dag.rs +133 -0
- package/cli/src/cmd/git.rs +148 -0
- package/cli/src/cmd/hook.rs +51 -0
- package/cli/src/cmd/index.rs +363 -0
- package/cli/src/cmd/manifest.rs +34 -0
- package/cli/src/cmd/memory.rs +680 -0
- package/cli/src/cmd/migrate.rs +790 -0
- package/cli/src/cmd/mod.rs +14 -0
- package/cli/src/cmd/progress.rs +107 -0
- package/cli/src/cmd/project.rs +1700 -0
- package/cli/src/cmd/session.rs +64 -0
- package/cli/src/cmd/state.rs +317 -0
- package/cli/src/cmd/validate/mod.rs +506 -0
- package/cli/src/cmd/validate/prd.rs +472 -0
- package/cli/src/cmd/version.rs +89 -0
- package/cli/src/helpers.rs +40 -0
- package/cli/src/main.rs +75 -0
- package/cli/tests/fixtures/plan_empty_pointers.json +60 -0
- package/cli/tests/fixtures/plan_missing_pointers.json +59 -0
- package/cli/tests/fixtures/plan_too_many_pointers.json +92 -0
- package/cli/tests/fixtures/plan_v1_valid.json +64 -0
- package/cli/tests/fixtures/prd_bad_flow_bullet.md +37 -0
- package/cli/tests/fixtures/prd_bad_flow_prose.md +33 -0
- package/cli/tests/fixtures/prd_good_flow.md +41 -0
- package/cli/tests/fixtures/prd_xref_dangling.md +38 -0
- package/cli/tests/fixtures/prd_xref_valid.md +53 -0
- package/cli/tests/fixtures/projects/proj_a/.compass/.state/config.json +12 -0
- package/cli/tests/fixtures/projects/proj_b/.compass/.state/config.json +12 -0
- package/cli/tests/fixtures/projects/proj_c/.compass/.state/config.json +12 -0
- package/cli/tests/fixtures/registry/all_dead.json +18 -0
- package/cli/tests/fixtures/registry/corrupt.json +1 -0
- package/cli/tests/fixtures/registry/empty.json +1 -0
- package/cli/tests/fixtures/registry/last_active_dead.json +24 -0
- package/cli/tests/fixtures/registry/multi_alive.json +24 -0
- package/cli/tests/fixtures/registry/one_alive.json +12 -0
- package/cli/tests/fixtures/v0_project/.compass/.state/config.json +5 -0
- package/cli/tests/fixtures/v0_project/.compass/.state/sessions/onboarding-redesign/plan.json +29 -0
- package/cli/tests/fixtures/v0_project/.compass/.state/sessions/sample-feature/context.json +11 -0
- package/cli/tests/fixtures/v0_project/.compass/.state/sessions/sample-feature/plan.json +49 -0
- package/core/colleagues/base-rules.md +112 -0
- package/core/colleagues/manifest.json +85 -0
- package/core/colleagues/market-analyst.md +50 -0
- package/core/colleagues/prioritizer.md +53 -0
- package/core/colleagues/researcher.md +54 -0
- package/core/colleagues/reviewer.md +55 -0
- package/core/colleagues/stakeholder-comm.md +59 -0
- package/core/colleagues/story-breaker.md +57 -0
- package/core/colleagues/ux-reviewer.md +54 -0
- package/core/colleagues/writer.md +55 -0
- package/core/commands/compass/brief.md +28 -0
- package/core/commands/compass/check.md +27 -0
- package/core/commands/compass/epic.md +32 -0
- package/core/commands/compass/feedback.md +32 -0
- package/core/commands/compass/help.md +24 -0
- package/core/commands/compass/ideate.md +32 -0
- package/core/commands/compass/init.md +30 -0
- package/core/commands/compass/plan.md +27 -0
- package/core/commands/compass/prd.md +39 -0
- package/core/commands/compass/prioritize.md +36 -0
- package/core/commands/compass/prototype.md +28 -0
- package/core/commands/compass/release.md +32 -0
- package/core/commands/compass/research.md +31 -0
- package/core/commands/compass/roadmap.md +32 -0
- package/core/commands/compass/run.md +28 -0
- package/core/commands/compass/setup.md +32 -0
- package/core/commands/compass/sprint.md +32 -0
- package/core/commands/compass/status.md +32 -0
- package/core/commands/compass/story.md +37 -0
- package/core/commands/compass/undo.md +33 -0
- package/core/commands/compass/update.md +29 -0
- package/core/hooks/context-monitor.sh +5 -0
- package/core/hooks/manifest-tracker.sh +62 -0
- package/core/hooks/statusline.sh +12 -0
- package/core/hooks/update-checker.sh +24 -0
- package/core/integrations/confluence.md +267 -0
- package/core/integrations/figma.md +277 -0
- package/core/integrations/jira.md +436 -0
- package/core/integrations/vercel.md +170 -0
- package/core/manifest.json +172 -0
- package/core/shared/SCHEMAS-v1.md +404 -0
- package/core/shared/progress.md +145 -0
- package/core/shared/project-scan.md +293 -0
- package/core/shared/resolve-project.md +136 -0
- package/core/shared/ux-rules.md +52 -0
- package/core/shared/version-backup.md +38 -0
- package/core/templates/prd-template.md +145 -0
- package/core/templates/story-template.md +99 -0
- package/core/workflows/brief.md +184 -0
- package/core/workflows/check.md +436 -0
- package/core/workflows/epic.md +177 -0
- package/core/workflows/feedback.md +164 -0
- package/core/workflows/help.md +79 -0
- package/core/workflows/ideate.md +320 -0
- package/core/workflows/init.md +524 -0
- package/core/workflows/migrate.md +136 -0
- package/core/workflows/plan.md +320 -0
- package/core/workflows/prd.md +632 -0
- package/core/workflows/prioritize.md +301 -0
- package/core/workflows/project.md +177 -0
- package/core/workflows/prototype.md +174 -0
- package/core/workflows/release.md +179 -0
- package/core/workflows/research.md +613 -0
- package/core/workflows/roadmap.md +152 -0
- package/core/workflows/run.md +367 -0
- package/core/workflows/setup.md +294 -0
- package/core/workflows/sprint.md +187 -0
- package/core/workflows/status.md +185 -0
- package/core/workflows/story.md +477 -0
- package/core/workflows/undo.md +42 -0
- package/core/workflows/update.md +127 -0
- 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 |
|