baldart 3.21.2 → 3.22.1
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/CHANGELOG.md +91 -0
- package/VERSION +1 -1
- package/framework/.claude/agents/prd-card-writer.md +36 -0
- package/framework/.claude/skills/prd/SKILL.md +115 -12
- package/framework/.claude/skills/prd/assets/state-template.md +7 -0
- package/framework/.claude/skills/prd/references/backlog-phase.md +17 -4
- package/framework/.claude/skills/prd/references/discovery-phase.md +75 -18
- package/framework/.claude/skills/prd/references/ui-design-phase.md +7 -0
- package/framework/.claude/skills/prd/references/validation-phase.md +106 -23
- package/framework/.claude/skills/prd-add/SKILL.md +48 -5
- package/framework/.claude/skills/ui-design/SKILL.md +21 -1
- package/framework/.claude/skills/worktree-manager/SKILL.md +282 -9
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,97 @@ All notable changes to BALDART will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [3.22.1] - 2026-05-27
|
|
9
|
+
|
|
10
|
+
Rimosso il gate `AskUserQuestion` di conferma merge introdotto in v3.22.0 Step 7 — era friction inutile contro il "seamless" che è il punto della release. Quando l'utente lancia `/prd` ha già implicitamente accettato la pipeline completa (discovery → design → cards → commit → merge in develop). Chiedere "Procedo con merge?" a fine sessione equivale a chiedere "sei sicuro di voler completare quello che mi hai chiesto di fare?".
|
|
11
|
+
|
|
12
|
+
### Changed — `/prd` Step 7 merge è ora full-seamless
|
|
13
|
+
|
|
14
|
+
- **[framework/.claude/skills/prd/references/validation-phase.md](framework/.claude/skills/prd/references/validation-phase.md)**: Step 7 point 9 non è più un `AskUserQuestion` ma una nota che chiarisce il razionale del no-confirmation flow + escape hatch user-initiated ("non mergiare" / "lascia il worktree" honora l'override e ferma dopo il commit).
|
|
15
|
+
- **[framework/.claude/skills/prd/SKILL.md](framework/.claude/skills/prd/SKILL.md)** HARD RULE 17 lifecycle: la descrizione di Step 7 cita "Seamless by default, no confirmation gate" + l'escape hatch.
|
|
16
|
+
- **[framework/.claude/skills/prd/references/discovery-phase.md](framework/.claude/skills/prd/references/discovery-phase.md)**: il messaggio di kickoff visibile all'utente promette esplicitamente "commit + merge automatico in develop + cleanup worktree, seamless" — niente più sorprese a fine sessione.
|
|
17
|
+
|
|
18
|
+
### Why PATCH and not MINOR
|
|
19
|
+
|
|
20
|
+
Rimozione di un comportamento (gate di conferma) introdotto solo 0 minuti fa nella stessa giornata. Nessuna nuova capability, nessun breaking change per consumer: il gate non era una feature documentata né attesa dagli utenti pre-v3.22.0, era una sovra-cautela introdotta da me contro la richiesta esplicita ("seamless"). La decision tree di MAINTAINING.md classifica "bugfix di behaviour non desiderato senza breaking change" come PATCH.
|
|
21
|
+
|
|
22
|
+
### Why no schema-change propagation
|
|
23
|
+
|
|
24
|
+
Modifica puramente comportamentale dentro un singolo step di una singola skill. Zero chiavi nuove, zero modifiche CLI, zero hook.
|
|
25
|
+
|
|
26
|
+
## [3.22.0] - 2026-05-27
|
|
27
|
+
|
|
28
|
+
Le sessioni `/prd` ora vivono in un **docs worktree** dedicato, esattamente come fa `/new` per le card di codice. Il problema risolto: con 5-10 sessioni Claude in parallelo, ogni PRD inquinava il main checkout con `docs/prd/<slug>/PRD.md`, lo state file, le card YAML, l'eventuale `design.html`, e gli update a `ssot-registry.md` / `project-status.md`. `git status` diventava un campo minato, le sessioni `/new` rischiavano di stashare/committare file PRD non loro, e la review manuale era pressoché impossibile. Soluzione: estendere `worktree-manager` con una **modalità docs lean** (no `npm install`, no porta, no `.env` copy, no build verify, no lint/tsc gates) e integrarla nel ciclo di vita del PRD — creazione automatica al kickoff, merge automatico (previa conferma utente) al termine, cleanup seamless.
|
|
29
|
+
|
|
30
|
+
### Added — `worktree-manager` programmatic docs mode
|
|
31
|
+
|
|
32
|
+
- **[framework/.claude/skills/worktree-manager/SKILL.md](framework/.claude/skills/worktree-manager/SKILL.md)**: nuova sezione "Programmatic API — docs mode" con due funzioni:
|
|
33
|
+
- **`nw-docs`** — input `{ slug, branchPrefix? }`, output `{ path, branch, kind: "docs" }`. Esegue solo `git fetch origin develop` + `git worktree add .worktrees/prd-<slug> -b prd/<slug> origin/develop` + entry nel registry con `kind: "docs"`, `port: null`, `buildVerified: null`. Target di costo: < 5 secondi (vs minuti per `/nw` standard a causa di `npm install`).
|
|
34
|
+
- **`mw-docs`** — input `{ worktreePath, commitMessage? }`, output `{ merged, mergeCommit, prNumber, strategy, worktreeRemoved }`. Esegue safety commit + rebase su `origin/develop` (con il protocollo conflict-resolution doc-friendly esistente in `/mw` step 4b) + merge via `git.merge_strategy` configurato (`pr` o `local-push`) + cleanup worktree/branch. **Salta** i gate inapplicabili a un worktree di docs: `npm run build`, `npx eslint`, `npx tsc`, `npm run test`, post-merge build verify.
|
|
35
|
+
- Forme **FORBIDDEN** documentate esplicitamente: niente `npm install`/port scan/`.env*` copy/build in `nw-docs`; niente lint/tsc/build gates in `mw-docs`. Il senso della modalità lean è proprio non eseguirli.
|
|
36
|
+
- Registry condiviso con i code worktrees (`.worktrees/registry.json`) — `/lw` e `/cw` mostrano docs worktrees accanto ai code worktrees, distinti dal campo `kind`.
|
|
37
|
+
|
|
38
|
+
### Changed — `worktree-manager`: rebase conflict protocol hardened
|
|
39
|
+
|
|
40
|
+
- **[framework/.claude/skills/worktree-manager/SKILL.md](framework/.claude/skills/worktree-manager/SKILL.md)** — la tabella di conflict-resolution dello step 4b di `/mw` (riusata verbatim da `mw-docs`) è stata estesa con due categorie nuove **prima** della catch-all "Docs/config":
|
|
41
|
+
- **Structured registries** (`project-status.md`, `ssot-registry.md`, `field-registry.*`, `traceability-matrix.md`, `REGISTRY.md`) → **STOP**: abort rebase, report all'utente. Senza questa riga, due PRD paralleli che toccano `project-status.md` farebbero auto-strip dei marker di conflitto producendo file con sezioni duplicate e tabelle malformate. Il fix vale anche per `/mw` su code worktrees — qualsiasi card che modifica una di queste registry ora chiede risoluzione manuale invece di corromperle silenziosamente.
|
|
42
|
+
- **Append-only logs** (`**/*.jsonl` sotto `docs/metrics/`) → auto-resolve "keep both sides", che per JSONL è semanticamente corretto (file line-oriented additivo). Questo permette al Metrics Log del PRD (vedi sotto) di sopravvivere a merge concorrenti senza intervento.
|
|
43
|
+
|
|
44
|
+
### Changed — `/prd` skill: HARD RULE 17 (worktree isolation)
|
|
45
|
+
|
|
46
|
+
- **[framework/.claude/skills/prd/SKILL.md](framework/.claude/skills/prd/SKILL.md)**: nuova HARD RULE 17 obbligatoria — ogni sessione PRD apre un docs worktree allo Step 1 prima di scrivere qualunque file, e committa/mergia tutto allo Step 7 prima di terminare. La regola include:
|
|
47
|
+
- **Path resolution explicit rule**: tutti i `Write` / `Edit` / `Read` di Claude Code DEVONO prefissare i path con `$WORKTREE_PATH` (Claude Code richiede path assoluti — senza prefisso esplicito i file finirebbero nel main repo, vanificando l'isolamento). Esempio `right vs wrong` nel testo della regola.
|
|
48
|
+
- **Forbidden operations**: nessun `git checkout`/`switch`/`branch` sul main, nessun `git stash` (refs/stash è condiviso fra worktree), nessuna scrittura diretta sul main repo durante la sessione.
|
|
49
|
+
- **Failure handling**: se `nw-docs` fallisce (e.g. `.worktrees/` non in `.gitignore`), la skill DEVE fermarsi e segnalare — niente fallback silenzioso al main repo.
|
|
50
|
+
- **HARD RULE 9 aggiornata**: il session-start update di `project-status.md` viene **skippato** quando la sessione gira in un docs worktree (sarebbe invisibile alle altre sessioni). L'update at-commit resta attivo, eseguito nel worktree come ultima scrittura prima del rebase + merge.
|
|
51
|
+
- **Step 1 (Kickoff)** in [discovery-phase.md](framework/.claude/skills/prd/references/discovery-phase.md): aggiunto step 3 che chiama `worktree-manager nw-docs` subito dopo aver derivato lo `<slug>`, prima di creare lo state file. Output kickoff aggiornato per mostrare path/branch del worktree all'utente.
|
|
52
|
+
- **Step 0 (Context Recovery)** in [discovery-phase.md](framework/.claude/skills/prd/references/discovery-phase.md): scan iniziale di `.worktrees/registry.json` per entries con `kind: "docs"` che matchano lo slug — se trovate, `cd` nel worktree e riprendi. Gestito anche il caso "state file legacy nel main da pre-v3.22.0" (chiede all'utente se migrare o continuare in legacy mode).
|
|
53
|
+
- **Step 7 (Resolution, Commit & Merge)** in [validation-phase.md](framework/.claude/skills/prd/references/validation-phase.md) — rinominato da "Resolution and Commit" e riscritto end-to-end:
|
|
54
|
+
- Update di `ssot-registry.md` / `project-status.md` avviene nel worktree (skip se file inesistente).
|
|
55
|
+
- Commit con `git -C "$WORKTREE_PATH" commit` (file espliciti, mai `git add .`).
|
|
56
|
+
- **Gate di conferma esplicito** (`AskUserQuestion`) prima del merge: "Procedo con merge automatico in `develop` e cleanup del worktree?". Opzione "lascia il worktree" per review manuale o test.
|
|
57
|
+
- Sulla conferma: invocazione `worktree-manager mw-docs` che rebase + merge + cleanup. Failure handling: il worktree resta su disco, niente retry automatico.
|
|
58
|
+
- **[framework/.claude/skills/prd/assets/state-template.md](framework/.claude/skills/prd/assets/state-template.md)**: nuova sezione `## Worktree` (path, branch, kind, created_at, merge_commit).
|
|
59
|
+
- **Metrics Log riposizionato dentro il worktree.** La sezione "Metrics Log" di SKILL.md scriveva precedentemente in `docs/metrics/skill-runs.jsonl` con risoluzione del path rispetto al main repo root — incompatibile con HARD RULE 17 e con isolamento parallelo. Ora scrive in `$WORKTREE_PATH/docs/metrics/skill-runs.jsonl` come ultimo append PRIMA del commit di Step 7; il file è incluso nella lista di stage esplicita e il conflict protocol di `mw-docs` lo riconosce come append-only (vedi categoria "Append-only logs" sopra). Risultato: due PRD paralleli che terminano insieme producono un append di entrambe le righe nel file su `develop`, senza intervento manuale.
|
|
60
|
+
|
|
61
|
+
### Why MINOR and not PATCH
|
|
62
|
+
|
|
63
|
+
Nuova capability portata da una skill esistente (`worktree-manager` guadagna l'API docs mode) + cambio di workflow per `/prd` (gira sempre in worktree). Nessun breaking change per i consumer: le sessioni PRD esistenti pre-3.22.0 sono detettate in Step 0 e gestite con prompt di migrazione (legacy mode resta supportato). La decision tree di `MAINTAINING.md` classifica "added capability" come MINOR.
|
|
64
|
+
|
|
65
|
+
### Why no schema-change propagation
|
|
66
|
+
|
|
67
|
+
Zero nuove chiavi in `baldart.config.yml`. La modalità docs riusa:
|
|
68
|
+
- `git.merge_strategy` (già esistente da v3.9.0) per il merge — `pr` o `local-push`, rispetta la scelta del progetto.
|
|
69
|
+
- `paths.prd_dir`, `paths.backlog_dir`, `paths.references_dir` (esistenti) — risolti relativamente al worktree (HARD RULE 17).
|
|
70
|
+
- `features.has_prd_workflow` (esistente) — gating della skill.
|
|
71
|
+
|
|
72
|
+
Nota CHANGELOG-only (non normativa): per i PRD molti consumer preferiscono `merge_strategy: local-push` (no PR per documentazione). Chi vuole differenziare la strategia per skill può farlo via overlay `.baldart/overlays/prd.md` — la skill non impone scelte.
|
|
73
|
+
|
|
74
|
+
### Pre-release code review fixes (within v3.22.0)
|
|
75
|
+
|
|
76
|
+
Un `/code-review` high-effort eseguito prima del tag ha individuato 10 bug — tutti corretti in questa stessa release prima del rilascio. I più gravi:
|
|
77
|
+
|
|
78
|
+
- **`prd-card-writer` agent + `backlog-phase.md` invocation**: il subagent scriveva le card a `backlog/` consumer-root-relative senza alcuna `$WORKTREE_PATH` awareness — Step 5 del PRD spruzzava le card nel main repo, vanificando l'isolamento. Fix: nuova sezione "Working Directory (MANDATORY)" nel file dell'agent + il prompt da `backlog-phase.md` ora passa `WORKING_DIRECTORY` esplicito (regola di substitution documentata).
|
|
79
|
+
- **`ui-design/SKILL.md` Step G**: copia `design.html` a `${paths.prd_dir}/<slug>/design.html` consumer-root-relative. Fix identico: sezione "Working Directory" + `ui-design-phase.md` ora passa `WORKING_DIRECTORY=$WORKTREE_PATH` come arg.
|
|
80
|
+
- **`/prd-add` Step 0**: listava `${paths.prd_dir}/sessions/` sul main repo, zero scan del registry. Fix: Step 0 riscritto — scansiona `.worktrees/registry.json` per `kind: "docs"` prima di guardare il main; gestisce sia worktree-mode che legacy; documenta gli effetti collaterali downstream (delta commit nel worktree, sub-agents ri-invocati con `WORKING_DIRECTORY`, no auto-merge per CR).
|
|
81
|
+
- **Regressione `/new` introdotta dal conflict protocol hardening**: la prima versione della tabella step 4b in `worktree-manager` abortiva blanket il rebase su `ssot-registry.md` / `project-status.md`, ma `/new` AGGIORNA `ssot-registry.md` per ogni card (line 1131 di `framework/.claude/skills/new/SKILL.md`, hook pre-commit che blocca commit a `backlog/` senza ssot). Risultato: ogni batch multi-card di `/new` sarebbe fallito al rebase. Fix: sostituito il blanket abort con **structural validation** (`validate_structured_md` helper) — strip markers + check struttura (no marker residui, no header table duplicati, no frontmatter doppio). Se valido → accept (caso routine: append additivo); se invalido → abort (caso raro: due card hanno modificato la stessa riga). Restituisce a `/new` il comportamento additivo originale, mantiene la protezione contro corruzione reale.
|
|
82
|
+
- **`git stash` in `mw-docs`**: la prima versione riusava verbatim `/mw` step 4b che fa `git stash push --include-untracked` prima del rebase. Violazione diretta della Safety Rule "NEVER use git stash in worktrees" (refs/stash condiviso fra worktree — incidente FEAT-0522). Fix: la sezione `mw-docs` ora esplicita "NO stash" — il safety commit dello step 1 garantisce working tree clean, qualunque dirty post-safety è un errore che richiede STOP, mai uno stash di recovery.
|
|
83
|
+
- **`nw-docs` mancante `.gitignore` check**: la Safety Rule generale dice "Always verify `.worktrees/` is in `.gitignore` before creating", ma `nw-docs` la omette. Fix: step 0 di `nw-docs` è ora un pre-flight `.gitignore` check che fallisce con errore esplicito se mancante.
|
|
84
|
+
- **`nw-docs` pseudo-bash relativo invece che assoluto**: il path ritornato come `path` doveva essere assoluto (per HARD RULE 17), ma lo pseudo-code lo settava relativo. Fix: ancorato a `$MAIN_ROOT` esplicito via `git rev-parse --show-toplevel` + `WORKTREE_PATH="$MAIN_ROOT/$WORKTREE_REL"`.
|
|
85
|
+
- **Esempio HARD RULE 17 fuorviante**: l'esempio "RIGHT" mostrava `Write file_path = "$WORKTREE_PATH/..."` come stringa literal. Claude Code NON espande shell variables → o errore "path must be absolute" o creazione di una dir letterale `$WORKTREE_PATH/`. Fix: esempio riscritto con 3 forme "wrong" (main repo, literal var, relative) + 1 "right" (substitution textuale dell'absolute path).
|
|
86
|
+
- **Off-by-one cross-ref Metrics Log**: "Add the file to Step 7 point 5" ma il staging è point 6 (point 5 è il Metrics Log step stesso, self-referential). Fix: cross-ref corretto a point 6 con nota di disambiguazione.
|
|
87
|
+
- **Case pattern `*.jsonl` non raggiungibile per il secondo arm + auto-strip non desiderato per fixture**: `*.jsonl|docs/metrics/*.jsonl` matchava ogni `.jsonl` ovunque (anche fixture/seed). Fix: tabella sostituita con pattern espliciti — `docs/metrics/*.jsonl` auto-resolve, altri `*.jsonl` abort + manuale.
|
|
88
|
+
- **Numerazione stale "Step 1, point 7"** in `discovery-phase.md` § 1.6: dopo la renumerazione, point 7 è "Context Loading", non l'output kickoff. Fix: aggiornato a "point 9 (Business Rationale Extraction is the final point)".
|
|
89
|
+
|
|
90
|
+
### Verification
|
|
91
|
+
|
|
92
|
+
Modifiche applicate ma non testabili automaticamente (nessuna test suite in questo repo, come da `CLAUDE.md`). Validazione richiesta in un consumer reale:
|
|
93
|
+
1. Lanciare `/prd` su una feature qualunque → verificare la creazione `.worktrees/prd-<slug>/` + entry `kind: "docs"` nel registry.
|
|
94
|
+
2. Aprire una seconda sessione Claude in parallelo e fare `git status` sul main → deve essere pulito.
|
|
95
|
+
3. Procedere fino allo Step 7 → verificare il prompt di conferma merge, completare → worktree rimosso, branch eliminato, PRD su `develop`.
|
|
96
|
+
4. Resume test: chiudere/riaprire la sessione a metà PRD → Step 0 deve trovare il worktree dal registry e `cd` lì.
|
|
97
|
+
5. `/prd-add` su PRD attivo → deve riusare il worktree esistente, non crearne uno nuovo.
|
|
98
|
+
|
|
8
99
|
## [3.21.2] - 2026-05-26
|
|
9
100
|
|
|
10
101
|
Aggiunto un livello di automazione che intercetta il drift fra la skill `/baldart-update` (v3.21.0+) e le sorgenti CLI che essa replica in chat. La skill replica **5 decision point fissi** del comando `npx baldart update`; quando una release tocca `src/commands/update.js` (nuovi prompt), `src/utils/hooks.js` (nuove entry in `HOOK_REGISTRY`), o `framework/templates/baldart.config.template.yml` (nuove top-level key), la skill può silenziosamente disallinearsi. Il bug v3.21.0 → v3.21.1 (`git -C .framework fetch` errato) è già stato un esempio del problema: la skill prometteva un pattern che il test live ha smentito. Senza un meccanismo di alert, futuri drift sarebbero individuabili solo per accidente.
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.
|
|
1
|
+
3.22.1
|
|
@@ -8,6 +8,42 @@ color: amber
|
|
|
8
8
|
|
|
9
9
|
You are **PRD Card Writer** — a specialist agent that converts an approved PRD into a set of atomic, well-structured backlog cards with full traceability.
|
|
10
10
|
|
|
11
|
+
## Working Directory (MANDATORY — read FIRST, since v3.22.0)
|
|
12
|
+
|
|
13
|
+
When invoked by `/prd` Step 5 the caller passes a **`WORKING_DIRECTORY`** field
|
|
14
|
+
in the prompt — its value is the absolute path of the docs worktree where the
|
|
15
|
+
PRD lives (e.g. `/Users/alice/proj/.worktrees/prd-menu-info`). All your file
|
|
16
|
+
writes MUST land **inside** this directory, otherwise the cards spray into the
|
|
17
|
+
consumer's main repo and HARD RULE 17 of `/prd` SKILL.md is broken (cards
|
|
18
|
+
become invisible to the worktree's commit, isolation collapses, parallel
|
|
19
|
+
sessions get polluted `git status`).
|
|
20
|
+
|
|
21
|
+
**Rule of thumb:** every path in this document — `backlog/`,
|
|
22
|
+
`${paths.backlog_dir}/`, `docs/references/ssot-registry.md`,
|
|
23
|
+
`${paths.references_dir}/...`, the card template — is **relative to
|
|
24
|
+
WORKING_DIRECTORY**. Before any `Write`, `Read`, `Glob`, or `Grep` call,
|
|
25
|
+
construct the absolute path as `<WORKING_DIRECTORY>/<relative-path>`.
|
|
26
|
+
|
|
27
|
+
**Examples:**
|
|
28
|
+
- ❌ `Write(file_path="backlog/FEAT-0500-00-...yml")` — relative path: Claude
|
|
29
|
+
Code rejects, or resolves against the wrong cwd.
|
|
30
|
+
- ❌ `Write(file_path="/Users/alice/proj/backlog/FEAT-0500-00-...yml")` —
|
|
31
|
+
absolute, but main-repo: defeats the worktree.
|
|
32
|
+
- ✅ `Write(file_path="/Users/alice/proj/.worktrees/prd-menu-info/backlog/FEAT-0500-00-...yml")`
|
|
33
|
+
— absolute, inside `WORKING_DIRECTORY`.
|
|
34
|
+
|
|
35
|
+
**Sanity check before writing.** Always begin your work by running
|
|
36
|
+
`Bash("cd <WORKING_DIRECTORY> && pwd && ls -la backlog/ | head -5")` and
|
|
37
|
+
confirming the output matches `WORKING_DIRECTORY`. If it doesn't, halt and
|
|
38
|
+
report — do NOT proceed to write cards on whatever cwd you ended up in.
|
|
39
|
+
|
|
40
|
+
**When the caller does NOT pass `WORKING_DIRECTORY`** (legacy call sites
|
|
41
|
+
predating v3.22.0): fall back to the consumer root (whatever Bash `pwd`
|
|
42
|
+
returns). Log a `[WORKING-DIR-FALLBACK]` warning in your response so the
|
|
43
|
+
caller can detect it and migrate.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
11
47
|
## Field Grounding Rule (HARD RULE — zero tolerance)
|
|
12
48
|
|
|
13
49
|
**BEFORE writing any field name in any card**, execute this protocol:
|
|
@@ -38,7 +38,7 @@ message. You ask questions, wait for answers, and iterate.
|
|
|
38
38
|
| 4b | Confirm Specs | [prd-writing-phase.md](references/prd-writing-phase.md) |
|
|
39
39
|
| 5 | Backlog Cards | [backlog-phase.md](references/backlog-phase.md) |
|
|
40
40
|
| 6 | Quality Audit | [validation-phase.md](references/validation-phase.md) |
|
|
41
|
-
| 7 | Resolution &
|
|
41
|
+
| 7 | Resolution, Commit & Merge | [validation-phase.md](references/validation-phase.md) |
|
|
42
42
|
|
|
43
43
|
**Before starting each phase, read the corresponding reference file.**
|
|
44
44
|
|
|
@@ -55,6 +55,7 @@ message. You ask questions, wait for answers, and iterate.
|
|
|
55
55
|
7. No code generation. This skill produces planning artifacts only.
|
|
56
56
|
8. Use exact terminology from `agents/coding-standards.md` and the project's terminology section in `.baldart/overlays/prd.md` (audience segments come from `identity.audience_segments`; domain entities are listed in the overlay).
|
|
57
57
|
9. Update `${paths.references_dir}/project-status.md` Active Code Context at session start and at commit (AGENTS.md MUST). Skip when the file does not exist in the project.
|
|
58
|
+
**Worktree-mode exception (HARD RULE 17):** when the PRD runs inside a docs worktree (default since v3.22.0), the session-start update is **SKIPPED** — writing `project-status.md` in the worktree wouldn't be visible to other terminals working on the main repo, and writing it on the main repo would pollute `git status` for parallel sessions (exactly what worktree isolation is meant to prevent). The at-commit update still applies and runs inside the worktree as the last write before rebase + merge — see [validation-phase.md](references/validation-phase.md) § Step 7.
|
|
58
59
|
10. **STOP means STOP.** When you see `STOP`, end your message. Do not make more tool
|
|
59
60
|
calls. Do not continue to the next step. Wait for the user.
|
|
60
61
|
11. **Every message MUST end with the Progress Bar.** No exceptions.
|
|
@@ -108,6 +109,88 @@ message. You ask questions, wait for answers, and iterate.
|
|
|
108
109
|
riusa esattamente questa stessa procedura di Step 1.6 → Step 3 entra in Hybrid mode.
|
|
109
110
|
Vedi [ui-design-phase.md](references/ui-design-phase.md) § "Step 3.0 — Mockup Source Decision".
|
|
110
111
|
|
|
112
|
+
17. **Worktree isolation (MANDATORY since v3.22.0).** Every PRD session runs inside
|
|
113
|
+
a dedicated **docs worktree** created by the `worktree-manager` skill in
|
|
114
|
+
programmatic docs mode — never on the consumer's main checkout. The worktree
|
|
115
|
+
isolates PRD artefacts from other parallel Claude sessions: `git status` on
|
|
116
|
+
the main repo stays clean, accidental stashes / commits / push from sibling
|
|
117
|
+
`/new` runs cannot pick up PRD files, and the merge back into `develop`
|
|
118
|
+
becomes a single atomic operation.
|
|
119
|
+
|
|
120
|
+
**Why this exists.** Without the worktree, every PRD pollutes the main
|
|
121
|
+
checkout with `${paths.prd_dir}/<slug>/PRD.md`, `${paths.prd_dir}/sessions/...`,
|
|
122
|
+
`${paths.backlog_dir}/FEAT-XXXX-*.yml`, plus design assets and updated
|
|
123
|
+
SSOT/project-status files. With 5-10 parallel sessions, this is unworkable.
|
|
124
|
+
|
|
125
|
+
**Lifecycle (deterministic, no opt-in):**
|
|
126
|
+
- **Step 1 (Kickoff)** — after computing `<slug>`, before writing ANY file,
|
|
127
|
+
call `worktree-manager` programmatic `nw-docs` with `{ slug: <slug> }`.
|
|
128
|
+
Save the returned `path` as `$WORKTREE_PATH` in the state file under
|
|
129
|
+
`## Worktree` (path, branch, kind: "docs"). Then `cd "$WORKTREE_PATH"`
|
|
130
|
+
and run `pwd` to verify. From this moment, EVERY file write happens inside
|
|
131
|
+
the worktree. See [discovery-phase.md](references/discovery-phase.md) § Step 1.
|
|
132
|
+
- **Step 0 (Context Recovery)** — when resuming a `/prd` or running
|
|
133
|
+
`/prd-add`, scan `.worktrees/registry.json` for entries with
|
|
134
|
+
`kind: "docs"` matching the slug; if found, `cd` into that worktree
|
|
135
|
+
before scanning for state files. See [discovery-phase.md](references/discovery-phase.md) § Step 0.
|
|
136
|
+
- **Step 7 (Commit & Merge)** — commit happens inside the worktree, then
|
|
137
|
+
`worktree-manager` programmatic `mw-docs` is invoked immediately to
|
|
138
|
+
rebase onto `origin/develop` and land the PRD via the configured
|
|
139
|
+
`git.merge_strategy`. Seamless by default, no confirmation gate (the
|
|
140
|
+
user opted into the full pipeline when they ran `/prd`). If the user
|
|
141
|
+
explicitly says "non mergiare" / "lascia il worktree", honor the
|
|
142
|
+
override and stop after the commit. See [validation-phase.md](references/validation-phase.md) § Step 7.
|
|
143
|
+
|
|
144
|
+
**Path resolution rule (CRITICAL — read carefully).** Claude Code's
|
|
145
|
+
`Write` / `Edit` / `Read` tools require ABSOLUTE paths and **do NOT
|
|
146
|
+
expand shell variables**. All `${paths.X}` references in this skill and
|
|
147
|
+
its phase references are relative to the worktree for the entire
|
|
148
|
+
session — but you must construct the final absolute path **textually
|
|
149
|
+
by concatenation**, never by passing the literal string `$WORKTREE_PATH`
|
|
150
|
+
to a tool call.
|
|
151
|
+
|
|
152
|
+
The variable name `$WORKTREE_PATH` used throughout this document is a
|
|
153
|
+
**placeholder for the absolute path returned by `nw-docs` at Step 1**
|
|
154
|
+
(e.g. `/Users/alice/my-project/.worktrees/prd-menu-info`). Substitute
|
|
155
|
+
that absolute path before every Write/Edit. Worked example:
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
# State: nw-docs returned path="/Users/alice/my-project/.worktrees/prd-menu-info"
|
|
159
|
+
# Goal: write PRD.md for slug=menu-info
|
|
160
|
+
|
|
161
|
+
# ❌ WRONG #1 — writes to main repo, defeats isolation:
|
|
162
|
+
Write(file_path="/Users/alice/my-project/docs/prd/menu-info/PRD.md")
|
|
163
|
+
|
|
164
|
+
# ❌ WRONG #2 — literal $WORKTREE_PATH string:
|
|
165
|
+
Write(file_path="$WORKTREE_PATH/docs/prd/menu-info/PRD.md")
|
|
166
|
+
# Claude Code rejects ("path must be absolute") or creates a literal
|
|
167
|
+
# directory named "$WORKTREE_PATH" in the current cwd.
|
|
168
|
+
|
|
169
|
+
# ❌ WRONG #3 — relative path (also rejected by Write/Edit):
|
|
170
|
+
Write(file_path="docs/prd/menu-info/PRD.md")
|
|
171
|
+
|
|
172
|
+
# ✅ RIGHT — substitute the absolute path you got from nw-docs:
|
|
173
|
+
Write(file_path="/Users/alice/my-project/.worktrees/prd-menu-info/docs/prd/menu-info/PRD.md")
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Before every Write/Edit, mentally check: "does this path string start
|
|
177
|
+
with the absolute `nw-docs` path I saved at Step 1?" If not, you've
|
|
178
|
+
broken isolation. The exception is `/tmp/...` paths used for transient
|
|
179
|
+
reports (e.g., audit phase Step 2 step f) — those are intentionally
|
|
180
|
+
outside any worktree.
|
|
181
|
+
|
|
182
|
+
**Forbidden operations during the session:**
|
|
183
|
+
- `git checkout` / `git switch` / `git branch` on the main repo (worktree-manager Safety Rules).
|
|
184
|
+
- `git stash` anywhere (shared `refs/stash` across worktrees — see Safety Rules in worktree-manager).
|
|
185
|
+
- Writing to the main repo's `${paths.prd_dir}`, `${paths.backlog_dir}`,
|
|
186
|
+
or `${paths.references_dir}` directly. Only the merge in Step 7 touches `develop`.
|
|
187
|
+
|
|
188
|
+
**Exception — when the worktree cannot be created.** If `git worktree add`
|
|
189
|
+
fails (e.g., `.worktrees/` not in `.gitignore`, disk full, repo not a git
|
|
190
|
+
repository, or the consumer has explicitly disabled docs worktrees via
|
|
191
|
+
overlay), STOP and report the error to the user. Do NOT silently fall back
|
|
192
|
+
to writing on the main repo — that defeats the entire purpose of this rule.
|
|
193
|
+
|
|
111
194
|
---
|
|
112
195
|
|
|
113
196
|
## TEMPLATES
|
|
@@ -121,12 +204,16 @@ Use these templates when creating artifacts:
|
|
|
121
204
|
| Backlog epic (always 1) | [assets/epic-template.yml](assets/epic-template.yml) |
|
|
122
205
|
| Backlog child card (N≥1) | [assets/card-template.yml](assets/card-template.yml) |
|
|
123
206
|
|
|
124
|
-
**State file location:** `${paths.prd_dir}/sessions/YYYY-MM-DD-<slug>-state.md`
|
|
125
|
-
**PRD location:** `${paths.prd_dir}/<slug>/PRD.md`
|
|
126
|
-
**Design location:** `${paths.prd_dir}/<slug>/design.html`
|
|
207
|
+
**State file location:** `$WORKTREE_PATH/${paths.prd_dir}/sessions/YYYY-MM-DD-<slug>-state.md`
|
|
208
|
+
**PRD location:** `$WORKTREE_PATH/${paths.prd_dir}/<slug>/PRD.md`
|
|
209
|
+
**Design location:** `$WORKTREE_PATH/${paths.prd_dir}/<slug>/design.html`
|
|
127
210
|
**Cards location:**
|
|
128
|
-
- Epic: `${paths.backlog_dir}/FEAT-XXXX-00-<slug>-epic.yml` (mandatory when `features.has_backlog: true`)
|
|
129
|
-
- Children: `${paths.backlog_dir}/FEAT-XXXX-NN-<sub-slug>.yml` for N=1..M (at least 1)
|
|
211
|
+
- Epic: `$WORKTREE_PATH/${paths.backlog_dir}/FEAT-XXXX-00-<slug>-epic.yml` (mandatory when `features.has_backlog: true`)
|
|
212
|
+
- Children: `$WORKTREE_PATH/${paths.backlog_dir}/FEAT-XXXX-NN-<sub-slug>.yml` for N=1..M (at least 1)
|
|
213
|
+
|
|
214
|
+
**`$WORKTREE_PATH`** is set in Step 1 (Kickoff) by `worktree-manager nw-docs` —
|
|
215
|
+
see HARD RULE 17. Until Step 1 has run, no file writes are allowed; until then
|
|
216
|
+
the value lives only in the state file `## Worktree` section.
|
|
130
217
|
|
|
131
218
|
---
|
|
132
219
|
|
|
@@ -146,7 +233,7 @@ At the END of every message (after all text, before stopping), display:
|
|
|
146
233
|
| 2 | Design UI & approvazione | ⬜/🔄/✅/⏭️ |
|
|
147
234
|
| 3 | Conferma specifiche | ⬜/🔄/✅ |
|
|
148
235
|
| 4 | Creazione backlog cards | ⬜/🔄/✅ |
|
|
149
|
-
| 5 | Validazione
|
|
236
|
+
| 5 | Validazione, commit & merge | ⬜/🔄/✅ |
|
|
150
237
|
|
|
151
238
|
Comprensione: X% (N/M dimensioni coperte) — ISA: N punti identificati
|
|
152
239
|
Mockup: ⬜ non chiesto / 🔄 in attesa / ✅ N mockup / ⏭️ nessuno
|
|
@@ -231,7 +318,7 @@ Dimension 10 uses a built-in evaluation tree (see discovery-phase.md).
|
|
|
231
318
|
| 2 | Design UI & approvazione | ✅/⏭️ |
|
|
232
319
|
| 3 | Conferma specifiche | ✅ |
|
|
233
320
|
| 4 | Creazione backlog cards | ✅ |
|
|
234
|
-
| 5 | Validazione
|
|
321
|
+
| 5 | Validazione, commit & merge | ✅ |
|
|
235
322
|
|
|
236
323
|
Comprensione: 100%
|
|
237
324
|
Mockup: ✅ N mockup analizzati / ⏭️ nessuno fornito
|
|
@@ -242,9 +329,22 @@ Step 3 mode: full / hybrid / skipped
|
|
|
242
329
|
|
|
243
330
|
---
|
|
244
331
|
|
|
245
|
-
## Metrics Log (MANDATORY —
|
|
332
|
+
## Metrics Log (MANDATORY — runs inside Step 7, BEFORE the commit)
|
|
333
|
+
|
|
334
|
+
After cards are created and audited (Steps 5-6) and BEFORE the explicit stage in
|
|
335
|
+
validation-phase.md Step 7 point 5, log this PRD run to the skill-runs file.
|
|
246
336
|
|
|
247
|
-
|
|
337
|
+
**Location (HARD RULE 17 applies):**
|
|
338
|
+
`$WORKTREE_PATH/docs/metrics/skill-runs.jsonl`
|
|
339
|
+
|
|
340
|
+
The file is committed together with the rest of the PRD artefacts in Step 7,
|
|
341
|
+
so it flows into `develop` via `mw-docs` atomically with the PRD.
|
|
342
|
+
|
|
343
|
+
**Conflict resilience.** JSONL is line-oriented and additive: when two parallel
|
|
344
|
+
PRDs both append a line and one rebases onto the other, the doc-friendly conflict
|
|
345
|
+
protocol in `worktree-manager` step 4b auto-resolves the `.jsonl` conflict by
|
|
346
|
+
keeping both lines (this is the one canonical case where "keep both sides" is
|
|
347
|
+
exactly the correct semantics). No special handling needed.
|
|
248
348
|
|
|
249
349
|
**Steps:**
|
|
250
350
|
|
|
@@ -256,10 +356,13 @@ After cards are created and committed, log this PRD run to `docs/metrics/skill-r
|
|
|
256
356
|
- `has_db_indexes_pct`: % of cards that have a `db_indexes` field (covers any persistence layer; legacy `firestore_indexes` cards count too)
|
|
257
357
|
- `discovery_iterations`: approximate number of Q&A rounds with the user (count AskUserQuestion calls in this session, default 1 if unknown)
|
|
258
358
|
|
|
259
|
-
2.
|
|
359
|
+
2. Append ONE JSON line to `$WORKTREE_PATH/docs/metrics/skill-runs.jsonl`
|
|
360
|
+
(create the file + parent directory if absent):
|
|
260
361
|
|
|
261
362
|
```json
|
|
262
363
|
{"ts":"<ISO-8601-UTC>","skill":"prd","run_id":"prd-<slug>","prd_slug":"<slug>","cards_created":0,"ac_coverage_ratio":0.0,"isa_count":0,"has_test_plan_pct":0.0,"has_db_indexes_pct":0.0,"discovery_iterations":1,"prd_path":"${paths.prd_dir}/<slug>/PRD.md"}
|
|
263
364
|
```
|
|
264
365
|
|
|
265
|
-
|
|
366
|
+
3. Add the file to the explicit stage list in validation-phase.md Step 7 point 6 (the stage list is at point 6; point 5 is the invocation of this very Metrics Log step).
|
|
367
|
+
|
|
368
|
+
**This step is NON-BLOCKING** — if it fails, do not abort. Log "Metrics Log: SKIPPED" in the progress bar. The PRD merge proceeds regardless.
|
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
Created: {{YYYY-MM-DD HH:MM}}
|
|
3
3
|
Status: discovery
|
|
4
4
|
|
|
5
|
+
## Worktree
|
|
6
|
+
- path: {{absolute worktree path returned by worktree-manager nw-docs}}
|
|
7
|
+
- branch: prd/{{slug}}
|
|
8
|
+
- kind: docs
|
|
9
|
+
- created_at: {{ISO-8601 UTC}}
|
|
10
|
+
- merge_commit: (pending — populated by validation-phase Step 7 after mw-docs)
|
|
11
|
+
|
|
5
12
|
## Feature Description
|
|
6
13
|
{{user's description verbatim}}
|
|
7
14
|
|
|
@@ -162,9 +162,16 @@ Agent(
|
|
|
162
162
|
prompt: """
|
|
163
163
|
Generate backlog cards from the approved PRD.
|
|
164
164
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
165
|
+
WORKING_DIRECTORY: <$WORKTREE_PATH absolute path>
|
|
166
|
+
(Per HARD RULE 17 of /prd SKILL.md — all file writes must go inside this
|
|
167
|
+
directory, NOT into the consumer's main repo. See your "Working Directory"
|
|
168
|
+
section for the rule and sanity check.)
|
|
169
|
+
|
|
170
|
+
PRD path: <$WORKTREE_PATH>/<prd_path>
|
|
171
|
+
State file path: <$WORKTREE_PATH>/<state_file_path>
|
|
172
|
+
Card template: <$WORKTREE_PATH>/.claude/skills/prd/assets/card-template.yml
|
|
173
|
+
(the template is symlinked from .framework/ into the worktree just like
|
|
174
|
+
in the main repo — the symlink works inside the worktree)
|
|
168
175
|
Feature slug: <slug>
|
|
169
176
|
|
|
170
177
|
The PRD has been approved by the user. Read it in full, read the state file
|
|
@@ -175,7 +182,7 @@ Agent(
|
|
|
175
182
|
error_handling, reuse_analysis). Populate them per your field-mapping instructions.
|
|
176
183
|
Use Grep/Glob to verify file paths and line numbers for existing_patterns and reuse_analysis.
|
|
177
184
|
|
|
178
|
-
Write all card YAML files to backlog
|
|
185
|
+
Write all card YAML files to <$WORKTREE_PATH>/backlog/ (absolute path).
|
|
179
186
|
Update the state file ## Backlog Cards section with card list and traceability matrices.
|
|
180
187
|
Return the Parallel Execution Map summary.
|
|
181
188
|
""",
|
|
@@ -183,6 +190,12 @@ Agent(
|
|
|
183
190
|
)
|
|
184
191
|
```
|
|
185
192
|
|
|
193
|
+
**Substitution rule.** In the prompt above, `<$WORKTREE_PATH>` is a textual
|
|
194
|
+
placeholder — the `/prd` skill MUST replace it with the absolute path stored
|
|
195
|
+
in the state file's `## Worktree` section BEFORE invoking the agent. Do NOT
|
|
196
|
+
pass the literal string `$WORKTREE_PATH` — the subagent has no shell context
|
|
197
|
+
to expand it.
|
|
198
|
+
|
|
186
199
|
### What the agent handles
|
|
187
200
|
|
|
188
201
|
The `prd-card-writer` agent owns the entire card writing pipeline:
|
|
@@ -4,15 +4,36 @@
|
|
|
4
4
|
|
|
5
5
|
Run BEFORE any other step.
|
|
6
6
|
|
|
7
|
-
1.
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
1. **Worktree lookup (since v3.22.0)** — read `.worktrees/registry.json` from
|
|
8
|
+
the main repo and scan for an entry with `kind: "docs"` whose `slug` matches
|
|
9
|
+
the feature the user just mentioned (or that you can infer from their
|
|
10
|
+
message — e.g., `/prd-add` for an active PRD).
|
|
11
|
+
- **Found**: `cd` into the worktree's `path` (save as `$WORKTREE_PATH`),
|
|
12
|
+
log "Resuming PRD session in worktree `<path>`", then continue to step 2.
|
|
13
|
+
All subsequent file paths in this skill resolve under `$WORKTREE_PATH`
|
|
14
|
+
(HARD RULE 17).
|
|
15
|
+
- **Not found, but main repo has a stale state file** at
|
|
16
|
+
`${paths.prd_dir}/sessions/*-<slug>-state.md`: this is a pre-v3.22.0 PRD
|
|
17
|
+
session created before the worktree mandate. ASK the user: "Found a
|
|
18
|
+
legacy PRD state file outside any worktree. Migrate it to a fresh docs
|
|
19
|
+
worktree before resuming, or continue on the main repo (legacy mode)?"
|
|
20
|
+
If migrate: create the worktree via `nw-docs`, `git mv` the relevant
|
|
21
|
+
files into it. If legacy mode: STOP and warn that parallel sessions
|
|
22
|
+
will pollute `git status`.
|
|
23
|
+
- **Not found and no state file**: fresh session, proceed to Step 1.
|
|
24
|
+
2. With `$WORKTREE_PATH` resolved (or null for fresh sessions), check if
|
|
25
|
+
`$WORKTREE_PATH/${paths.prd_dir}/sessions/` contains a state file for the
|
|
26
|
+
current feature.
|
|
27
|
+
3. If found: read it, identify last completed step, resume from next pending step.
|
|
28
|
+
4. If not found: proceed to Step 1.
|
|
29
|
+
|
|
30
|
+
Triggers: session start, context compression, re-invocation of `/prd`, every
|
|
31
|
+
`/prd-add` invocation.
|
|
12
32
|
|
|
13
33
|
## Step 1 — Kickoff
|
|
14
34
|
|
|
15
|
-
**Precondition:** user has described the feature
|
|
35
|
+
**Precondition:** user has described the feature; Step 0 ran and confirmed
|
|
36
|
+
this is a fresh session (no existing state file).
|
|
16
37
|
|
|
17
38
|
1. Derive `<slug>`: kebab-case, lowercase, max 40 chars, no special chars.
|
|
18
39
|
Example: "Nutritional info on menu" -> `menu-nutritional-info`
|
|
@@ -22,16 +43,44 @@ Triggers: session start, context compression, re-invocation of `/prd`.
|
|
|
22
43
|
`## Obsidian Spec Note: [[Note Name]]`. This will be added to Canonical Sources in the PRD.
|
|
23
44
|
- Read the note content from the vault path in memory (`reference_obsidian_vault.md`)
|
|
24
45
|
to pre-populate discovery dimensions where possible — treat it as a user-provided spec.
|
|
25
|
-
3. Create
|
|
26
|
-
|
|
27
|
-
|
|
46
|
+
3. **Create the docs worktree (MANDATORY — HARD RULE 17)** — invoke the
|
|
47
|
+
`worktree-manager` skill in programmatic docs mode BEFORE any file write:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
Skill: worktree-manager
|
|
51
|
+
Mode: programmatic, nw-docs
|
|
52
|
+
Input: { "slug": "<slug>" }
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
On success the skill returns `{ path, branch, kind: "docs" }`. Save
|
|
56
|
+
`path` as `$WORKTREE_PATH` for the entire session.
|
|
57
|
+
|
|
58
|
+
Verify the working directory is the worktree:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
cd "$WORKTREE_PATH"
|
|
62
|
+
pwd
|
|
63
|
+
# MUST print the absolute worktree path. If pwd shows the main repo root,
|
|
64
|
+
# STOP — every Write/Edit you make next will pollute the main checkout.
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Failure handling.** If `nw-docs` fails (e.g., `.worktrees/` not in
|
|
68
|
+
`.gitignore`, slug already in registry as a non-docs entry, repo not
|
|
69
|
+
initialized), STOP and surface the error verbatim. Do NOT fall back to
|
|
70
|
+
writing on the main repo — that breaks HARD RULE 17.
|
|
71
|
+
|
|
72
|
+
4. **Create state file** inside the worktree:
|
|
73
|
+
`$WORKTREE_PATH/${paths.prd_dir}/sessions/YYYY-MM-DD-<slug>-state.md`
|
|
74
|
+
using template from `assets/state-template.md`. Populate the `## Worktree`
|
|
75
|
+
section with `path`, `branch`, `kind: docs`, `created_at` (ISO-8601 UTC).
|
|
76
|
+
5. Create 5 macro-tasks via TaskCreate:
|
|
28
77
|
- `[PRD] Discovery & comprensione feature`
|
|
29
78
|
- `[PRD] Design UI & approvazione`
|
|
30
79
|
- `[PRD] Conferma specifiche complete`
|
|
31
80
|
- `[PRD] Creazione backlog cards`
|
|
32
|
-
- `[PRD] Validazione
|
|
33
|
-
|
|
34
|
-
|
|
81
|
+
- `[PRD] Validazione, commit & merge`
|
|
82
|
+
6. Mark task 1 as `in_progress`.
|
|
83
|
+
7. **Context Loading (MANDATORY):** invoke the context-primer skill (`/cont`) with
|
|
35
84
|
2-4 keywords extracted from the user's feature description. This launches
|
|
36
85
|
`codebase-architect` which searches the Obsidian-first LightRAG MCP index,
|
|
37
86
|
docs, backlog, source code, and git history. The returned context informs all
|
|
@@ -39,10 +88,10 @@ Triggers: session start, context compression, re-invocation of `/prd`.
|
|
|
39
88
|
feature domain. Use Obsidian hits for concept context, then verify
|
|
40
89
|
implementation and stateful claims against repo docs/code before carrying
|
|
41
90
|
them into the PRD.
|
|
42
|
-
|
|
91
|
+
8. Mark clearly irrelevant dimensions as "N/A" with reason
|
|
43
92
|
(e.g., backend-only -> UI impact = N/A).
|
|
44
93
|
If UI impact is N/A, immediately mark task 2 as `completed` ("Skipped — no UI").
|
|
45
|
-
|
|
94
|
+
9. **Business Rationale Extraction (MANDATORY):** Before entering the discovery loop,
|
|
46
95
|
evaluate the user's initial feature description for business rationale signals:
|
|
47
96
|
- WHY is this feature needed? (business motivation)
|
|
48
97
|
- What customer/market signal triggered it?
|
|
@@ -59,10 +108,16 @@ Triggers: session start, context compression, re-invocation of `/prd`.
|
|
|
59
108
|
**Output:**
|
|
60
109
|
|
|
61
110
|
```
|
|
62
|
-
Ho creato la sessione PRD per **<slug
|
|
111
|
+
Ho creato la sessione PRD per **<slug>** in un worktree dedicato.
|
|
63
112
|
|
|
113
|
+
Worktree: <relative-worktree-path>
|
|
114
|
+
Branch: prd/<slug>
|
|
64
115
|
Descrizione: <user's description>
|
|
65
|
-
Contesto
|
|
116
|
+
Contesto: <one-line summary from context-primer>
|
|
117
|
+
|
|
118
|
+
Tutti i file del PRD vivono nel worktree — il main repo resta pulito.
|
|
119
|
+
Al termine commit + merge automatico in develop + cleanup worktree, seamless.
|
|
120
|
+
(Se in qualunque momento mi dici "non mergiare", mi fermo dopo il commit.)
|
|
66
121
|
|
|
67
122
|
Ora comincio la fase di **Discovery** — ti faro delle domande per capire bene
|
|
68
123
|
la feature prima di scrivere qualsiasi documento.
|
|
@@ -70,7 +125,9 @@ la feature prima di scrivere qualsiasi documento.
|
|
|
70
125
|
<Progress Bar>
|
|
71
126
|
```
|
|
72
127
|
|
|
73
|
-
**Gate:**
|
|
128
|
+
**Gate:** docs worktree created (registry entry with `kind: "docs"` present)
|
|
129
|
+
AND state file exists on disk inside the worktree AND all tasks created AND
|
|
130
|
+
context loaded.
|
|
74
131
|
|
|
75
132
|
**Immediately proceed to Step 1.6** — do NOT stop here. Show the kickoff message
|
|
76
133
|
and ask the mockup intake question in the same turn.
|
|
@@ -86,7 +143,7 @@ result.
|
|
|
86
143
|
|
|
87
144
|
### 1.6.1 — Ask
|
|
88
145
|
|
|
89
|
-
After the kickoff output (Step 1, point
|
|
146
|
+
After the kickoff output (Step 1, point 9 — Business Rationale Extraction is the final point of the Kickoff step since the v3.22.0 renumbering), append this question to the SAME message:
|
|
90
147
|
|
|
91
148
|
```
|
|
92
149
|
### Domanda — Mockup
|
|
@@ -118,6 +118,13 @@ The skill handles the full pipeline:
|
|
|
118
118
|
|
|
119
119
|
When invoking `ui-design`, ensure it has access to:
|
|
120
120
|
|
|
121
|
+
- **`WORKING_DIRECTORY`** — the absolute path of the PRD's docs worktree,
|
|
122
|
+
read from the state file `## Worktree` section. Pass it explicitly in the
|
|
123
|
+
args (e.g. `WORKING_DIRECTORY=<absolute-path-of-$WORKTREE_PATH>`) so the
|
|
124
|
+
skill's Step G saves `design.html` inside the worktree, not into the
|
|
125
|
+
consumer's main repo. Without this, the design lands on main, the `/prd`
|
|
126
|
+
Step 7 stage list can't find it, and the merged PRD ships without its
|
|
127
|
+
design asset. See `ui-design/SKILL.md` § "Working Directory" (added v3.22.0).
|
|
121
128
|
- Feature description (from state file `## Feature Description`)
|
|
122
129
|
- All discovery answers relevant to UI (from state file `## Discovery Log`)
|
|
123
130
|
- The `<slug>` for file naming
|
|
@@ -49,34 +49,115 @@ Mark task 5 as `in_progress`.
|
|
|
49
49
|
|
|
50
50
|
**Gate:** all HIGH/MEDIUM findings resolved, no open `[MANUAL]` items.
|
|
51
51
|
|
|
52
|
-
## Step 7 — Resolution
|
|
52
|
+
## Step 7 — Resolution, Commit & Merge
|
|
53
53
|
|
|
54
|
-
**Precondition:** Step 6 complete
|
|
54
|
+
**Precondition:** Step 6 complete; the session is running inside a docs worktree
|
|
55
|
+
created by Step 1 (HARD RULE 17). `$WORKTREE_PATH` is set in the state file.
|
|
55
56
|
|
|
56
57
|
### Resolve remaining items
|
|
57
58
|
|
|
58
59
|
1. If `[MANUAL]` items remain: resolve each one.
|
|
59
60
|
2. If resolution required card re-edits: re-run the audit protocol (audit-phase.md) on affected cards.
|
|
60
61
|
|
|
61
|
-
### Update knowledge base
|
|
62
|
-
|
|
63
|
-
3. Add/update entry in `${paths.references_dir}/ssot-registry.md`
|
|
64
|
-
as canonical source for this macro feature.
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
-
|
|
71
|
-
- `
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
-
|
|
75
|
-
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
62
|
+
### Update knowledge base (inside the worktree)
|
|
63
|
+
|
|
64
|
+
3. Add/update entry in `$WORKTREE_PATH/${paths.references_dir}/ssot-registry.md`
|
|
65
|
+
pointing to the new PRD as canonical source for this macro feature. **Skip
|
|
66
|
+
when the file does not exist in the project** (some consumers don't maintain
|
|
67
|
+
one — check the path before writing).
|
|
68
|
+
4. Update `$WORKTREE_PATH/${paths.references_dir}/project-status.md` Active Code
|
|
69
|
+
Context with PRD completion. **Skip when the file does not exist.**
|
|
70
|
+
|
|
71
|
+
**Note on cross-PRD collisions.** Both files (`ssot-registry.md` and
|
|
72
|
+
`project-status.md`) live on `develop` and are touched by other PRD sessions
|
|
73
|
+
in parallel. The rebase in step 8 below brings the worktree up to the latest
|
|
74
|
+
`origin/develop` BEFORE the merge, so two parallel PRDs ending at the same
|
|
75
|
+
time produce a clean append-only diff in most cases. If the rebase reports
|
|
76
|
+
conflicts on these two files specifically, the `worktree-manager mw-docs`
|
|
77
|
+
protocol stops and asks for manual resolution — do NOT auto-strip merge
|
|
78
|
+
markers on structured files like these.
|
|
79
|
+
|
|
80
|
+
### Commit (inside the worktree)
|
|
81
|
+
|
|
82
|
+
5. **Run the Metrics Log step from SKILL.md** ("Metrics Log — MANDATORY") FIRST
|
|
83
|
+
— it appends the run summary to `$WORKTREE_PATH/docs/metrics/skill-runs.jsonl`,
|
|
84
|
+
which must be part of the same commit. Non-blocking: if it fails, log
|
|
85
|
+
"Metrics Log: SKIPPED" in the progress bar and continue.
|
|
86
|
+
|
|
87
|
+
6. Stage ONLY PRD session artefacts by explicit file name (NEVER `git add .`
|
|
88
|
+
or `git add -A`):
|
|
89
|
+
- `$WORKTREE_PATH/${paths.prd_dir}/sessions/YYYY-MM-DD-<slug>-state.md`
|
|
90
|
+
- `$WORKTREE_PATH/${paths.prd_dir}/<slug>/PRD.md`
|
|
91
|
+
- `$WORKTREE_PATH/${paths.prd_dir}/<slug>/design.html` (if exists)
|
|
92
|
+
- `$WORKTREE_PATH/${paths.prd_dir}/<slug>/mockups/**` (if any)
|
|
93
|
+
- `$WORKTREE_PATH/${paths.backlog_dir}/FEAT-XXXX-*.yml` (all cards from Step 5)
|
|
94
|
+
- `$WORKTREE_PATH/${paths.references_dir}/ssot-registry.md` (if updated)
|
|
95
|
+
- `$WORKTREE_PATH/${paths.references_dir}/project-status.md` (if updated)
|
|
96
|
+
- `$WORKTREE_PATH/docs/metrics/skill-runs.jsonl` (if the Metrics Log step in 5 wrote a line)
|
|
97
|
+
|
|
98
|
+
Verify staged set with `git -C "$WORKTREE_PATH" diff --staged --name-only`.
|
|
99
|
+
|
|
100
|
+
7. Update state file: status -> `completed`, add `worktree.branch`, will fill
|
|
101
|
+
commit hash after the commit lands.
|
|
102
|
+
|
|
103
|
+
8. Commit with format: `[PRD] <slug>: <brief description>`
|
|
104
|
+
```bash
|
|
105
|
+
git -C "$WORKTREE_PATH" commit -m "[PRD] <slug>: <brief description>"
|
|
106
|
+
```
|
|
107
|
+
Capture the SHA via `git -C "$WORKTREE_PATH" rev-parse HEAD` and write it
|
|
108
|
+
back into the state file under `## Validation`.
|
|
109
|
+
|
|
110
|
+
### Merge into develop (worktree-manager mw-docs)
|
|
111
|
+
|
|
112
|
+
9. **Invoke `worktree-manager` programmatic mw-docs immediately** — no
|
|
113
|
+
confirmation prompt. The user opted into the full PRD pipeline when they
|
|
114
|
+
ran `/prd`; chiedere conferma a fine sessione è friction inutile e rompe
|
|
115
|
+
il "seamless" che è il punto della v3.22.0.
|
|
116
|
+
|
|
117
|
+
The merge is recoverable: if something goes wrong post-merge the user can
|
|
118
|
+
`git revert` on develop just like any other commit. The hard-to-reverse
|
|
119
|
+
operations (`git push`, branch deletion) happen inside `mw-docs` which
|
|
120
|
+
has its own failure handling (rebase abort, push rejection, gh CLI error)
|
|
121
|
+
— none of which silently corrupts state.
|
|
122
|
+
|
|
123
|
+
**Escape hatch.** If the user explicitly says "non mergiare" or "lascia il
|
|
124
|
+
worktree" at any point during Step 7 (e.g. they want to review the PRD
|
|
125
|
+
manually before it lands on develop), respect that and STOP after the
|
|
126
|
+
commit — the worktree stays on disk, ready for a future manual `/mw` or
|
|
127
|
+
`worktree-manager mw-docs`. This is a user-initiated override, not a
|
|
128
|
+
default gate.
|
|
129
|
+
|
|
130
|
+
10. **Invoke `worktree-manager` programmatic mw-docs**:
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
Skill: worktree-manager
|
|
134
|
+
Mode: programmatic, mw-docs
|
|
135
|
+
Input: { "worktreePath": "$WORKTREE_PATH" }
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The skill executes:
|
|
139
|
+
- Safety commit (idempotent — likely no-op after step 8).
|
|
140
|
+
- `git fetch origin develop` + `git rebase origin/develop` inside the worktree.
|
|
141
|
+
- Conflict auto-resolution table (see `/mw` step 4b): additive docs/yaml and
|
|
142
|
+
append-only `.jsonl` files auto-resolve; **structured registries**
|
|
143
|
+
(`project-status.md`, `ssot-registry.md`, `field-registry.*`,
|
|
144
|
+
`traceability-matrix.md`, `REGISTRY.md`) abort the rebase and report —
|
|
145
|
+
these must be resolved manually because blindly stripping markers would
|
|
146
|
+
corrupt their internal structure.
|
|
147
|
+
- Merge via the configured `git.merge_strategy` (`pr` or `local-push`).
|
|
148
|
+
- Cleanup: `git worktree remove` + `git branch -d` + registry entry removal.
|
|
149
|
+
- Local develop ref sync (only if main repo HEAD is already `develop`).
|
|
150
|
+
|
|
151
|
+
On success it returns `{ merged: true, mergeCommit, prNumber, strategy,
|
|
152
|
+
worktreeRemoved: true }`.
|
|
153
|
+
|
|
154
|
+
**Failure handling.** If `mw-docs` reports failure (rebase conflicts, push
|
|
155
|
+
rejected, gh CLI error, post-cleanup error): STOP and surface the error
|
|
156
|
+
verbatim. The worktree stays on disk so the user can investigate. Do NOT
|
|
157
|
+
retry automatically — the next attempt should be user-driven.
|
|
158
|
+
|
|
159
|
+
**Gate:** `mw-docs` returned `merged: true` AND `worktreeRemoved: true` AND
|
|
160
|
+
the state file (now on `develop` via the merge) shows `completed`.
|
|
80
161
|
|
|
81
162
|
Mark task 5 as `completed`.
|
|
82
163
|
|
|
@@ -84,9 +165,11 @@ Mark task 5 as `completed`.
|
|
|
84
165
|
|
|
85
166
|
Print final summary:
|
|
86
167
|
|
|
87
|
-
- PRD path
|
|
168
|
+
- PRD path (relative to repo root, e.g. `docs/prd/<slug>/PRD.md`)
|
|
88
169
|
- Design path (if applicable)
|
|
89
170
|
- Card IDs created
|
|
90
|
-
-
|
|
171
|
+
- Branch & merge strategy used
|
|
172
|
+
- PR number (if `strategy = pr`) or merge SHA (if `local-push`)
|
|
173
|
+
- Confirmation that the worktree was cleaned up
|
|
91
174
|
|
|
92
175
|
Display completed Progress Bar.
|
|
@@ -64,11 +64,54 @@ Sequential, single-turn analysis + selective multi-turn re-execution.
|
|
|
64
64
|
|
|
65
65
|
## Step 0 — Session Locate
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
67
|
+
**Since v3.22.0, active PRD sessions live inside docs worktrees** created by
|
|
68
|
+
`/prd` Step 1 (HARD RULE 17 of `/prd` SKILL.md). The main repo's
|
|
69
|
+
`${paths.prd_dir}/sessions/` may be EMPTY even when there are active sessions
|
|
70
|
+
— each one lives at `<docs-worktree>/${paths.prd_dir}/sessions/`. This step
|
|
71
|
+
must scan the worktree registry FIRST, then fall back to the main repo for
|
|
72
|
+
legacy sessions.
|
|
73
|
+
|
|
74
|
+
1. **Read `.worktrees/registry.json` from the main repo root.** Filter entries
|
|
75
|
+
with `kind: "docs"`. For each, list state files at
|
|
76
|
+
`<entry.path>/${paths.prd_dir}/sessions/*.md` and read the first line of
|
|
77
|
+
each to extract `status:` (or scan for `Status:` line — depends on
|
|
78
|
+
state-template.md format). Collect every state with `status != "completed"`
|
|
79
|
+
together with its `WORKING_DIRECTORY` = `<entry.path>` and `branch` =
|
|
80
|
+
`<entry.branch>`.
|
|
81
|
+
|
|
82
|
+
2. **Also list `${paths.prd_dir}/sessions/` on the main repo** (legacy
|
|
83
|
+
pre-v3.22.0 sessions). Collect any state files there as candidates with
|
|
84
|
+
`WORKING_DIRECTORY` = main repo root.
|
|
85
|
+
|
|
86
|
+
3. Merge the two lists. Behavior:
|
|
87
|
+
- **Exactly ONE active session**: use it. Save its `WORKING_DIRECTORY` and
|
|
88
|
+
`branch` for every subsequent step.
|
|
89
|
+
- **Multiple active sessions**: ask the user which one, surfacing
|
|
90
|
+
`WORKING_DIRECTORY` (worktree path or "main repo") in the choice list so
|
|
91
|
+
they know where the CR will be written.
|
|
92
|
+
- **Zero sessions**: inform user, suggest `/prd` instead.
|
|
93
|
+
|
|
94
|
+
4. **`cd "$WORKING_DIRECTORY"`** before any read or write — every subsequent
|
|
95
|
+
step in this skill (intake → impact analysis → selective execution → delta
|
|
96
|
+
commit) MUST happen inside the selected session's directory.
|
|
97
|
+
|
|
98
|
+
5. Read the state file AND the PRD document (if exists), both resolved under
|
|
99
|
+
`$WORKING_DIRECTORY`.
|
|
100
|
+
|
|
101
|
+
6. **Worktree-mode side effects for the rest of the skill:**
|
|
102
|
+
- Step 5 "Delta Commit" stages files inside the worktree and commits with
|
|
103
|
+
`git -C "$WORKING_DIRECTORY" commit`. NEVER `git add` on the main repo.
|
|
104
|
+
- If `prd-card-writer` is re-invoked in Step 4 (Backlog Cards REDO), pass
|
|
105
|
+
`WORKING_DIRECTORY: $WORKING_DIRECTORY` in the prompt — same convention
|
|
106
|
+
as backlog-phase.md (see `framework/.claude/agents/prd-card-writer.md` §
|
|
107
|
+
"Working Directory").
|
|
108
|
+
- If `ui-design` is re-invoked in Step 4 (UI Design REDO), pass
|
|
109
|
+
`WORKING_DIRECTORY=$WORKING_DIRECTORY` as args — same convention as
|
|
110
|
+
ui-design-phase.md.
|
|
111
|
+
- The delta commit is NOT auto-merged. Document the new branch tip in the
|
|
112
|
+
`## Change Requests` section. The user merges with the rest of the PRD
|
|
113
|
+
when they run validation-phase.md Step 7 (`mw-docs` is invoked once per
|
|
114
|
+
PRD, not per CR).
|
|
72
115
|
|
|
73
116
|
---
|
|
74
117
|
|
|
@@ -28,6 +28,26 @@ Evaluation is always performed by a separate agent with fresh context.
|
|
|
28
28
|
|
|
29
29
|
**On missing/empty keys:** ask the user; do not assume defaults. See `framework/agents/project-context.md` § 3.
|
|
30
30
|
|
|
31
|
+
## Working Directory (MANDATORY when invoked from `/prd`, since v3.22.0)
|
|
32
|
+
|
|
33
|
+
When `/prd` Step 3 invokes this skill, the caller passes (or sets as cwd) an
|
|
34
|
+
absolute **`WORKING_DIRECTORY`** that points to the PRD's docs worktree
|
|
35
|
+
(e.g. `/Users/alice/proj/.worktrees/prd-menu-info`). All persistent design
|
|
36
|
+
artefacts produced by this skill — most notably the `design.html` saved in
|
|
37
|
+
Step G — MUST be written inside that directory, NOT into the consumer's main
|
|
38
|
+
checkout. Without this, the design lands on the main repo, the `/prd` Step 7
|
|
39
|
+
stage list at `$WORKTREE_PATH/${paths.prd_dir}/<slug>/design.html` finds
|
|
40
|
+
nothing, and the PRD merged into `develop` ships without its design asset.
|
|
41
|
+
|
|
42
|
+
**Rule:** every `${paths.prd_dir}/...` reference in this document — including
|
|
43
|
+
Step G's "Copy approved HTML to `${paths.prd_dir}/<slug>/design.html`" — is
|
|
44
|
+
relative to `WORKING_DIRECTORY` when invoked from `/prd`. Construct the
|
|
45
|
+
absolute target path as `<WORKING_DIRECTORY>/<paths.prd_dir>/<slug>/design.html`
|
|
46
|
+
before any `Write`.
|
|
47
|
+
|
|
48
|
+
**Standalone invocations** (when the user runs `/ui-design` directly, no PRD
|
|
49
|
+
worktree): fall back to the consumer root. No prefix needed.
|
|
50
|
+
|
|
31
51
|
---
|
|
32
52
|
|
|
33
53
|
## Prerequisites — BLOCKING reads before ANY design work
|
|
@@ -141,7 +161,7 @@ Invoke a **separate** `code-reviewer` agent (NOT the same agent that generated):
|
|
|
141
161
|
|
|
142
162
|
Read [references/inventory.md](references/inventory.md).
|
|
143
163
|
|
|
144
|
-
1. Copy approved HTML to `${paths.prd_dir}/<slug>/design.html` (if `features.has_prd_workflow: true`; otherwise ask the user where to persist the design).
|
|
164
|
+
1. Copy approved HTML to `${paths.prd_dir}/<slug>/design.html` (if `features.has_prd_workflow: true`; otherwise ask the user where to persist the design). **When invoked from `/prd` (since v3.22.0), prefix this with `WORKING_DIRECTORY` — see the "Working Directory" section near the top of this file.** Concrete absolute target: `<WORKING_DIRECTORY>/<paths.prd_dir>/<slug>/design.html`.
|
|
145
165
|
2. Extract UI Element Inventory (sprint contract).
|
|
146
166
|
3. Update state file with chosen option, design decisions, component lists.
|
|
147
167
|
4. Clean up `/tmp/prd-design-<slug>/`.
|
|
@@ -45,6 +45,207 @@ Output: `{ path: string, branch: string, port: number }`
|
|
|
45
45
|
Input: `{ worktreePath: string, checksAlreadyPassed?: boolean }`
|
|
46
46
|
Output: `{ merged: boolean, developVerified: boolean, prNumber: number|null, mergeCommit: string, strategy: "pr"|"local-push" }`
|
|
47
47
|
|
|
48
|
+
## Programmatic API — docs mode (for /prd orchestrator)
|
|
49
|
+
|
|
50
|
+
The docs mode is the **lean** counterpart to `/nw` and `/mw`. It is intentionally
|
|
51
|
+
stripped down for skills that produce **documentation artefacts only** — PRDs,
|
|
52
|
+
backlog cards, design references — and never touch source code.
|
|
53
|
+
|
|
54
|
+
What docs mode SKIPS vs the standard flow:
|
|
55
|
+
- No `npm install` (no `node_modules/` inside the worktree)
|
|
56
|
+
- No port allocation (no dev server)
|
|
57
|
+
- No `.env`/`.env.local` copy
|
|
58
|
+
- No `npm run build` baseline verification
|
|
59
|
+
- No lint / tsc baseline checks
|
|
60
|
+
- No `--dev` server bootstrap
|
|
61
|
+
- No build / lint / tsc gates at merge time
|
|
62
|
+
|
|
63
|
+
What docs mode KEEPS:
|
|
64
|
+
- Pre-flight `git fetch origin develop` (read-only on the main repo).
|
|
65
|
+
- `git worktree add` branched from `origin/develop`.
|
|
66
|
+
- Registry entry with `kind: "docs"` so `/lw` and `/cw` can list and clean docs worktrees alongside code worktrees.
|
|
67
|
+
- Safety commit at merge time (uncommitted files are never lost).
|
|
68
|
+
- Rebase onto `origin/develop` before merging (prevents PR/FF conflicts).
|
|
69
|
+
- The configured `git.merge_strategy` (`pr` or `local-push`).
|
|
70
|
+
- Cleanup of worktree + local branch + remote branch after merge.
|
|
71
|
+
|
|
72
|
+
Cost target: **< 5 seconds** to create a docs worktree on a typical machine (no
|
|
73
|
+
network beyond the `fetch`, no install, no build). Compare to `/nw` which can
|
|
74
|
+
run for minutes due to `npm install` + build.
|
|
75
|
+
|
|
76
|
+
### nw-docs programmatic
|
|
77
|
+
|
|
78
|
+
Input:
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"slug": "string", // REQUIRED — kebab-case feature slug
|
|
82
|
+
"branchPrefix": "string" // OPTIONAL — defaults to "prd/"
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Output:
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"path": "string", // absolute worktree path
|
|
90
|
+
"branch": "string", // e.g. "prd/menu-nutritional-info"
|
|
91
|
+
"kind": "docs"
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Steps (run exactly these, nothing else):**
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# 0. Pre-flight: .gitignore safety check (MANDATORY — Safety Rules
|
|
99
|
+
# "Always verify .worktrees/ is in .gitignore before creating").
|
|
100
|
+
# Without this, the worktree IS git-tracked: `git status` on the main
|
|
101
|
+
# repo explodes with every file inside the worktree, exactly defeating
|
|
102
|
+
# the parallel-isolation purpose of the docs-mode.
|
|
103
|
+
MAIN_ROOT="$(git rev-parse --show-toplevel)"
|
|
104
|
+
if [ ! -f "$MAIN_ROOT/.gitignore" ] || ! grep -qE '^\.worktrees/?$' "$MAIN_ROOT/.gitignore"; then
|
|
105
|
+
echo "ERROR: .worktrees/ is not in $MAIN_ROOT/.gitignore" >&2
|
|
106
|
+
echo "Add it before running nw-docs: echo '.worktrees/' >> .gitignore" >&2
|
|
107
|
+
echo "(or invoke this skill with --auto-ignore to append it for you — not yet implemented)" >&2
|
|
108
|
+
exit 1
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
# 1. Pre-flight — read-only fetch, NEVER touches main repo HEAD
|
|
112
|
+
git fetch origin develop
|
|
113
|
+
|
|
114
|
+
# 2. Duplicate check — read registry; if an entry with the same slug AND kind=docs
|
|
115
|
+
# exists, return the existing { path, branch, kind } instead of creating a new
|
|
116
|
+
# one (resume semantics — Step 0 of /prd needs this).
|
|
117
|
+
# If an entry with same slug AND kind != "docs" exists (code worktree
|
|
118
|
+
# collision), fail loudly — never silently coexist.
|
|
119
|
+
|
|
120
|
+
# 3. Create the worktree. The path returned MUST be ABSOLUTE — Claude Code's
|
|
121
|
+
# Write/Edit require absolute paths, and downstream skills (/prd, ui-design,
|
|
122
|
+
# prd-card-writer) interpolate this path verbatim.
|
|
123
|
+
SLUG="<slug>"
|
|
124
|
+
BRANCH_PREFIX="${branchPrefix:-prd/}"
|
|
125
|
+
BRANCH="${BRANCH_PREFIX}${SLUG}"
|
|
126
|
+
WORKTREE_REL=".worktrees/prd-${SLUG}"
|
|
127
|
+
WORKTREE_PATH="$MAIN_ROOT/$WORKTREE_REL" # absolute, anchored to main repo root
|
|
128
|
+
git -C "$MAIN_ROOT" worktree add "$WORKTREE_REL" -b "$BRANCH" origin/develop
|
|
129
|
+
|
|
130
|
+
# 4. Registry entry — kind: "docs", port: null, buildVerified: null
|
|
131
|
+
# Same registry file (.worktrees/registry.json) as code worktrees.
|
|
132
|
+
# The `path` field MUST hold $WORKTREE_PATH (absolute), not $WORKTREE_REL.
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Registry entry shape for docs worktrees:**
|
|
136
|
+
|
|
137
|
+
```json
|
|
138
|
+
{
|
|
139
|
+
"card": null,
|
|
140
|
+
"cards": [],
|
|
141
|
+
"groupParent": null,
|
|
142
|
+
"slug": "menu-nutritional-info",
|
|
143
|
+
"branch": "prd/menu-nutritional-info",
|
|
144
|
+
"path": "/abs/.worktrees/prd-menu-nutritional-info",
|
|
145
|
+
"port": null,
|
|
146
|
+
"kind": "docs",
|
|
147
|
+
"createdAt": "2026-05-27T10:00:00Z",
|
|
148
|
+
"envSyncedAt": null,
|
|
149
|
+
"buildVerified": null
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**Forbidden in docs mode**: `npm install`, port scan, `.env*` copy, `npm run build`,
|
|
154
|
+
`npx tsc`, `npx eslint`, dev server start, `git checkout`/`switch`/`branch` on main.
|
|
155
|
+
|
|
156
|
+
### mw-docs programmatic
|
|
157
|
+
|
|
158
|
+
Input:
|
|
159
|
+
```json
|
|
160
|
+
{
|
|
161
|
+
"worktreePath": "string", // REQUIRED — absolute path of the docs worktree
|
|
162
|
+
"commitMessage": "string" // OPTIONAL — defaults to "[PRD] <slug>: <generated summary>"
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Output:
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"merged": true,
|
|
170
|
+
"mergeCommit": "string", // SHA of the merge commit (or branch tip in local-push)
|
|
171
|
+
"prNumber": null, // populated only when strategy = "pr"
|
|
172
|
+
"strategy": "pr" | "local-push",
|
|
173
|
+
"worktreeRemoved": true
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**Steps (run exactly these, nothing else):**
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
cd "$WORKTREE_PATH"
|
|
181
|
+
|
|
182
|
+
# 1. Safety commit (MANDATORY — same as /mw step 3, never skippable).
|
|
183
|
+
# Stage every changed and untracked file by explicit name, then commit.
|
|
184
|
+
# For docs worktrees the staged set is typically:
|
|
185
|
+
# - ${paths.prd_dir}/<slug>/PRD.md
|
|
186
|
+
# - ${paths.prd_dir}/<slug>/design.html (if exists)
|
|
187
|
+
# - ${paths.prd_dir}/<slug>/mockups/** (if any)
|
|
188
|
+
# - ${paths.prd_dir}/sessions/YYYY-MM-DD-<slug>-state.md
|
|
189
|
+
# - ${paths.backlog_dir}/FEAT-XXXX-*.yml (all cards)
|
|
190
|
+
# - ${paths.references_dir}/ssot-registry.md (if updated by Step 7)
|
|
191
|
+
# - ${paths.references_dir}/project-status.md (if updated by Step 7)
|
|
192
|
+
# NEVER `git add .` or `git add -A`. NEVER `git stash` (see Safety Rules).
|
|
193
|
+
|
|
194
|
+
# 2. Rebase onto latest develop. Reuses the /mw step 4b conflict-resolution
|
|
195
|
+
# table (additive auto-strip for docs/yaml/jsonl-in-docs-metrics; abort on
|
|
196
|
+
# structured registries when validation fails; abort on code/tests/fixtures).
|
|
197
|
+
#
|
|
198
|
+
# IMPORTANT — NO `git stash` in mw-docs. The safety commit in step 1
|
|
199
|
+
# above guarantees a clean working tree, so the stash logic at the top of
|
|
200
|
+
# /mw step 4b ("stash dirty files before rebase, pop after") is a no-op
|
|
201
|
+
# for mw-docs and must be SKIPPED. Running `git stash push` from a
|
|
202
|
+
# worktree violates the Safety Rule "NEVER use git stash in worktrees"
|
|
203
|
+
# (refs/stash is shared across all worktrees via git.commondir — see the
|
|
204
|
+
# FEAT-0522 incident note). Two parallel mw-docs runs that both stash
|
|
205
|
+
# would race on the shared stash list and could pop into the wrong tree.
|
|
206
|
+
#
|
|
207
|
+
# Direct rebase, no stash. If the working tree is unexpectedly dirty here
|
|
208
|
+
# (someone wrote between step 1 and step 2), STOP and report — a second
|
|
209
|
+
# safety commit would be the right answer, never a stash.
|
|
210
|
+
DIRTY=$(git -C "$WORKTREE_PATH" status --porcelain 2>/dev/null)
|
|
211
|
+
if [ -n "$DIRTY" ]; then
|
|
212
|
+
echo "ERROR: working tree dirty in $WORKTREE_PATH after safety commit." >&2
|
|
213
|
+
echo "Files: $DIRTY" >&2
|
|
214
|
+
echo "Investigate — never stash to recover (refs/stash shared across worktrees)." >&2
|
|
215
|
+
exit 1
|
|
216
|
+
fi
|
|
217
|
+
git -C "$WORKTREE_PATH" fetch origin develop
|
|
218
|
+
git -C "$WORKTREE_PATH" rebase origin/develop
|
|
219
|
+
# (apply /mw 4b conflict-resolution table if rebase reports conflicts)
|
|
220
|
+
|
|
221
|
+
# 3. Land on develop — reuse /mw step 4c verbatim. Read git.merge_strategy from
|
|
222
|
+
# baldart.config.yml. NEVER `git checkout develop` on the main repo.
|
|
223
|
+
# - pr → gh pr create + gh pr merge --merge --delete-branch
|
|
224
|
+
# - local-push → git push origin <branch>:develop (fast-forward only)
|
|
225
|
+
#
|
|
226
|
+
# Note: many consumers prefer `local-push` for docs worktrees specifically,
|
|
227
|
+
# because a PRD is rarely worth a GitHub PR roundtrip. The CLI does not
|
|
228
|
+
# differentiate — it respects the project's configured strategy. If the user
|
|
229
|
+
# wants per-skill strategy, they should override via overlay (.baldart/overlays/prd.md).
|
|
230
|
+
|
|
231
|
+
# 4. Cleanup — reuse /mw step 6 verbatim (worktree remove + branch -d + prune).
|
|
232
|
+
# Skip /mw step 5 (post-merge `npm run build`) — docs worktrees have nothing
|
|
233
|
+
# to build.
|
|
234
|
+
|
|
235
|
+
# 5. Sync local develop ref — reuse /mw "Common" block: ff-only pull when main
|
|
236
|
+
# repo HEAD is already develop; otherwise just fetch.
|
|
237
|
+
|
|
238
|
+
# 6. Remove the registry entry for this worktree.
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**Forbidden in docs merge**: pre-merge `npm run build`, `npx eslint`, `npx tsc`, `npm run test`, post-merge `npm run build`. The whole point of docs mode is that these gates are inapplicable.
|
|
242
|
+
|
|
243
|
+
**Failure handling**: if the safety commit, rebase, or merge fails, STOP and
|
|
244
|
+
report — do NOT proceed to cleanup. The worktree must stay on disk so the user
|
|
245
|
+
can investigate. Cleanup runs only after a successful merge.
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
48
249
|
The merge path depends on `git.merge_strategy` in `baldart.config.yml`:
|
|
49
250
|
- `pr` (default, since v3.4.0): merge via `gh pr create` + `gh pr merge`. `prNumber` is the PR number, `mergeCommit` is the SHA returned by the GitHub merge API.
|
|
50
251
|
- `local-push` (since v3.9.0): direct fast-forward push of the rebased feature branch to `origin/develop` — no PR, no `gh`. `prNumber` is `null`, `mergeCommit` is the local SHA of the feature branch tip.
|
|
@@ -412,25 +613,97 @@ fi
|
|
|
412
613
|
CONFLICTED=$(git diff --name-only --diff-filter=U)
|
|
413
614
|
```
|
|
414
615
|
|
|
415
|
-
Categorize each conflicted file and resolve
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
|
421
|
-
|
|
616
|
+
Categorize each conflicted file and resolve. **Per-file rule of thumb**:
|
|
617
|
+
auto-resolve only when "keep both sides" is semantically additive (markdown
|
|
618
|
+
bullet lists, YAML lists, JSONL append-only logs); abort on anything with
|
|
619
|
+
internal structure (tables, key/value blocks, code).
|
|
620
|
+
|
|
621
|
+
| Category | Patterns | Action | Note |
|
|
622
|
+
|----------|----------|--------|------|
|
|
623
|
+
| **Structured registries** | `project-status.md`, `ssot-registry.md`, `field-registry.*`, `traceability-matrix.md`, `REGISTRY.md` | Strip markers, then **structural validation** — if valid, accept; if invalid, abort | The auto-strip "keep both sides" usually produces an additive result (new bullet rows appended to a table or section). The validation step catches the rare case where the two sides modified the same row. See `validate_structured_md` below. |
|
|
624
|
+
| **JSONL logs under `docs/metrics/`** | `docs/metrics/*.jsonl`, `docs/metrics/**/*.jsonl` | Auto-resolve: strip markers, keep both sides | JSONL is line-oriented and additive — duplicating both branches' lines yields a valid file. |
|
|
625
|
+
| **Other `.jsonl`** | `*.jsonl` outside `docs/metrics/` | STOP — abort and report | Fixtures, seeds, training data: auto-strip can corrupt them. The user must inspect. |
|
|
626
|
+
| **Docs/config** | `docs/**/*.md`, `backlog/*.yml`, `*.md` outside `src/`, `*.json`/`*.yml` outside `src/` (excluding rows above) | Auto-resolve: strip markers, keep both sides | The canonical additive case. |
|
|
627
|
+
| **Code** | `src/**/*.ts`, `*.tsx`, `*.js`, `*.jsx` | STOP — abort rebase, report to user | |
|
|
628
|
+
| **Tests** | `*.test.*`, `*.spec.*` | Manual only — report to user | |
|
|
629
|
+
|
|
630
|
+
The "Structured registries" row replaces the v3.22.0-initial blanket-abort
|
|
631
|
+
behaviour. The blanket abort regressed the `/new` flow (every multi-card batch
|
|
632
|
+
that updates `ssot-registry.md` would fail rebase); the validation-based
|
|
633
|
+
approach restores the additive merge for the routine case while still
|
|
634
|
+
catching genuine corruption.
|
|
422
635
|
|
|
423
636
|
```bash
|
|
637
|
+
# Helper: validate that a structured markdown file is still parseable after
|
|
638
|
+
# auto-strip. Cheap heuristics; returns 0 if file looks structurally intact.
|
|
639
|
+
validate_structured_md() {
|
|
640
|
+
local f="$1"
|
|
641
|
+
# Reject if any residual conflict markers (shouldn't happen after sed)
|
|
642
|
+
if grep -qE '^(<{7}|={7}|>{7})' "$f"; then return 1; fi
|
|
643
|
+
# Reject if a top-level markdown table got duplicated header rows back-to-back
|
|
644
|
+
# (two `|---|---|` separator lines in a row = malformed table).
|
|
645
|
+
if awk 'prev~/^\|[ -:|]+\|$/ && $0~/^\|[ -:|]+\|$/{found=1; exit} {prev=$0} END{exit !found}' "$f"; then
|
|
646
|
+
return 1
|
|
647
|
+
fi
|
|
648
|
+
# Reject if a YAML frontmatter block (--- ... ---) got duplicated.
|
|
649
|
+
if [ "$(grep -cE '^---[[:space:]]*$' "$f")" -gt 2 ]; then return 1; fi
|
|
650
|
+
return 0
|
|
651
|
+
}
|
|
652
|
+
|
|
424
653
|
for FILE in $CONFLICTED; do
|
|
654
|
+
BASENAME=$(basename "$FILE")
|
|
655
|
+
|
|
656
|
+
# 1. Code / tests — always abort
|
|
425
657
|
case "$FILE" in
|
|
426
658
|
src/*.ts|src/*.tsx|src/*.js|src/*.jsx|*.test.*|*.spec.*)
|
|
427
|
-
# Code or test conflict — abort and report
|
|
428
659
|
git rebase --abort
|
|
660
|
+
# When invoked from /mw (code worktree) a stash may have been created
|
|
661
|
+
# at the start of step 4b. Pop it back. mw-docs never stashes
|
|
662
|
+
# (safety commit step 1 leaves the tree clean) so the pop is a no-op.
|
|
429
663
|
git stash pop 2>/dev/null || true
|
|
430
664
|
echo "CONFLICT in $FILE — cannot auto-resolve" >&2
|
|
431
665
|
exit 1 ;;
|
|
666
|
+
esac
|
|
667
|
+
|
|
668
|
+
# 2. Structured registries — strip + structural validation
|
|
669
|
+
case "$BASENAME" in
|
|
670
|
+
project-status.md|ssot-registry.md|traceability-matrix.md|REGISTRY.md)
|
|
671
|
+
sed -i '' '/^<<<<<<< /d; /^=======/d; /^>>>>>>> /d' "$FILE"
|
|
672
|
+
if ! validate_structured_md "$FILE"; then
|
|
673
|
+
git checkout --conflict=merge "$FILE" 2>/dev/null || true
|
|
674
|
+
git rebase --abort
|
|
675
|
+
git stash pop 2>/dev/null || true
|
|
676
|
+
echo "CONFLICT in structured registry $FILE produced invalid structure after auto-strip — manual resolution required." >&2
|
|
677
|
+
exit 1
|
|
678
|
+
fi
|
|
679
|
+
git add "$FILE"
|
|
680
|
+
continue ;;
|
|
681
|
+
esac
|
|
682
|
+
case "$BASENAME" in
|
|
683
|
+
field-registry.*)
|
|
684
|
+
# field-registry.json typically — strict JSON, can't auto-strip safely
|
|
685
|
+
git rebase --abort
|
|
686
|
+
git stash pop 2>/dev/null || true
|
|
687
|
+
echo "CONFLICT in structured registry $FILE — JSON cannot be auto-stripped." >&2
|
|
688
|
+
exit 1 ;;
|
|
689
|
+
esac
|
|
690
|
+
|
|
691
|
+
# 3. JSONL — only auto-resolve under docs/metrics/
|
|
692
|
+
case "$FILE" in
|
|
693
|
+
docs/metrics/*.jsonl|docs/metrics/**/*.jsonl)
|
|
694
|
+
sed -i '' '/^<<<<<<< /d; /^=======/d; /^>>>>>>> /d' "$FILE"
|
|
695
|
+
git add "$FILE"
|
|
696
|
+
continue ;;
|
|
697
|
+
*.jsonl)
|
|
698
|
+
git rebase --abort
|
|
699
|
+
git stash pop 2>/dev/null || true
|
|
700
|
+
echo "CONFLICT in $FILE (.jsonl outside docs/metrics/ — may be fixture/seed) — manual resolution required." >&2
|
|
701
|
+
exit 1 ;;
|
|
702
|
+
esac
|
|
703
|
+
|
|
704
|
+
# 4. Generic docs/config — additive merge
|
|
705
|
+
case "$FILE" in
|
|
432
706
|
docs/*|backlog/*|*.md|*.json|*.yml)
|
|
433
|
-
# Doc/config conflict — auto-resolve keeping both sides
|
|
434
707
|
sed -i '' '/^<<<<<<< /d; /^=======/d; /^>>>>>>> /d' "$FILE"
|
|
435
708
|
git add "$FILE" ;;
|
|
436
709
|
esac
|