@haposoft/cafekit 0.11.10 → 0.11.11

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haposoft/cafekit",
3
- "version": "0.11.10",
3
+ "version": "0.11.11",
4
4
  "description": "Claude Code-first spec-driven workflow for AI coding assistants. Bundles CafeKit hapo: skills, runtime hooks, agents, and installer scaffolding.",
5
5
  "author": "Haposoft <nghialt@haposoft.com>",
6
6
  "license": "MIT",
@@ -116,7 +116,7 @@ Consult these when the task touches the relevant area:
116
116
 
117
117
  ## Language Consistency
118
118
 
119
- When generating specs or structured project output, use the user's preferred language consistently across the whole spec workspace. Technical terms, code samples, and file paths may remain English.
119
+ Spec artifacts (`spec.json`, `requirements.md`, `research.md`, `design.md`, `tasks/*.md`) are **canonical in English** regardless of the session's response language. When the configured language is not English, `hapo:specs` may additionally generate a reference-only translation mirror under `specs/<feature>/i18n/<lang>/`. Chat replies and other non-spec output still follow the user's preferred language. Technical terms, code samples, and file paths stay English.
120
120
 
121
121
  ## Communication
122
122
 
@@ -71,7 +71,7 @@ Enabled by default for all develop modes. Disable only with `--no-notes`.
71
71
 
72
72
  <HARD-GATE>
73
73
  DO NOT write implementation code until an approved spec exists.
74
- - If the directory `specs/<feature-name>` DOES NOT EXIST or `spec.json` is not ready, automatically trigger `/hapo:specs <feature-name>` first to create the specification. Do not improvise.
74
+ - If the directory `specs/<feature-name>` DOES NOT EXIST or `spec.json` is not ready, automatically trigger `/hapo:specs <feature-name> --auto` first to create the specification end-to-end (non-interactive). Do not improvise.
75
75
  </HARD-GATE>
76
76
 
77
77
  <DEFINITION-OF-DONE>
@@ -5,7 +5,7 @@ user-invocable: true
5
5
  when_to_use: "Invoke to turn a vague idea into an actionable, gated specification."
6
6
  category: utilities
7
7
  keywords: [specs, requirements, design, tasks]
8
- argument-hint: "<feature-description> | status | resume | --validate | archive"
8
+ argument-hint: "[<feature-description>] [--auto] | --status | --validate <feature> | --archive"
9
9
  metadata:
10
10
  author: haposoft
11
11
  version: "2.0.0"
@@ -22,6 +22,8 @@ This skill provides a 10-step workflow to transform ideas into evidence-backed s
22
22
  Analyze → Dependency Scan → Complexity Assessment → Init → Evidence Gate + Requirements → Design → Tasks → Hydration → Review → Completion
23
23
  ```
24
24
 
25
+ An entry/dispatch layer sits in front of the pipeline: four flags (`--auto`, `--validate`, `--status`, `--archive`) plus **Interactive State Discovery** (the no-flag path) decide *which part of the pipeline to run and where to stop* — see **Default Behavior**. The pipeline itself is unchanged regardless of how it is invoked.
26
+
25
27
  **CRITICAL:** Before starting, the system MUST:
26
28
  1. Scan `specs/` directory for incomplete specs
27
29
  2. If any spec is `in_progress` (accept legacy `in-progress` when reading) → ask user whether to continue or create new
@@ -39,7 +41,7 @@ Analyze → Dependency Scan → Complexity Assessment → Init → Evidence Gate
39
41
  - Each phase (Init → Requirements → Design → Tasks) must complete before the next begins
40
42
  - No skipping — don't write design without requirements
41
43
  - Exception: simple tasks may merge requirements + design into one step
42
- - A normal `/hapo:specs <feature-description>` run is an end-to-end spec creation workflow. Do not stop after Init unless the user explicitly asks for init-only behavior.
44
+ - A `/hapo:specs <feature-description>` run defaults to **Interactive State Discovery**: it asks the Creation Mode (Auto / Stop after Design / Step by step) before running. `--auto` runs the full pipeline end-to-end without asking. Either way, phases never skip — each completes before the next begins, and Init is never a stop point.
43
45
 
44
46
  ### Scope Rules
45
47
  - Respect `scope_lock` absolutely once user has confirmed
@@ -54,6 +56,10 @@ Analyze → Dependency Scan → Complexity Assessment → Init → Evidence Gate
54
56
  - `ready_for_implementation` is a hard gate, not a convenience flag. Never set it before the finalization audit passes.
55
57
  - Non-trivial specs MUST have an evidence trail in `research.md` before requirements, design, or tasks are finalized. Evidence can be codebase scout findings, external/current research, or an explicit skip rationale.
56
58
 
59
+ ### Language & Canonical Rules
60
+ - **English is the canonical language for every spec artifact** (`spec.json`, `requirements.md`, `research.md`, `design.md`, `tasks/*.md`) — write them in English regardless of the session's response language.
61
+ - If the configured language (`.claude/settings.json` → `language`) is not English, you MAY additionally generate a **reference-only translation mirror** under `i18n/<lang>/`. See `references/translation-mirror.md`. The mirror never replaces canonical and is never a source of truth.
62
+
57
63
  ### Output Criteria
58
64
  - Never implement code — only create spec documents
59
65
  - Return file paths and a brief summary
@@ -96,37 +102,62 @@ Forbidden generated artifacts:
96
102
 
97
103
  ## Default Behavior
98
104
 
99
- ### When called WITHOUT arguments
100
-
101
- Display selection menu via `AskUserQuestion`:
102
-
103
- ```json
104
- {
105
- "questions": [{
106
- "question": "What would you like to do?",
107
- "header": "Specs",
108
- "options": [
109
- { "label": "Create new spec", "description": "Initialize spec from a feature description" },
110
- { "label": "status", "description": "View status of all specs in specs/" },
111
- { "label": "resume", "description": "Continue an active spec" },
112
- { "label": "--validate", "description": "Review spec (auto-decides: red team or validation)" },
113
- { "label": "archive", "description": "Archive completed specs + write journal" }
114
- ],
115
- "multiSelect": false
116
- }]
117
- }
118
- ```
105
+ > **This section is the entry/dispatch layer ONLY.** It decides *which part of the pipeline to run and where to stop*. It does NOT change any pipeline step, the validator, templates, or rules. The detailed Steps 1–10 below are unchanged.
106
+
107
+ `hapo:specs` exposes exactly **four flags**: `--auto`, `--validate`, `--status`, `--archive`. Everything else (which spec, new vs continue, how far to run) is resolved by **Interactive State Discovery**, never by extra flags.
108
+
109
+ **Back-compat aliases** (accepted silently, not advertised): bare `status` / `archive` / `resume`, and `--validate` as today. Treat them as their `--flag` equivalents.
110
+
111
+ ### Dispatch order
112
+
113
+ 1. `--status` (or bare `status`) → run the status report (see **Subcommands**), then stop.
114
+ 2. `--validate <feature>` → jump to **Step 9** (the `--validate` rules below are unchanged).
115
+ 3. `--archive` (or bare `archive`) → run the archive workflow, then stop.
116
+ 4. `--auto` → **non-interactive run**. If the argument matches an unfinished spec → resume it from `current_phase` and finish to Tasks. Otherwise create new and run the full pipeline (Step 1→10) end-to-end. Either way: auto-approve and skip the Creation Mode question; if a new description is missing, ask only for it; the hard safety gates still apply.
117
+ 5. Otherwise (`/hapo:specs` or `/hapo:specs "<description>"`) → **Interactive State Discovery**.
118
+
119
+ ### Interactive State Discovery (no-flag path)
120
+
121
+ Goal: ask the user enough to determine **state** and **intent**, then run the existing pipeline. This only chooses *what to run and where to stop* — it does not alter any step's logic.
122
+
123
+ 1. **Detect state.** Scan `specs/` for unfinished specs (`status=in_progress` / `ready_for_implementation=false`) and git-branch match.
124
+ - Found → `AskUserQuestion`: `Continue <spec A> · Continue <spec B> · Create new spec`.
125
+ - None → default to create-new.
126
+ 2. **Create-new + no description yet** → ask for the description, then analyze it (logic unchanged):
127
+ - If description is too short (< 20 words) or missing one concrete detail → stop and ask 1-2 clarifying questions
128
+ - If the idea has unresolved architecture choices, unclear acceptance criteria, unclear scope boundaries, or multiple plausible approaches → stop and route to `/hapo:brainstorm <idea>` before creating spec artifacts
129
+ - If task is simple (small bugfix, config change) → suggest "A spec may not be needed for this. Continue anyway?"
130
+ - If task is complex (multi-module, security/migration related) → auto-activate deep research, ask user 3 scope questions
131
+ - For non-trivial specs, execute the Step 5 Evidence Gate before writing final requirements. Do not design from memory when codebase or current external evidence can answer the question.
132
+ 3. **Creation Mode Gate** (how far to run) — see the dedicated section below. Options: `Auto (→ Tasks)` · `Stop after Design` · `Step by step`. If `.claude/settings.json` → `language` is not English, also offer the **Translation Mirror** (see below).
133
+ 4. **Continue an unfinished spec** → read `spec.json.current_phase`, then `AskUserQuestion` offering the **remaining** stop points (e.g. `→ Design`, `→ Tasks`, `Step by step`) and resume the existing pipeline from that phase. If a message accompanied the call, treat it as added context for the next phase (scope expansion → ask, per `references/ask-user-question-gates.md`).
134
+ 5. **Run the chosen scope.** On an early stop, emit the Paused Block (Step 10). Sync `spec.json` per `state-sync.md`.
135
+
136
+ > The pipeline, validator, templates, and rules are unchanged. "Stop after Design" simply halts before Step 7; it runs Steps 1–6 exactly as specified.
137
+
138
+ ### Creation Mode Gate
139
+
140
+ Shown once (via `AskUserQuestion`) on the no-flag create path, after the description passes the safety gates. It selects the **stop point only** — every phase that runs uses the unchanged Step logic.
141
+
142
+ | Option | Runs | Stops after | Approvals |
143
+ |---|---|---|---|
144
+ | **Auto (→ Tasks)** | Step 1→10 end-to-end | full (ready gate) | each phase `generated=true` + `approved=true` |
145
+ | **Stop after Design** | Step 1→6 | `design` (before Step 7) | requirements + design `approved=true`; `ready_for_implementation=false` |
146
+ | **Step by step** | one phase at a time | after each phase | per phase `generated=true`, `approved=false` until user approves |
119
147
 
120
- ### When called WITH a feature description
148
+ Rules:
149
+ - `--auto` equals choosing **Auto (→ Tasks)** without showing this gate.
150
+ - **Stop after Design** / **Step by step** leave `ready_for_implementation=false` and emit the Paused Block (Step 10).
151
+ - Continuing later: run `/hapo:specs` again → Interactive State Discovery detects the unfinished spec and offers the remaining stop points. No flag or keyword required.
121
152
 
122
- System auto-analyzes the description:
123
- - If description is too short (< 20 words) or missing one concrete detail → stop and ask 1-2 clarifying questions
124
- - If the idea has unresolved architecture choices, unclear acceptance criteria, unclear scope boundaries, or multiple plausible approaches → stop and route to `/hapo:brainstorm <idea>` before creating spec artifacts
125
- - If task is simple (small bugfix, config change) → suggest "A spec may not be needed for this. Continue anyway?"
126
- - If task is complex (multi-module, security/migration related) → auto-activate deep research, ask user 3 scope questions
127
- - For non-trivial specs, execute the Step 5 Evidence Gate before writing final requirements. Do not design from memory when codebase or current external evidence can answer the question.
128
- - After user confirms scope, continue through Init → Evidence/Requirements → Design → Tasks → Finalization in the same workflow unless the user explicitly asks for "init only" or "pause after init".
129
- - If the workflow must pause for manual approval, the continuation command is `/hapo:specs resume <feature>` or `/hapo:specs <feature>`.
153
+ ### Translation Mirror (optional reference copy)
154
+
155
+ Load `references/translation-mirror.md`. This is the only language feature in the entry layer; canonical artifacts are always English.
156
+
157
+ - Read `.claude/settings.json` → `language`. If it is **not** English and the run is **interactive** (no `--auto`), ask once via `AskUserQuestion`: "Generate a `<language>` reference copy of this spec? (kept in sync, read-only)".
158
+ - On `Yes` → set `spec.json.translation` (`enabled`, `language`, `language_code`, `dir: i18n/<code>`, `sync: always`) and, after each canonical doc is written in Steps 5–7, regenerate the matching file under `i18n/<code>/` with the reference-only marker.
159
+ - `--auto` does not prompt for a mirror, so an `--auto` create makes none. But if the spec already has `translation.enabled = true` (set in an earlier interactive run), always-sync still applies: an `--auto` resume keeps regenerating the mirror after each canonical write.
160
+ - The mirror is reference-only: never validated, never a source of truth, ignored by `hapo:develop`.
130
161
 
131
162
  ### When called WITH `--validate` argument
132
163
 
@@ -148,9 +179,16 @@ The system MUST NOT execute Steps 1-8. Instead, load `references/review.md` and
148
179
 
149
180
  ```mermaid
150
181
  flowchart TD
151
- A["Call /hapo:specs"] --> B{Has description?}
152
- B -->|No| C["Menu: init / status / resume / --validate / archive"]
153
- B -->|Yes| D["Step 1: Analyze description"]
182
+ A["Call /hapo:specs"] --> B{Flag?}
183
+ B -->|"--status"| ST["Status report → stop"]
184
+ B -->|"--archive"| AR["Archive workflow → stop"]
185
+ B -->|"--validate"| W
186
+ B -->|"--auto"| D["Step 1: Analyze description"]
187
+ B -->|none| DISC["Interactive State Discovery"]
188
+ DISC --> DISC1{Unfinished spec?}
189
+ DISC1 -->|Continue| RES["Read current_phase → resume remaining phases"]
190
+ DISC1 -->|New| D
191
+ RES --> CM
154
192
  D --> DB{"Needs pre-spec brainstorm?"}
155
193
  DB -->|Yes| DB2["Stop: run /hapo:brainstorm with same idea"]
156
194
  DB -->|No| E{Clear enough?}
@@ -174,7 +212,9 @@ flowchart TD
174
212
  N -->|Yes| P["Step 5B: Requirements — write EARS"]
175
213
  P --> Q["Step 6: Design — pick discovery mode"]
176
214
  Q --> R["Write design.md"]
177
- R --> S["Step 7: Tasks — split into individual files"]
215
+ R --> CM{"Creation Mode?"}
216
+ CM -->|"Stop after Design"| STOP["Paused at design → emit Paused Block"]
217
+ CM -->|"Auto / Step by step"| S["Step 7: Tasks — split into individual files"]
178
218
  S --> T["Create tasks/task-R*.md + task_registry"]
179
219
  T --> U["Step 8: Hydrate Claude Tasks if >= 3 task files"]
180
220
  U --> V{Review?}
@@ -233,7 +273,7 @@ Load: `references/scope-inquiry.md`
233
273
  - `in_scope`: confirmed scope items
234
274
  - `out_of_scope`: excluded items
235
275
  - `expansion_policy`: `requires-user-approval`
236
- - Step 4 itself only initializes files. In a normal `/hapo:specs <feature-description>` run, immediately continue to Step 5 after Init. Stop here only when the user explicitly requested init-only behavior.
276
+ - Step 4 itself only initializes files. The Creation Mode Gate (or `--auto`) decides how far the run proceeds; in every mode Step 4 continues into Step 5 — Init is never a stop point.
237
277
 
238
278
  ### Step 5: Evidence Gate, Requirements & Research
239
279
  - Read `spec.json` — stop if init hasn't completed
@@ -392,6 +432,7 @@ Load: `references/review.md` + `rules/design-review.md`
392
432
  Tasks and requirements must reuse the same policy verbatim; mixed policies are invalid.
393
433
  - FAIL if `validation.status = "completed"` but `timestamps.validation_done` / `timestamps.review_done`, `updated_at`, and report metadata are not synchronized with the final reviewed state.
394
434
  - If `validation_recommended = true` and `validation.status` is not `completed` (or an explicit accepted-risk state recorded by the user), `ready_for_implementation` MUST remain `false`
435
+ - If `translation.enabled = true`, ensure `i18n/<language_code>/` exists and was re-synced after the final canonical write; the mirror itself is excluded from validation and never blocks `ready_for_implementation`.
395
436
  - Only after this audit passes may the system mark `progress.tasks = "done"` and `ready_for_implementation = true`
396
437
 
397
438
  ### Step 10: Completion — Context Reminder (MANDATORY)
@@ -407,15 +448,27 @@ After completing the spec, output a short summary of what was generated, then yo
407
448
  💡 Tip: Run /clear or start a new chat session before implementing to reduce planning context carryover.
408
449
  ```
409
450
 
451
+ ### Step 10b: Paused Block (early stop)
452
+
453
+ When the run stops before Tasks (Creation Mode = **Stop after Design** or **Step by step**), do NOT print the completion block above and do NOT run the deterministic validator (no tasks exist yet). Instead print:
454
+
455
+ ```
456
+ ⏸ Spec paused at <phase>: specs/<feature>/
457
+ 📌 Continue — run /hapo:specs and choose "Continue <feature>"
458
+ (or /hapo:specs <feature> --auto to finish straight to Tasks)
459
+ ```
460
+
461
+ `ready_for_implementation` stays `false`. The next `/hapo:specs` run re-detects this spec via Interactive State Discovery and offers the remaining phases.
462
+
410
463
  ## Active Spec State
411
464
 
412
465
  When user calls `hapo:specs`, system checks `specs/`:
413
466
 
414
467
  | Situation | Action |
415
468
  |---|---|
416
- | A spec is `in_progress` | Ask: "You have spec `<name>` at phase `<phase>`. Continue? [Y/n]" |
417
- | A spec matches current git branch | Ask: "Branch `feature/X` has spec `X`. Activate or create new?" |
418
- | Nothing found | Create new spec or show menu |
469
+ | A spec is `in_progress` | Interactive State Discovery offers `Continue <name>` (resume from `<phase>`) vs `Create new spec` |
470
+ | A spec matches current git branch | Offer `Continue <X>` vs `Create new` |
471
+ | Nothing found | Create new spec → Creation Mode Gate |
419
472
 
420
473
  **Next step suggestions based on `spec.json`:**
421
474
 
@@ -437,8 +490,9 @@ When user calls `hapo:specs`, system checks `specs/`:
437
490
  **Timestamps:** Each `timestamps.*_done` field MUST use the **actual current time** (ISO 8601 with timezone) when that specific phase completes. This includes `review_done` and `validation_done` after review/validate workflows. Do NOT reuse the `init` timestamp for later phases. If running the full pipeline end-to-end, capture a fresh timestamp at each phase transition.
438
491
 
439
492
  **Approvals (auto-approval behavior):**
440
- - When running the **full pipeline end-to-end** (init → tasks in one session): set `approvals.{phase}.generated = true` AND `approvals.{phase}.approved = true` for each completed phase before proceeding to the next.
441
- - When running a **single phase**: set `generated = true` but leave `approved = false` — user must explicitly approve before continuing.
493
+ - When running the **full pipeline end-to-end** (`--auto` or Creation Mode "Auto", init → tasks in one session): set `approvals.{phase}.generated = true` AND `approvals.{phase}.approved = true` for each completed phase before proceeding to the next.
494
+ - When running to an **early stop point** (Creation Mode "Stop after Design"): for each phase that ran to reach the stop point, set `generated = true` AND `approved = true`; do not generate later phases; keep `ready_for_implementation = false`.
495
+ - When running a **single phase** (Creation Mode "Step by step"): set `generated = true` but leave `approved = false` — user must explicitly approve before continuing.
442
496
 
443
497
  **Task inventory:** `task_files` MUST be present and MUST list every real task file exactly once using relative paths like `tasks/task-R1-01-example.md`.
444
498
  Task paths that omit the `task-` prefix or use non-padded sequence numbers (for example `tasks/R1-1-example.md`) are invalid for new CafeKit specs.
@@ -447,6 +501,8 @@ Task paths that omit the `task-` prefix or use non-padded sequence numbers (for
447
501
 
448
502
  **Validation recommendation:** `design_context.validation_recommended` MUST be `true` for auth, privacy, delete-data, migration, schema-change, browser-extension-permission, external-provider, or 5+ task file specs.
449
503
 
504
+ **Translation mirror:** `translation` records the optional reference copy (`enabled`, `language`, `language_code`, `dir`, `sync: always`, `last_synced_at`). Canonical artifacts stay English; when `enabled = true`, regenerate `i18n/<language_code>/` after each canonical doc write and stamp `last_synced_at`. The mirror never affects `ready_for_implementation`. See `references/translation-mirror.md`.
505
+
450
506
  **`ready_for_implementation`:** This field MUST only be set to `true` when ALL of the following conditions are met:
451
507
  1. `approvals.requirements.approved = true`
452
508
  2. `approvals.design.approved = true`
@@ -480,14 +536,28 @@ specs/
480
536
  └── red-team-report.md
481
537
  ```
482
538
 
539
+ When `translation.enabled` is true, a reference-only mirror is added alongside (English stays canonical):
540
+
541
+ ```
542
+ specs/<feature-name>/
543
+ └── i18n/<lang-code>/ # reference only — generated from canonical, never validated
544
+ ├── requirements.md
545
+ ├── design.md
546
+ ├── research.md
547
+ └── tasks/task-R*.md
548
+ ```
549
+
483
550
  ## Subcommands
484
551
 
552
+ The canonical surface is four flags. Bare-verb forms are kept only as silent back-compat aliases.
553
+
485
554
  | Command | Purpose | Reference |
486
555
  |---|---|---|
487
- | `/hapo:specs status` | View status of all specs | — |
488
- | `/hapo:specs resume <feature>` | Continue an active spec | — |
556
+ | `/hapo:specs --status` | View status of all specs (alias: `status`) | — |
489
557
  | `/hapo:specs --validate <feature>` | Validate spec (auto: red team + validate based on complexity) | `references/review.md` |
490
- | `/hapo:specs archive` | Archive completed specs + write journal | `references/archive-workflow.md` |
558
+ | `/hapo:specs --archive` | Archive completed specs + write journal (alias: `archive`) | `references/archive-workflow.md` |
559
+ | `/hapo:specs --auto [<desc>]` | Non-interactive: create (or resume) and run end-to-end to Tasks | — |
560
+ | `/hapo:specs [<desc>]` | Interactive State Discovery (continue unfinished, or create + Creation Mode Gate). Alias `resume` accepted. | — |
491
561
 
492
562
  ## Quality Standards
493
563
 
@@ -578,3 +648,4 @@ Before finalizing any specification, assert all the following:
578
648
  - `task-hydration.md` — Task files → Claude Tasks conversion
579
649
  - `review.md` — Spec review (auto-decides: red team 8 steps + validate 6 steps)
580
650
  - `archive-workflow.md` — Archive workflow (5 steps)
651
+ - `translation-mirror.md` — Optional reference-only translation mirror (detection, layout, sync, fields)
@@ -0,0 +1,83 @@
1
+ # Translation Mirror
2
+
3
+ Optional, reference-only duplicate of a spec in the user's configured language. The English spec is always the canonical source of truth; the mirror exists only for human cross-reading.
4
+
5
+ ## When To Offer
6
+
7
+ 1. Read the configured language from `.claude/settings.json` → `language` (a freeform label written at install time, e.g. `Tiếng Việt`, `日本語`, `Korean`, `English`).
8
+ 2. If the label resolves to English (`English` / `en`) → **do not** offer a mirror; there is nothing to duplicate.
9
+ 3. If it is any other language AND the run is interactive (no `--auto`) → ask once via `AskUserQuestion`:
10
+ - "Generate a `<language>` reference copy of this spec? (kept in sync, read-only)" → `Yes` / `No`.
11
+ 4. `--auto` runs are non-interactive → **skip** the offer (an `--auto` create makes no mirror). If `translation.enabled` is already `true` from an earlier run, always-sync still applies during an `--auto` resume.
12
+ 5. Persist the choice in `spec.json.translation` (see Fields).
13
+
14
+ ## Language Code
15
+
16
+ Map the freeform label to a short folder code:
17
+
18
+ | Label | Code |
19
+ |---|---|
20
+ | Tiếng Việt | `vi` |
21
+ | 日本語 / Japanese | `ja` |
22
+ | 한국어 / Korean | `ko` |
23
+ | 中文 / Chinese | `zh` |
24
+ | Français / French | `fr` |
25
+ | (anything else) | kebab-case slug of the label |
26
+
27
+ ## Layout
28
+
29
+ The mirror lives under the spec, never replacing canonical files:
30
+
31
+ ```
32
+ specs/<feature>/
33
+ ├── spec.json # canonical state — NOT mirrored
34
+ ├── requirements.md # English canonical
35
+ ├── design.md
36
+ ├── research.md
37
+ ├── tasks/task-R*.md
38
+ └── i18n/<code>/ # mirror (reference only)
39
+ ├── requirements.md
40
+ ├── design.md
41
+ ├── research.md
42
+ └── tasks/task-R*.md
43
+ ```
44
+
45
+ - Mirror **only** the human-readable docs: `requirements.md`, `design.md`, `research.md`, and every `tasks/task-*.md`.
46
+ - Do **not** mirror `spec.json` (machine state is language-agnostic and lives only at the root).
47
+ - Keep file names and the `tasks/` substructure identical to canonical so they line up 1:1.
48
+
49
+ ## Mirror File Marker
50
+
51
+ Every generated mirror file MUST begin with this HTML comment so no one mistakes it for a source:
52
+
53
+ ```
54
+ <!-- TRANSLATION MIRROR — generated from English canonical. Reference only. Do not edit; regenerated on sync. -->
55
+ ```
56
+
57
+ EARS trigger keywords and fixed phrases stay in English even inside the mirror (`When`, `If`, `While`, `Where`, `The system shall`); only the variable parts are translated — same rule as `rules/ears-format.md`.
58
+
59
+ ## Always-Sync
60
+
61
+ `spec.json.translation.sync` is `always`:
62
+
63
+ - Whenever a canonical doc is written or updated (Step 5 requirements/research, Step 6 design, Step 7 tasks, or any later edit), regenerate the matching mirror file from the new canonical content.
64
+ - After regenerating, set `spec.json.translation.last_synced_at` to the current time.
65
+ - If a canonical task file is added/removed, add/remove the matching mirror file so the two trees stay 1:1.
66
+
67
+ ## Not A Source Of Truth
68
+
69
+ - The deterministic validator (`validate-spec-output.cjs`) runs on **canonical only**. The `i18n/` tree is never validated and never blocks `ready_for_implementation`.
70
+ - `task_files` and `task_registry` reference canonical paths only.
71
+ - `hapo:develop` implements from canonical English; it must ignore `i18n/`.
72
+ - If the mirror and canonical ever disagree, canonical wins; re-sync the mirror.
73
+
74
+ ## Fields (`spec.json.translation`)
75
+
76
+ | Field | Meaning |
77
+ |---|---|
78
+ | `enabled` | `true` once the user opts in |
79
+ | `language` | freeform label from settings (e.g. `Tiếng Việt`) |
80
+ | `language_code` | folder code (e.g. `vi`) |
81
+ | `dir` | relative mirror dir (e.g. `i18n/vi`) |
82
+ | `sync` | `always` |
83
+ | `last_synced_at` | ISO 8601 timestamp of the last regeneration |
@@ -4,8 +4,8 @@
4
4
  EARS (Easy Approach to Requirements Syntax) is the standard format for acceptance criteria in spec-driven development.
5
5
 
6
6
  EARS patterns describe the logical structure of a requirement (condition + subject + response) and are not tied to any particular natural language.
7
- All acceptance criteria should be written in the target language configured for the specification (for example, `spec.json.language` / `en`).
8
- Keep EARS trigger keywords and fixed phrases in English (`When`, `If`, `While`, `Where`, `The system shall`, `The [system] shall`) and localize only the variable parts (`[event]`, `[precondition]`, `[trigger]`, `[feature is included]`, `[response/action]`) into the target language. Do not interleave target-language text inside the trigger or fixed English phrases themselves.
7
+ Canonical acceptance criteria are written in **English** (`spec.json.language` is `en`). A non-English rendering only appears in the optional translation mirror (`i18n/<lang>/`, see `references/translation-mirror.md`), never in the canonical files.
8
+ Keep EARS trigger keywords and fixed phrases in English (`When`, `If`, `While`, `Where`, `The system shall`, `The [system] shall`). In the mirror, localize only the variable parts (`[event]`, `[precondition]`, `[trigger]`, `[feature is included]`, `[response/action]`); do not interleave translated text inside the trigger or fixed English phrases themselves.
9
9
 
10
10
  ## Primary EARS Patterns
11
11
 
@@ -2,7 +2,7 @@
2
2
  "feature_name": "{{FEATURE_NAME}}",
3
3
  "created_at": "{{TIMESTAMP}}",
4
4
  "updated_at": "{{TIMESTAMP}}",
5
- "language": "vi",
5
+ "language": "en",
6
6
  "status": "in_progress",
7
7
  "phase": "initialized",
8
8
  "current_phase": "init",
@@ -68,5 +68,13 @@
68
68
  "questions_asked": 0,
69
69
  "last_validated_at": null
70
70
  },
71
+ "translation": {
72
+ "enabled": false,
73
+ "language": null,
74
+ "language_code": null,
75
+ "dir": null,
76
+ "sync": "always",
77
+ "last_synced_at": null
78
+ },
71
79
  "ready_for_implementation": false
72
80
  }