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,524 @@
1
+ # Workflow: compass:init (v1.1.1 smart-detect)
2
+
3
+ You are the onboarding orchestrator. Mission: set up the right thing for the right context. One entry point, 3 modes:
4
+
5
+ - **Mode A** (first-time global): `~/.compass/global-config.json` does NOT exist → run the global preferences wizard, then proceed to Mode B.
6
+ - **Mode B** (project-create): cwd has no `.compass/.state/config.json` → ask to create a new Compass project at cwd, set up Silver Tiger folder structure, register in `~/.compass/projects.json`, set as `last_active`.
7
+ - **Mode C** (config-update): cwd already has `.compass/.state/config.json` → ask which field(s) to update, edit in place.
8
+
9
+ All user-facing text uses `lang` from `~/.compass/global-config.json` if set, else `en`. Apply the UX rules from `core/shared/ux-rules.md` throughout. `compass:init` is the ONE workflow that does NOT include `core/shared/resolve-project.md` at Step 0 — it IS the setup that produces the registry/global-config files the resolver depends on.
10
+
11
+ > **Additional rules for init**:
12
+ > - Before language is chosen (Mode A) OR loaded from global config, default to English. Do not mix languages mid-flow.
13
+ > - Show progress implicitly via cumulative checkmarks (e.g. `✓ Global ✓ Project → Structure...`) — never expose internal step or mode names to the user.
14
+ > - Every invocation starts fresh. If the user dismissed or aborted a previous run of this workflow (in the same conversation), DISCARD all prior answers. Re-detect mode every time.
15
+ > - When the workflow falls through from Mode A → Mode B in the same run, the global wizard's answers serve as defaults for project setup — do not re-ask the same field unless the PO opts to override.
16
+
17
+ ---
18
+
19
+ ## Step 0 — Detect mode (silent)
20
+
21
+ Run BEFORE any output:
22
+
23
+ ```bash
24
+ # Does global config exist?
25
+ if [ ! -f "$HOME/.compass/global-config.json" ]; then
26
+ MODE="A"
27
+ elif [ -f ".compass/.state/config.json" ]; then
28
+ MODE="C"
29
+ else
30
+ MODE="B"
31
+ fi
32
+ ```
33
+
34
+ Then print exactly one banner before proceeding (raw English here — `lang` is not yet known in Mode A; in B/C the global default `lang` is loaded and the banner is rendered in that language — see translations below):
35
+
36
+ | Mode | en banner | vi banner |
37
+ |------|-----------|-----------|
38
+ | A | `👋 First-time setup — configuring global Compass preferences...` | (always en — language not chosen yet) |
39
+ | B | `📦 Creating Compass project at $(pwd)...` | `📦 Đang tạo project Compass tại $(pwd)...` |
40
+ | C | `🔧 Updating Compass config for $(basename $(pwd))...` | `🔧 Đang cập nhật cấu hình Compass cho $(basename $(pwd))...` |
41
+
42
+ For Mode B / Mode C: load `lang` first via `compass-cli project global-config get --key lang` (default `en` if missing), then print the matching banner.
43
+
44
+ After the banner, branch on `$MODE`:
45
+ - `A` → Step 1, then fall through to Step 2.
46
+ - `B` → Step 2.
47
+ - `C` → Step 3.
48
+
49
+ ---
50
+
51
+ ## Step 1 (Mode A only) — Global wizard
52
+
53
+ The aim: capture the PO's defaults once so subsequent project creates pre-fill cleanly. All Mode A text is in English (the language hasn't been chosen yet).
54
+
55
+ ### 1a. Batch the four global questions
56
+
57
+ Use a single `AskUserQuestion` call (`ux-rules` permits 1–4 questions per call). Use this EXACT JSON shape:
58
+
59
+ ```json
60
+ {"questions": [
61
+ {"question": "Which language should Compass speak with you?", "header": "Language", "multiSelect": false, "options": [
62
+ {"label": "Tiếng Việt", "description": "Chat + tài liệu đều tiếng Việt"},
63
+ {"label": "English", "description": "Chat + docs all in English"}
64
+ ]},
65
+ {"question": "What's your default tech stack? (pick all that apply)", "header": "Tech stack", "multiSelect": true, "options": [
66
+ {"label": "typescript", "description": "TypeScript / JavaScript projects"},
67
+ {"label": "python", "description": "Python services / scripts"},
68
+ {"label": "rust", "description": "Rust binaries / libraries"},
69
+ {"label": "go", "description": "Go services"},
70
+ {"label": "java", "description": "Java / Kotlin / JVM"},
71
+ {"label": "None — tôi sẽ chọn per-project", "description": "Skip default; choose stack each time"}
72
+ ]},
73
+ {"question": "Default review style for documents?", "header": "Review style", "multiSelect": false, "options": [
74
+ {"label": "whole_document", "description": "Review the full doc end-to-end in one pass"},
75
+ {"label": "section_by_section", "description": "Walk section by section, confirm each before moving on"}
76
+ ]},
77
+ {"question": "Default product domain?", "header": "Domain", "multiSelect": false, "options": [
78
+ {"label": "ard", "description": "Anti Reverse / Defense"},
79
+ {"label": "platform", "description": "Platform / infra"},
80
+ {"label": "communication", "description": "Communication products"},
81
+ {"label": "internal", "description": "Internal tooling"},
82
+ {"label": "access", "description": "Access / identity"},
83
+ {"label": "ai", "description": "AI products / agents"},
84
+ {"label": "None — ask per-project", "description": "No default; ask every project"}
85
+ ]}
86
+ ]}
87
+ ```
88
+
89
+ ### 1b. Map answers and persist via the CLI
90
+
91
+ - `Tiếng Việt` → `lang=vi`. `English` → `lang=en`.
92
+ - Multi-select tech stack → JSON array (e.g. `["typescript","python"]`). If `None — tôi sẽ chọn per-project` selected, save `[]`.
93
+ - Review style → save the literal label (`whole_document` / `section_by_section`).
94
+ - Domain → save the literal label, or `null` if `None — ask per-project`.
95
+
96
+ ```bash
97
+ compass-cli project global-config set --key lang --value "<lang>"
98
+ compass-cli project global-config set --key default_tech_stack --value '<json-array>'
99
+ compass-cli project global-config set --key default_review_style --value "<style>"
100
+ compass-cli project global-config set --key default_domain --value "<domain-or-null>"
101
+ ```
102
+
103
+ `global-config set` creates `~/.compass/global-config.json` on first write and stamps `created_at` / `updated_at`.
104
+
105
+ ### 1c. Echo summary (in the just-saved `lang`)
106
+
107
+ en:
108
+ ```
109
+ ✓ Global preferences saved to ~/.compass/global-config.json
110
+ Language: <lang>
111
+ Tech stack: <list or "(none)">
112
+ Review style: <style>
113
+ Default domain: <domain or "(ask per-project)">
114
+ ```
115
+
116
+ vi:
117
+ ```
118
+ ✓ Đã lưu cấu hình toàn cục vào ~/.compass/global-config.json
119
+ Ngôn ngữ: <lang>
120
+ Tech stack: <list hoặc "(không có)">
121
+ Kiểu review: <style>
122
+ Domain mặc định: <domain hoặc "(hỏi mỗi project)">
123
+ ```
124
+
125
+ ### 1d. Fall through to Mode B
126
+
127
+ cwd has no project yet — the natural next step is to create one. Print:
128
+
129
+ - en: `→ Now let's set up a project at $(pwd)...`
130
+ - vi: `→ Tiếp theo, tạo project tại $(pwd)...`
131
+
132
+ Continue to Step 2.
133
+
134
+ ---
135
+
136
+ ## Step 2 (Mode B) — Create project at cwd
137
+
138
+ ### 2a. Load global defaults
139
+
140
+ ```bash
141
+ GLOBAL=$(compass-cli project global-config get) # full JSON
142
+ LANG=$(echo "$GLOBAL" | jq -r '.lang // "en"')
143
+ DEF_STACK=$(echo "$GLOBAL" | jq -c '.default_tech_stack // []')
144
+ DEF_REVIEW=$(echo "$GLOBAL" | jq -r '.default_review_style // "whole_document"')
145
+ DEF_DOMAIN=$(echo "$GLOBAL" | jq -r '.default_domain // empty')
146
+ ```
147
+
148
+ From here on, ALL user-facing chat is in `$LANG`.
149
+
150
+ ### 2b. Confirm target path
151
+
152
+ Use AskUserQuestion (pick `lang` version):
153
+
154
+ en:
155
+ ```json
156
+ {"questions": [{"question": "Create Compass project at $(pwd)?", "header": "Target", "multiSelect": false, "options": [
157
+ {"label": "Yes — create here", "description": "Use $(pwd) as the project root"},
158
+ {"label": "No — specify a different path", "description": "I'll point to another absolute path"},
159
+ {"label": "Cancel", "description": "Stop without creating anything"}
160
+ ]}]}
161
+ ```
162
+
163
+ vi:
164
+ ```json
165
+ {"questions": [{"question": "Tạo project Compass tại $(pwd)?", "header": "Đích", "multiSelect": false, "options": [
166
+ {"label": "Có — tạo ở đây", "description": "Dùng $(pwd) làm project root"},
167
+ {"label": "Không — chọn đường dẫn khác", "description": "Tôi sẽ trỏ tới một absolute path khác"},
168
+ {"label": "Huỷ", "description": "Dừng, không tạo gì"}
169
+ ]}]}
170
+ ```
171
+
172
+ Branch:
173
+ - `Yes / Có` → `TARGET="$(pwd)"`.
174
+ - `No / Không` → ask for the absolute path (use `Type your own answer`), resolve it, set `TARGET=<absolute>`. Validate that the directory exists and is writable; if not, abort with a clear error.
175
+ - `Cancel / Huỷ` → stop cleanly. Print: en `Stopped — no changes made.` / vi `Đã dừng — không thay đổi gì.`
176
+
177
+ ### 2c. Project-specific questions (batched)
178
+
179
+ Detect smart defaults BEFORE asking:
180
+
181
+ ```bash
182
+ DETECTED_NAME=$(basename "$TARGET") # folder name
183
+ DETECTED_USER=$(git config user.name 2>/dev/null || echo "$USER")
184
+ # Prefix: uppercase first letter of each dash-separated word, 2-5 chars
185
+ DETECTED_PREFIX=$(echo "$DETECTED_NAME" | awk -F- '{for(i=1;i<=NF;i++) printf "%s", toupper(substr($i,1,1))}' | cut -c1-5)
186
+ ```
187
+
188
+ Decide whether to ask the domain question:
189
+ - If `$DEF_DOMAIN` is non-empty → DO NOT ask domain. Use the global default.
190
+ - If `$DEF_DOMAIN` is empty → include the 6-domain question in the batch.
191
+
192
+ Send 3 or 4 questions in one AskUserQuestion call. Example with all 4 (domain included):
193
+
194
+ en:
195
+ ```json
196
+ {"questions": [
197
+ {"question": "Project name?", "header": "Project", "multiSelect": false, "options": [
198
+ {"label": "<DETECTED_NAME>", "description": "From folder name"},
199
+ {"label": "<title-cased DETECTED_NAME>", "description": "Title-cased variant"}
200
+ ]},
201
+ {"question": "Who's the PO?", "header": "PO", "multiSelect": false, "options": [
202
+ {"label": "@<DETECTED_USER>", "description": "From git config / $USER"},
203
+ {"label": "@me", "description": "Self-assign for now, change later"}
204
+ ]},
205
+ {"question": "Issue prefix? (2–5 uppercase letters)", "header": "Prefix", "multiSelect": false, "options": [
206
+ {"label": "<DETECTED_PREFIX>", "description": "Derived from project name"},
207
+ {"label": "<DETECTED_PREFIX[0:3]>", "description": "Shorter variant"}
208
+ ]},
209
+ {"question": "Product domain?", "header": "Domain", "multiSelect": false, "options": [
210
+ {"label": "ard", "description": "Anti Reverse / Defense"},
211
+ {"label": "platform", "description": "Platform / infra"},
212
+ {"label": "communication", "description": "Communication products"},
213
+ {"label": "internal", "description": "Internal tooling"},
214
+ {"label": "access", "description": "Access / identity"},
215
+ {"label": "ai", "description": "AI products / agents"}
216
+ ]}
217
+ ]}
218
+ ```
219
+
220
+ vi (same shape, translated):
221
+ ```json
222
+ {"questions": [
223
+ {"question": "Tên project?", "header": "Project", "multiSelect": false, "options": [
224
+ {"label": "<DETECTED_NAME>", "description": "Từ tên thư mục"},
225
+ {"label": "<title-cased DETECTED_NAME>", "description": "Biến thể title-case"}
226
+ ]},
227
+ {"question": "PO phụ trách?", "header": "PO", "multiSelect": false, "options": [
228
+ {"label": "@<DETECTED_USER>", "description": "Từ git config / $USER"},
229
+ {"label": "@me", "description": "Tự assign tạm, đổi sau"}
230
+ ]},
231
+ {"question": "Prefix ticket? (2–5 chữ cái viết hoa)", "header": "Prefix", "multiSelect": false, "options": [
232
+ {"label": "<DETECTED_PREFIX>", "description": "Suy ra từ tên project"},
233
+ {"label": "<DETECTED_PREFIX[0:3]>", "description": "Biến thể ngắn hơn"}
234
+ ]},
235
+ {"question": "Domain sản phẩm?", "header": "Domain", "multiSelect": false, "options": [
236
+ {"label": "ard", "description": "Anti Reverse / Defense"},
237
+ {"label": "platform", "description": "Platform / infra"},
238
+ {"label": "communication", "description": "Sản phẩm communication"},
239
+ {"label": "internal", "description": "Tooling nội bộ"},
240
+ {"label": "access", "description": "Access / identity"},
241
+ {"label": "ai", "description": "AI products / agents"}
242
+ ]}
243
+ ]}
244
+ ```
245
+
246
+ **IMPORTANT:** Replace every `<placeholder>` with actual detected values BEFORE calling AskUserQuestion. The "Type your own answer" affordance handles free-text overrides — never use empty `Other` options.
247
+
248
+ ### 2d. Create folder structure
249
+
250
+ ```bash
251
+ mkdir -p "$TARGET/prd" \
252
+ "$TARGET/epics" \
253
+ "$TARGET/wiki" \
254
+ "$TARGET/prototype" \
255
+ "$TARGET/technical" \
256
+ "$TARGET/release-notes" \
257
+ "$TARGET/research" \
258
+ "$TARGET/.compass/.state/sessions"
259
+ ```
260
+
261
+ ### 2e. Write `.compass/.state/config.json`
262
+
263
+ Merge global defaults + project-specific answers. Version = `"1.1.1"`. Schema:
264
+
265
+ ```json
266
+ {
267
+ "version": "1.1.1",
268
+ "lang": "<from global>",
269
+ "spec_lang": "<from global, default same as lang>",
270
+ "project": {
271
+ "name": "<from 2c>",
272
+ "po": "@<from 2c>",
273
+ "prefix": "<from 2c>",
274
+ "domain": "<from 2c or global default>"
275
+ },
276
+ "tech_stack": <global default_tech_stack array>,
277
+ "review_style": "<global default_review_style>",
278
+ "mode": "silver-tiger",
279
+ "created_at": "<ISO-8601 now>"
280
+ }
281
+ ```
282
+
283
+ Write atomically:
284
+
285
+ ```bash
286
+ cat > "$TARGET/.compass/.state/config.json" <<JSON
287
+ { ... merged JSON above ... }
288
+ JSON
289
+ ```
290
+
291
+ ### 2f. Write Silver Tiger CLAUDE.md
292
+
293
+ `$TARGET/CLAUDE.md` — header block matches the Silver Tiger v1.1 convention so domain rules are reachable from any Claude Code session:
294
+
295
+ ```markdown
296
+ # Claude Context — <project-name>
297
+
298
+ <!-- Domain rules: /product-owner/shared/domain-rules/<domain>.md -->
299
+
300
+ - product: <project-name>
301
+ - domain: <domain>
302
+ - po: <po>
303
+ - <domain>_po_lead: <po>
304
+
305
+ ## <Project Name> – Product Description
306
+
307
+ <1–2 paragraphs describing what this product does, who it's for, and what makes it different. To be filled by the PO after init.>
308
+
309
+ ## Core Concept
310
+
311
+ <Key concept / differentiator, 3–6 bullets. To be filled by the PO after init.>
312
+
313
+ ## Architecture
314
+
315
+ <Key technical decisions, stack, constraints. To be filled as the product evolves.>
316
+
317
+ ## Epic Map
318
+
319
+ | ID | Name | Priority | Status |
320
+ |----|------|----------|--------|
321
+ | | | | |
322
+
323
+ ## Team
324
+
325
+ | Role | Person |
326
+ |------|--------|
327
+ | PO | <po> |
328
+
329
+ ## Document Structure
330
+
331
+ - `prd/` — PRDs (<PREFIX>-YYYY-MM-DD-slug.md)
332
+ - `epics/` — Epics + User Stories
333
+ - `research/` — Ideas, Backlog, Research
334
+ - `wiki/` — Product overview, glossary, features
335
+ - `prototype/` — UI prototypes
336
+ - `release-notes/` — Release notes
337
+ - `technical/` — Technical specs
338
+ ```
339
+
340
+ If `domain` is null → omit the `<!-- Domain rules: ... -->` comment AND the `domain` / `<domain>_po_lead` bullets. Keep `product` + `po`.
341
+
342
+ **Do NOT list Compass commands in CLAUDE.md.** Adapter files load them automatically.
343
+
344
+ ### 2g. Write `domain.yaml`
345
+
346
+ ```yaml
347
+ domain: <from config or "general">
348
+ product: <project-name>
349
+ po: "<po>"
350
+ po_lead: "<po>"
351
+ keywords:
352
+ - <project-name>
353
+ - <2–3 keywords inferred from name / folder>
354
+ related_domains: []
355
+ ```
356
+
357
+ ### 2h. Write `README.md` stub (only if not present)
358
+
359
+ ```markdown
360
+ # <Project Name>
361
+
362
+ <One-line description — to be filled>
363
+
364
+ - **PO:** <po>
365
+ - **Domain:** <domain>
366
+ - **Prefix:** <PREFIX>
367
+
368
+ ## Document Structure
369
+
370
+ ```
371
+ <project>/
372
+ ├── prd/ PRDs (<PREFIX>-YYYY-MM-DD-slug.md)
373
+ ├── epics/ Epics + User Stories
374
+ ├── research/ Ideas, Backlog, Research
375
+ ├── prototype/ Prototypes
376
+ ├── release-notes/ Release notes
377
+ ├── technical/ Technical specs
378
+ ├── wiki/ Product overview, glossary, features
379
+ └── .compass/.state/ Compass config + sessions
380
+ ```
381
+ ```
382
+
383
+ ### 2i. Register in `~/.compass/projects.json`
384
+
385
+ ```bash
386
+ compass-cli project add "$TARGET" # idempotent
387
+ compass-cli project use "$TARGET" # set last_active + touch last_used
388
+ ```
389
+
390
+ If either CLI call fails, surface the error to the user — never silently swallow. Project files are already on disk; the failure mode is "registered? no — fix and retry `compass-cli project add`".
391
+
392
+ ### 2j. Success summary
393
+
394
+ en:
395
+ ```
396
+ ✓ Compass project ready.
397
+ Name: <project-name>
398
+ Path: <TARGET>
399
+ PO: <po>
400
+ Prefix: <PREFIX>
401
+ Domain: <domain or "(none)">
402
+ Active: yes (set as last_active)
403
+ ```
404
+
405
+ vi:
406
+ ```
407
+ ✓ Project Compass đã sẵn sàng.
408
+ Tên: <project-name>
409
+ Đường dẫn: <TARGET>
410
+ PO: <po>
411
+ Prefix: <PREFIX>
412
+ Domain: <domain hoặc "(không có)">
413
+ Active: có (đặt làm last_active)
414
+ ```
415
+
416
+ Continue to the Final hand-off block.
417
+
418
+ ---
419
+
420
+ ## Step 3 (Mode C) — Update config in place
421
+
422
+ ### 3a. Load current config
423
+
424
+ ```bash
425
+ CONFIG_PATH=".compass/.state/config.json"
426
+ CONFIG=$(cat "$CONFIG_PATH")
427
+ LANG=$(echo "$CONFIG" | jq -r '.lang // "en"')
428
+ ```
429
+
430
+ All Mode C user-facing chat uses this `$LANG`.
431
+
432
+ ### 3b. Pick fields to update
433
+
434
+ Use AskUserQuestion (multi-select). Build options dynamically from the keys actually present in the config — typical set: `lang`, `spec_lang`, `prefix` (under `project.prefix`), `domain` (under `project.domain`), `po` (under `project.po`). Always add a `Cancel — no changes` escape hatch.
435
+
436
+ en:
437
+ ```json
438
+ {"questions": [{"question": "Which fields would you like to update?", "header": "Update", "multiSelect": true, "options": [
439
+ {"label": "lang", "description": "UI/chat language (current: <lang>)"},
440
+ {"label": "spec_lang", "description": "Document/spec language (current: <spec_lang>)"},
441
+ {"label": "prefix", "description": "Issue prefix (current: <prefix>)"},
442
+ {"label": "domain", "description": "Product domain (current: <domain>)"},
443
+ {"label": "po", "description": "Product Owner handle (current: <po>)"},
444
+ {"label": "Cancel — no changes", "description": "Exit without modifying anything"}
445
+ ]}]}
446
+ ```
447
+
448
+ vi:
449
+ ```json
450
+ {"questions": [{"question": "Bạn muốn cập nhật trường nào?", "header": "Update", "multiSelect": true, "options": [
451
+ {"label": "lang", "description": "Ngôn ngữ chat/UI (hiện tại: <lang>)"},
452
+ {"label": "spec_lang", "description": "Ngôn ngữ tài liệu/spec (hiện tại: <spec_lang>)"},
453
+ {"label": "prefix", "description": "Prefix ticket (hiện tại: <prefix>)"},
454
+ {"label": "domain", "description": "Domain sản phẩm (hiện tại: <domain>)"},
455
+ {"label": "po", "description": "Handle PO (hiện tại: <po>)"},
456
+ {"label": "Huỷ — không đổi gì", "description": "Thoát, không cập nhật"}
457
+ ]}]}
458
+ ```
459
+
460
+ If the user picks `Cancel / Huỷ`, stop immediately — print en `No changes made.` / vi `Không có thay đổi.`
461
+
462
+ ### 3c. Ask new value for each picked field
463
+
464
+ For every selected field, send ONE AskUserQuestion with smart defaults — current value as the first option:
465
+
466
+ - `lang` / `spec_lang` → 2 options: `Tiếng Việt` / `English`.
467
+ - `prefix` → 2 options: current prefix, plus a Type-your-own affordance (the user almost certainly wants free text here).
468
+ - `domain` → the 6-domain enum (same list as Mode B).
469
+ - `po` → 2 options: current value, plus `@<git config user.name or $USER>`.
470
+
471
+ Across multiple selected fields, batch in a SINGLE AskUserQuestion call (max 4 fields per call — if the PO somehow picked >4, split into two calls).
472
+
473
+ ### 3d. Write back
474
+
475
+ Load the full existing config, overlay only the picked keys (preserve every untouched field, including `version`, `created_at`, nested objects). Write back atomically:
476
+
477
+ ```bash
478
+ TMP=$(mktemp)
479
+ echo "$NEW_CONFIG" | jq '.' > "$TMP" && mv "$TMP" "$CONFIG_PATH"
480
+ ```
481
+
482
+ If `lang` changed, also touch `~/.compass/projects.json` so the next session sees the latest:
483
+
484
+ ```bash
485
+ compass-cli project use "$(pwd)" # idempotent — refreshes last_used
486
+ ```
487
+
488
+ ### 3e. Summary of changes
489
+
490
+ en:
491
+ ```
492
+ ✓ Config updated.
493
+ <field-1>: <old> → <new>
494
+ <field-2>: <old> → <new>
495
+ ```
496
+
497
+ vi:
498
+ ```
499
+ ✓ Đã cập nhật cấu hình.
500
+ <field-1>: <old> → <new>
501
+ <field-2>: <old> → <new>
502
+ ```
503
+
504
+ ---
505
+
506
+ ## Final — Hand off
507
+
508
+ After Mode B success or Mode C summary (Mode A always falls through to B and exits via B's hand-off), print:
509
+
510
+ en:
511
+ ```
512
+ ✓ Compass ready.
513
+ Active project: <name> (<path>)
514
+ Next: /compass:brief <task> or /compass:prd
515
+ ```
516
+
517
+ vi:
518
+ ```
519
+ ✓ Compass đã sẵn sàng.
520
+ Project active: <name> (<path>)
521
+ Tiếp theo: /compass:brief <task> hoặc /compass:prd
522
+ ```
523
+
524
+ Stop. Do NOT auto-invoke any other workflow.
@@ -0,0 +1,136 @@
1
+ # Workflow: compass:migrate
2
+
3
+ You are the migrate agent. Mission: migrate a project's `.compass/.state/` layout from Compass v0.x to v1.0 safely and idempotently.
4
+
5
+ **Principles:** Idempotent (safe to re-run). Back up before rewriting. Never destroy user data — on any unclear state, stop and surface the issue.
6
+
7
+ **Purpose**: Promote a legacy `.compass/.state/` layout (v0.x) to the v1.0 shape, creating `project-memory.json` and reorganizing sessions so subsequent commands work without surprises.
8
+
9
+ **Output**: A summary printed to the terminal. No documents are produced.
10
+
11
+ ---
12
+
13
+ Apply the UX rules from `core/shared/ux-rules.md`.
14
+
15
+ > **Additional rule for migrate**: Migrate pre-dates the project registry, so if `resolve-project` returns `status=none` (or the config is missing), fall back to operating at `cwd` and proceed. Default `lang` to `en` when no config is available.
16
+
17
+ ---
18
+
19
+ ## Step 0 — Resolve active project
20
+
21
+ 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.
22
+
23
+ **Migrate-specific `status=none` handler**: if the registry is empty OR no `$PROJECT_ROOT` can be resolved (pre-registry layouts), skip the ambiguous/none prompts from the shared snippet and continue with `$PROJECT_ROOT="$(pwd)"`. The migration CLI is designed to bootstrap legacy projects, so this graceful fallback is expected.
24
+
25
+ Extract `lang` from `$CONFIG` (default: `en`). Config missing is OK — migrate does not require it.
26
+
27
+ ---
28
+
29
+ ## Step 1 — Run migration
30
+
31
+ Call the CLI against the resolved project root (falls back to `cwd` per Step 0):
32
+
33
+ ```bash
34
+ compass-cli migrate "$PROJECT_ROOT"
35
+ ```
36
+
37
+ The CLI:
38
+ - Detects whether `.compass/.state/` is already v1.0 (no-op in that case).
39
+ - Writes backups into `$PROJECT_ROOT/.compass/.state/.backup-<ISO>/` before rewriting any file.
40
+ - Creates `$PROJECT_ROOT/.compass/.state/project-memory.json` if it doesn't exist.
41
+ - Promotes legacy session files into the v1.0 layout.
42
+ - Prints a JSON object on stdout summarizing what happened.
43
+
44
+ **Edge cases:**
45
+ - `compass-cli` not on PATH → show: `"⚠ compass-cli not found. Re-run ~/.compass/bin/install and try again."` Stop.
46
+ - Exit code ≠ 0 → read stderr, surface the first meaningful line, and stop. Do NOT retry blindly.
47
+ - Stdout is not valid JSON → show the raw output as-is and stop.
48
+
49
+ ---
50
+
51
+ ## Step 2 — Parse JSON result
52
+
53
+ Expected keys (fields may be added over time — ignore unknown keys):
54
+
55
+ - `already_v1` — boolean. True when nothing needed to change.
56
+ - `sessions_migrated` — integer count of session directories promoted.
57
+ - `backups_written` — integer count of backup files created.
58
+ - `project_memory` — one of `"created"` | `"exists"` | `"skipped"`.
59
+ - `errors` — array of `{ file, message }` objects. Empty array = success.
60
+
61
+ Parse with `jq` or `python3 -c "import json,sys; ..."`. If parsing fails, treat as a hard error (Step 1 edge case).
62
+
63
+ ---
64
+
65
+ ## Step 3 — Display summary
66
+
67
+ Pick the version matching `lang`.
68
+
69
+ **If `already_v1 = true`:**
70
+ - en: `"✓ Already on v1.0 state layout — nothing to migrate."`
71
+ - vi: `"✓ Đã ở layout v1.0 — không cần migrate."`
72
+
73
+ **If migration ran (no errors):**
74
+
75
+ English:
76
+ ```
77
+ ✓ Migrated to v1.0 state layout.
78
+
79
+ Sessions migrated: <sessions_migrated>
80
+ Backups written: <backups_written> → $PROJECT_ROOT/.compass/.state/.backup-<ISO>/
81
+ project-memory.json: <project_memory> ("created" or "exists")
82
+
83
+ Safe to re-run anytime — migrate is idempotent.
84
+ ```
85
+
86
+ Vietnamese:
87
+ ```
88
+ ✓ Đã migrate sang layout v1.0.
89
+
90
+ Session đã chuyển: <sessions_migrated>
91
+ Backup đã tạo: <backups_written> → $PROJECT_ROOT/.compass/.state/.backup-<ISO>/
92
+ project-memory.json: <project_memory> ("created" hoặc "exists")
93
+
94
+ Chạy lại lúc nào cũng an toàn — migrate là idempotent.
95
+ ```
96
+
97
+ ---
98
+
99
+ ## Step 4 — Handle errors (if any)
100
+
101
+ If `errors` is non-empty, list each entry and give an actionable next step. Do NOT pretend success.
102
+
103
+ - en:
104
+ ```
105
+ ⚠ Migration completed with <N> issue(s):
106
+
107
+ • <file>: <message>
108
+
109
+ Your original files are preserved in $PROJECT_ROOT/.compass/.state/.backup-<ISO>/.
110
+ Fix the issue above and re-run: /compass:migrate
111
+ ```
112
+
113
+ - vi:
114
+ ```
115
+ ⚠ Migrate xong nhưng có <N> lỗi:
116
+
117
+ • <file>: <message>
118
+
119
+ File gốc vẫn giữ trong $PROJECT_ROOT/.compass/.state/.backup-<ISO>/.
120
+ Sửa lỗi ở trên rồi chạy lại: /compass:migrate
121
+ ```
122
+
123
+ Exit code is still 0 for partial success — the user decides whether to re-run.
124
+
125
+ ---
126
+
127
+ ## Edge cases summary
128
+
129
+ | Situation | Behavior |
130
+ |---|---|
131
+ | No `$PROJECT_ROOT/.compass/` folder | CLI returns `{"already_v1": false, "sessions_migrated": 0, "project_memory": "skipped"}` — tell user to run `/compass:init` first |
132
+ | Already v1.0 | "Already on v1.0 state layout" — stop |
133
+ | `compass-cli` not installed | Point to `~/.compass/bin/install` |
134
+ | Non-zero exit | Surface stderr, do NOT retry |
135
+ | Invalid JSON on stdout | Show raw output, do NOT retry |
136
+ | Partial errors | List each one, point to the backup path |