@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 +1 -1
- package/src/claude/CLAUDE.md +1 -1
- package/src/claude/skills/develop/SKILL.md +1 -1
- package/src/claude/skills/specs/SKILL.md +115 -44
- package/src/claude/skills/specs/references/translation-mirror.md +83 -0
- package/src/claude/skills/specs/rules/ears-format.md +2 -2
- package/src/claude/skills/specs/templates/spec-state.json +9 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@haposoft/cafekit",
|
|
3
|
-
"version": "0.11.
|
|
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",
|
package/src/claude/CLAUDE.md
CHANGED
|
@@ -116,7 +116,7 @@ Consult these when the task touches the relevant area:
|
|
|
116
116
|
|
|
117
117
|
## Language Consistency
|
|
118
118
|
|
|
119
|
-
|
|
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
|
|
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 |
|
|
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
|
|
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
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
-
|
|
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
|
-
|
|
123
|
-
|
|
124
|
-
-
|
|
125
|
-
|
|
126
|
-
- If
|
|
127
|
-
-
|
|
128
|
-
-
|
|
129
|
-
-
|
|
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{
|
|
152
|
-
B -->|
|
|
153
|
-
B -->|
|
|
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 -->
|
|
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.
|
|
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` |
|
|
417
|
-
| A spec matches current git branch |
|
|
418
|
-
| Nothing found | Create new spec
|
|
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
|
|
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
|
-
|
|
8
|
-
Keep EARS trigger keywords and fixed phrases in English (`When`, `If`, `While`, `Where`, `The system shall`, `The [system] shall`)
|
|
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": "
|
|
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
|
}
|