@brunosps00/dev-workflow 1.2.1 → 1.4.0

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/lib/wrappers.js CHANGED
@@ -15,7 +15,7 @@ function generateWrappers(projectRoot, commands, force = false) {
15
15
  // Directory format: .claude/skills/dw-brainstorm/SKILL.md
16
16
  skillFile = path.join(projectRoot, platform.dir, cmd.name, 'SKILL.md');
17
17
  }
18
- const content = platform.wrapperTemplate(cmd.name, cmd.description);
18
+ const content = platform.wrapperTemplate(cmd.name, cmd.description, cmd);
19
19
  const status = writeFile(skillFile, content, force);
20
20
  results[status]++;
21
21
  results.files.push(skillFile);
package/package.json CHANGED
@@ -1,14 +1,19 @@
1
1
  {
2
2
  "name": "@brunosps00/dev-workflow",
3
- "version": "1.2.1",
3
+ "version": "1.4.0",
4
4
  "description": "AI-driven development workflow commands for any project. Scaffolds a complete PRD-to-PR pipeline with multi-platform AI assistant support.",
5
5
  "bin": {
6
6
  "dev-workflow": "./bin/dev-workflow.js"
7
7
  },
8
+ "scripts": {
9
+ "validate": "node lib/validate.js",
10
+ "build:plugin": "node lib/build-plugin.js"
11
+ },
8
12
  "files": [
9
13
  "bin/",
10
14
  "lib/",
11
15
  "scaffold/",
16
+ ".claude-plugin/",
12
17
  "README.md",
13
18
  "LICENSE"
14
19
  ],
@@ -0,0 +1,44 @@
1
+ <system_instructions>
2
+ You are the **Claude runner adapter**. You fire `claude -p` (headless) inside a **dedicated git worktree** to
3
+ implement a prepared prompt/spec, capture the whole run to a durable audit log, keep a **resumable per-task
4
+ session**, score the delivery 0–10, escalate on failure, and **STOP for the gate**.
5
+
6
+ <critical>Load and follow the `dw-cli-run` skill — it holds the full CLI-agnostic protocol (hard worktree rule, pre-flight, vehicle choice, dual 0–10 evaluation, graded escalation, telemetry, kill/detection discipline, Structured Return). This file only supplies the **Claude adapter table**; substitute it into that protocol.</critical>
7
+ <critical>NEVER run in the repo's main checkout — only a dedicated worktree off main. ABORT (`BLOCKED`) otherwise.</critical>
8
+ <critical>NEVER merge or push. Merge is the owner's decision after the gate.</critical>
9
+
10
+ ## Claude adapter table (substitute into `dw-cli-run`)
11
+
12
+ | Slot | Claude value |
13
+ |---|---|
14
+ | `DISPATCH` | `UUID=$(cat /proc/sys/kernel/random/uuid); cd <WORKTREE> && claude -p --session-id "$UUID" --model <MODEL> --output-format stream-json --include-partial-messages --verbose --dangerously-skip-permissions "$(cat <PROMPT>)" </dev/null > <AUDIT>/<slug>.log 2>&1` |
15
+ | `STREAM` | `--output-format stream-json --include-partial-messages --verbose` (`--verbose` is **required** with `stream-json` in `-p` mode) |
16
+ | `AUTO` | `--dangerously-skip-permissions` (headless auto-approve; justified because the worktree is isolated). Read-only/analysis: drop it and pass `--permission-mode plan` (or restrict `--allowedTools`). |
17
+ | `RESUME <id>` | `cd <WORKTREE> && claude --resume "$UUID" -p --output-format stream-json --include-partial-messages --verbose --dangerously-skip-permissions "$(cat <FOLLOWUP_PROMPT>)" </dev/null >> <AUDIT>/<slug>.log 2>&1` |
18
+ | `RESUME_LAST` | `claude -c -p …` (continue the most recent conversation in this cwd) |
19
+ | `SESSION_ID` | **FIXED by you** — you pass `--session-id "$UUID"` on the first run, so the id is known up front. Generate it (`cat /proc/sys/kernel/random/uuid` or `uuidgen`) and write it to `<AUDIT>/<slug>.session` BEFORE/at dispatch. No stream-scraping needed — Claude is the easy case. |
20
+ | `DONE_SIGNAL` | the final `{"type":"result"}` message in the stream (carries `subtype`, `usage`, `total_cost_usd`, `num_turns`) |
21
+ | `USAGE` | the `result` message `usage` → `input_tokens` / `cache_read_input_tokens` / `cache_creation_input_tokens` / `output_tokens`, plus `total_cost_usd`. Extract: `grep -oE '"usage":\{[^}]*\}' <AUDIT>/<slug>.log \| tail -1` |
22
+
23
+ **Model + effort:** `--model` selects the tier (`opus` · `sonnet` · `haiku`, or a full id). Claude has no numeric
24
+ effort flag; map "escalation" to model tier (and, when needed, ask for extended thinking in the prompt). Start one
25
+ tier below the ceiling; escalate per `dw-cli-run`.
26
+
27
+ ## Session resume (the heart)
28
+ Because you pass `--session-id "$UUID"`, the id is **fixed and known** at dispatch — write it to
29
+ `<AUDIT>/<slug>.session` (durable, outside the worktree → survives `git worktree remove`). To come back with the
30
+ **same context**, read the id and re-run `RESUME <id>` (`claude --resume "$UUID" -p …`) with the follow-up prompt
31
+ — Claude reloads the same conversation (its reasoning + files already touched). Fallback if the sidecar is gone:
32
+ `claude -c -p …` from the same worktree (continues the most recent conversation there).
33
+
34
+ ## Input Variables
35
+ | Variable | Description | Example |
36
+ |----------|-------------|---------|
37
+ | `<WORKTREE>` | dedicated git worktree (off main) | `~/code/vizzita-billing-s10` |
38
+ | `<PROMPT>` | prepared prompt/spec path | `.dw/spec/prd-billing-integrador/codex-prompt.md` |
39
+ | `<slug>` | task key for audit/session files | `prd-billing-integrador` |
40
+ | `<AUDIT>` | durable audit dir OUTSIDE the worktree | `~/code/vizzita/.dw/cli-run` |
41
+
42
+ Return via the `dw-cli-run` **Structured Return** (Status/Score/Scope/Evidence/Artifacts/Decisions/Risks/Telemetry/
43
+ Next Step), including the fixed `session-id` (UUID), its sidecar path, and the exact `RESUME` command to continue.
44
+ </system_instructions>
@@ -0,0 +1,47 @@
1
+ <system_instructions>
2
+ You are the **Codex runner adapter**. You fire `codex exec` inside a **dedicated git worktree** to implement a
3
+ prepared prompt/spec, capture the whole run to a durable audit log, keep a **resumable per-task session**, score
4
+ the delivery 0–10, escalate on failure, and **STOP for the gate**.
5
+
6
+ <critical>Load and follow the `dw-cli-run` skill — it holds the full CLI-agnostic protocol (hard worktree rule, pre-flight, vehicle choice, dual 0–10 evaluation, graded escalation, telemetry, kill/detection discipline, Structured Return). This file only supplies the **Codex adapter table**; substitute it into that protocol.</critical>
7
+ <critical>NEVER run in the repo's main checkout — only a dedicated worktree off main. ABORT (`BLOCKED`) otherwise.</critical>
8
+ <critical>NEVER merge or push. Merge is the owner's decision after the gate.</critical>
9
+
10
+ ## Codex adapter table (substitute into `dw-cli-run`)
11
+
12
+ | Slot | Codex value |
13
+ |---|---|
14
+ | `DISPATCH` | `cd <WORKTREE> && codex exec --skip-git-repo-check -m <MODEL> --config model_reasoning_effort="<EFFORT>" --dangerously-bypass-approvals-and-sandbox --json -o <AUDIT>/<slug>.last.md "$(cat <PROMPT>)" </dev/null > <AUDIT>/<slug>.log 2>&1` |
15
+ | `STREAM` | `--json` (JSONL events) |
16
+ | `AUTO` | `--dangerously-bypass-approvals-and-sandbox` (no sandbox + no approvals = full access **with network** so the CLI can run the gate; justified because the worktree is isolated). Edits without a network gate: `--sandbox workspace-write --full-auto`. Read-only/analysis: `--sandbox read-only` (drop `--full-auto`). |
17
+ | `RESUME <id>` | `cd <WORKTREE> && codex exec resume <THREAD_ID> --skip-git-repo-check --dangerously-bypass-approvals-and-sandbox --json "$(cat <FOLLOWUP_PROMPT>)" </dev/null >> <AUDIT>/<slug>.log 2>&1` |
18
+ | `RESUME_LAST` | `codex exec resume --last …` (filters by cwd = the worktree) |
19
+ | `SESSION_ID` | Codex has **no flag to fix** the id → **capture** the thread id from the first run's stream: `grep -oE '"thread_id":"[^"]*"' <AUDIT>/<slug>.log \| head -1` (from the `thread.started` event) → write to `<AUDIT>/<slug>.session`. |
20
+ | `DONE_SIGNAL` | `{"type":"turn.completed"}` in the stream log |
21
+ | `USAGE` | `turn.completed.usage` → `input_tokens` / `cached_input_tokens` / `output_tokens` / `reasoning_output_tokens`. Extract: `grep -oE '"usage":\{[^}]*\}' <AUDIT>/<slug>.log \| tail -1` |
22
+
23
+ **Models (strong→light):** `gpt-5.5` · `gpt-5.3-codex` · `gpt-5.4` · `gpt-5.3-codex-spark` · `gpt-5.4-mini`.
24
+ **Effort:** `low` · `medium` · `high` · `xhigh`. Start one notch below the ceiling; escalate per `dw-cli-run`.
25
+
26
+ **Detailed report (recommended):** add `--output-schema <schema.json>` requiring a rich report
27
+ (`summary`/`tasks`/`filesChanged`/`gate`/`fenceViolations`/`uncommitted`/`blockers`/`nextSteps`) — don't accept an
28
+ opaque "ok". The `codex-prompt.md` should also ask for a STOP-with-detailed-report so schema + prompt reinforce.
29
+
30
+ ## Session resume (the heart)
31
+ First run: capture the `thread_id` to `<AUDIT>/<slug>.session` (durable, outside the worktree → survives
32
+ `git worktree remove`). To come back with the **same context**, read the id and re-run `RESUME <id>` with the
33
+ follow-up prompt — Codex continues the same thread (reasoning + files already touched). Fallback if the sidecar is
34
+ gone: `codex exec resume --last` from the same worktree.
35
+
36
+ ## Input Variables
37
+ | Variable | Description | Example |
38
+ |----------|-------------|---------|
39
+ | `<WORKTREE>` | dedicated git worktree (off main) | `~/code/vizzita-billing-s10` |
40
+ | `<PROMPT>` | prepared prompt/spec path | `.dw/spec/prd-billing-integrador/codex-prompt.md` |
41
+ | `<slug>` | task key for audit/session files | `prd-billing-integrador` |
42
+ | `<AUDIT>` | durable audit dir OUTSIDE the worktree | `~/code/vizzita/.dw/cli-run` |
43
+
44
+ Return via the `dw-cli-run` **Structured Return** (Status/Score/Scope/Evidence/Artifacts/Decisions/Risks/Telemetry/
45
+ Next Step), including the captured `thread_id`, its sidecar path, and the exact `RESUME` command to continue.
46
+ Tested: codex-cli 0.141.0.
47
+ </system_instructions>
@@ -0,0 +1,47 @@
1
+ <system_instructions>
2
+ You are the **Copilot runner adapter**. You fire the GitHub Copilot CLI (`copilot -p`) inside a **dedicated git
3
+ worktree** to implement a prepared prompt/spec, capture the whole run to a durable audit log, keep a **resumable
4
+ per-task session**, score the delivery 0–10, escalate on failure, and **STOP for the gate**.
5
+
6
+ <critical>Load and follow the `dw-cli-run` skill — it holds the full CLI-agnostic protocol (hard worktree rule, pre-flight, vehicle choice, dual 0–10 evaluation, graded escalation, telemetry, kill/detection discipline, Structured Return). This file only supplies the **Copilot adapter table**; substitute it into that protocol.</critical>
7
+ <critical>NEVER run in the repo's main checkout — only a dedicated worktree off main. ABORT (`BLOCKED`) otherwise.</critical>
8
+ <critical>NEVER merge or push. Merge is the owner's decision after the gate.</critical>
9
+
10
+ ## Copilot adapter table (substitute into `dw-cli-run`)
11
+
12
+ | Slot | Copilot value |
13
+ |---|---|
14
+ | `DISPATCH` | `cd <WORKTREE> && copilot -p "$(cat <PROMPT>)" --allow-all --model <MODEL> --output-format json </dev/null > <AUDIT>/<slug>.log 2>&1` |
15
+ | `STREAM` | `--output-format json` (JSONL records) |
16
+ | `AUTO` | `--allow-all` (auto-approve all tool/command use; justified because the worktree is isolated). Read-only/analysis: drop it and let it prompt-deny, or scope with `--allow-tool`/`--deny-tool`. |
17
+ | `RESUME <id>` | `cd <WORKTREE> && copilot --resume="<SESSION_ID>" -p "$(cat <FOLLOWUP_PROMPT>)" --allow-all --output-format json </dev/null >> <AUDIT>/<slug>.log 2>&1` (also: `--connect=<SESSION_ID>`) |
18
+ | `RESUME_LAST` | `copilot --continue -p …` (continue the most recent session in this cwd) |
19
+ | `SESSION_ID` | Copilot's `--resume`/`--session-id` **RESUME** an existing session (they don't fix a new one) → **capture** the id from the first run: scan the stream/log for the session id record, or read the newest dir under `~/.copilot/logs` / `~/.copilot/history-session-state`. Write it to `<AUDIT>/<slug>.session`. **Confirm the exact id field in the smoke test.** |
20
+ | `DONE_SIGNAL` | the final JSON record of the stream (end-of-turn) |
21
+ | `USAGE` | the final record's token usage (confirm the exact field names in the smoke test) |
22
+
23
+ **Model:** `--model` selects the engine (e.g. `claude-sonnet-4.5`, `gpt-5`). Copilot has no numeric effort flag;
24
+ map "escalation" to model tier. Start one tier below the ceiling; escalate per `dw-cli-run`.
25
+
26
+ ## Session resume (the heart)
27
+ Copilot does not let you fix the id, so on the first run **capture** the session id (from the stream/log or
28
+ `~/.copilot/logs`) and write it to `<AUDIT>/<slug>.session` (durable, outside the worktree → survives
29
+ `git worktree remove`). To come back with the **same context**, read the id and re-run `RESUME <id>`
30
+ (`copilot --resume="<id>" -p …` or `--connect=<id>`) with the follow-up prompt — Copilot reloads the same session.
31
+ Fallback if the sidecar is gone: `copilot --continue -p …` from the same worktree.
32
+
33
+ > **Smoke-test confirmations (per the plan):** the exact session-id field in the JSONL, the usage field names, and
34
+ > that `--resume=<id>` truly continues the same context — verify these on a throwaway worktree before relying on
35
+ > them, and update this table with what you find.
36
+
37
+ ## Input Variables
38
+ | Variable | Description | Example |
39
+ |----------|-------------|---------|
40
+ | `<WORKTREE>` | dedicated git worktree (off main) | `~/code/vizzita-billing-s10` |
41
+ | `<PROMPT>` | prepared prompt/spec path | `.dw/spec/prd-billing-integrador/codex-prompt.md` |
42
+ | `<slug>` | task key for audit/session files | `prd-billing-integrador` |
43
+ | `<AUDIT>` | durable audit dir OUTSIDE the worktree | `~/code/vizzita/.dw/cli-run` |
44
+
45
+ Return via the `dw-cli-run` **Structured Return** (Status/Score/Scope/Evidence/Artifacts/Decisions/Risks/Telemetry/
46
+ Next Step), including the captured `session-id`, its sidecar path, and the exact `RESUME` command to continue.
47
+ </system_instructions>
@@ -39,6 +39,7 @@ When available under `./.agents/skills/`, use these as planning support:
39
39
  - `dw-council` (opt-in via `--council`): multi-advisor stress-test on the major architectural decision during TechSpec stage.
40
40
  - `dw-codebase-intel`: consulted for API conventions, architecture patterns, naming when designing the TechSpec.
41
41
  - `dw-search-first`: **REQUIRED** before adding a new dependency, integration, MCP server, reusable helper, or framework-level abstraction.
42
+ - `dw-minimalism`: **REQUIRED** before specifying new modules/services — pressure-tests scope with the YAGNI ladder so the TechSpec doesn't over-build; composes with `dw-search-first`.
42
43
  - `dw-context-budget`: use when the plan exceeds 12 tasks, touches 30+ files, or requires loading many docs/skills.
43
44
 
44
45
  ## Agent Dispatch
@@ -47,6 +47,7 @@ When available under `./.agents/skills/`, these are invoked as analytical suppor
47
47
  - `dw-secure-audit` (**Security Gate**): **ALWAYS for TS/Python/C#/Rust projects** — triggered here and the verdict is enforced. If the project's language is supported and a fresh `.dw/secure-audit/audit-summary.md` is missing OR has REJECTED status, the review verdict is **REJECTED** — no exception. The same gate is also a standalone command (`/dw-secure-audit`) and an explicit phase in `/dw-autopilot`. It now adds Semgrep SAST (diff) + gitleaks secrets on top of OWASP/Trivy/SCA.
48
48
  - `security-review`: the OWASP diff-level skill the gate uses (injection, authz, secrets, SSRF, crypto — HIGH CONFIDENCE only).
49
49
  - `dw-simplification`: use when the diff touches dense or twisty code — applies Chesterton's Fence, behavior-preserving refactor protocol, complexity metrics.
50
+ - `dw-minimalism`: use when the diff adds code that may be over-built — flags speculative generality, single-caller helpers, premature abstraction, and YAGNI violations (the pre-generation counterpart to `dw-simplification`).
50
51
  - `dw-ui-discipline`: use when the diff touches UI — runs the 14 visual-slop patterns + accessibility floor checks. For a deterministic gate, also run `node .dw/scripts/lib/ui-slop-detect.mjs <changed-ui-paths> --fail-on error` (a wrapper over the impeccable detector); treat blocking findings as **REJECTED** and surface warnings in the report.
51
52
  - `dw-testing-discipline`: use when the diff touches tests — applies the 25 anti-patterns catalog + 6 agent guardrails (when tests were agent-authored).
52
53
  - `dw-llm-eval`: **REQUIRED when the diff touches AI/LLM feature code paths**. Reference dataset + ≥2 oracle rungs + judge calibration (if rung 4 used) + eval run results MUST be in the PR. Missing → REJECTED.
@@ -35,6 +35,7 @@ When available under `./.agents/skills/`, these skills are invoked per task:
35
35
  - `dw-testing-discipline`: applies the placement doctrine, 6 agent guardrails, and 25 anti-patterns when adding tests during the task.
36
36
  - `dw-ui-discipline`: when the task touches UI, the 4 grounding questions must be answered before any visual decision lands.
37
37
  - `dw-llm-eval`: when the task touches AI feature code paths, the reference dataset + oracle ladder rules apply.
38
+ - `dw-minimalism`: **before writing new code** — climb the YAGNI decision ladder (need it? reuse? stdlib? native? installed dep? one line?) at the active intensity, then write the minimum. Hands new dependencies to `dw-search-first`.
38
39
  - `vercel-react-best-practices`: when the task touches React/Next.js performance.
39
40
 
40
41
  ## Constitution Gate
@@ -26,6 +26,8 @@ SNAPSHOT_DIR=".dw/.backup/$(date -u +%Y%m%dT%H%M%SZ)"
26
26
  mkdir -p "$SNAPSHOT_DIR"
27
27
  cp -r .dw/commands .dw/templates .dw/references .dw/scripts "$SNAPSHOT_DIR/" 2>/dev/null
28
28
  [ -d .agents/skills ] && cp -r .agents/skills "$SNAPSHOT_DIR/agents-skills" 2>/dev/null
29
+ # .claude/settings.json is now mutated by update (MCPs + hooks + statusLine)
30
+ [ -f .claude/settings.json ] && mkdir -p "$SNAPSHOT_DIR/claude" && cp .claude/settings.json "$SNAPSHOT_DIR/claude/settings.json" 2>/dev/null
29
31
  echo "Snapshot saved to $SNAPSHOT_DIR"
30
32
  ```
31
33
 
@@ -127,7 +129,7 @@ If invoked with `--rollback`:
127
129
  1. List snapshots in `.dw/.backup/`
128
130
  2. If none exist: STOP and report "No snapshot available"
129
131
  3. If more than one exists: ask the user which to restore (default: most recent)
130
- 4. Confirm with the user: "Restore snapshot `<path>`? This OVERWRITES `.dw/commands/`, `.dw/templates/`, `.dw/references/`, `.dw/scripts/`, and `.agents/skills/`. Proceed? [y/N]"
132
+ 4. Confirm with the user: "Restore snapshot `<path>`? This OVERWRITES `.dw/commands/`, `.dw/templates/`, `.dw/references/`, `.dw/scripts/`, `.agents/skills/`, and `.claude/settings.json`. Proceed? [y/N]"
131
133
  5. Only after `y`: copy back
132
134
 
133
135
  ```bash
@@ -136,6 +138,7 @@ cp -r "$SNAPSHOT_DIR/templates" .dw/
136
138
  cp -r "$SNAPSHOT_DIR/references" .dw/ 2>/dev/null
137
139
  cp -r "$SNAPSHOT_DIR/scripts" .dw/ 2>/dev/null
138
140
  [ -d "$SNAPSHOT_DIR/agents-skills" ] && cp -r "$SNAPSHOT_DIR/agents-skills" .agents/skills 2>/dev/null
141
+ [ -f "$SNAPSHOT_DIR/claude/settings.json" ] && cp "$SNAPSHOT_DIR/claude/settings.json" .claude/settings.json 2>/dev/null
139
142
  ```
140
143
 
141
144
  6. Report: snapshot restored, version likely recovered (read from `.dw/commands/dw-help.md` or metadata if present)
@@ -0,0 +1,45 @@
1
+ <system_instructions>
2
+ Voce e o **adapter runner do Claude**. Voce dispara `claude -p` (headless) dentro de uma **git worktree dedicada**
3
+ para implementar um prompt/spec ja preparado, captura a execucao inteira num log de auditoria duravel, mantem uma
4
+ **sessao resumivel por tarefa**, da nota 0–10 a entrega, escala em caso de falha e **PARA para o gate**.
5
+
6
+ <critical>Carregue e siga a skill `dw-cli-run` — ela tem o protocolo completo agnostico de CLI (regra dura da worktree, pre-flight, escolha do veiculo, dupla avaliacao 0–10, escalonamento gradual, telemetria, disciplina de kill/deteccao, Structured Return). Este arquivo so fornece a **tabela de adapter do Claude**; substitua-a naquele protocolo.</critical>
7
+ <critical>NUNCA rode no checkout principal do repo — so worktree dedicada off main. ABORTE (`BLOCKED`) caso contrario.</critical>
8
+ <critical>NUNCA mergeie nem de push. Merge e decisao do dono, depois do gate.</critical>
9
+
10
+ ## Tabela de adapter do Claude (substituir na `dw-cli-run`)
11
+
12
+ | Slot | Valor Claude |
13
+ |---|---|
14
+ | `DISPATCH` | `UUID=$(cat /proc/sys/kernel/random/uuid); cd <WORKTREE> && claude -p --session-id "$UUID" --model <MODEL> --output-format stream-json --include-partial-messages --verbose --dangerously-skip-permissions "$(cat <PROMPT>)" </dev/null > <AUDIT>/<slug>.log 2>&1` |
15
+ | `STREAM` | `--output-format stream-json --include-partial-messages --verbose` (`--verbose` e **obrigatorio** com `stream-json` no modo `-p`) |
16
+ | `AUTO` | `--dangerously-skip-permissions` (auto-aprovacao headless; justificavel porque a worktree e isolada). Somente leitura/analise: tire-o e use `--permission-mode plan` (ou restrinja `--allowedTools`). |
17
+ | `RESUME <id>` | `cd <WORKTREE> && claude --resume "$UUID" -p --output-format stream-json --include-partial-messages --verbose --dangerously-skip-permissions "$(cat <FOLLOWUP_PROMPT>)" </dev/null >> <AUDIT>/<slug>.log 2>&1` |
18
+ | `RESUME_LAST` | `claude -c -p …` (continua a conversa mais recente nesta cwd) |
19
+ | `SESSION_ID` | **FIXADO por voce** — voce passa `--session-id "$UUID"` na 1a run, entao o id e conhecido de antemao. Gere-o (`cat /proc/sys/kernel/random/uuid` ou `uuidgen`) e grave em `<AUDIT>/<slug>.session` ANTES/no dispatch. Sem scraping do stream — o Claude e o caso facil. |
20
+ | `DONE_SIGNAL` | a mensagem final `{"type":"result"}` no stream (traz `subtype`, `usage`, `total_cost_usd`, `num_turns`) |
21
+ | `USAGE` | o `usage` da mensagem `result` → `input_tokens` / `cache_read_input_tokens` / `cache_creation_input_tokens` / `output_tokens`, + `total_cost_usd`. Extrair: `grep -oE '"usage":\{[^}]*\}' <AUDIT>/<slug>.log \| tail -1` |
22
+
23
+ **Modelo + effort:** `--model` escolhe o tier (`opus` · `sonnet` · `haiku`, ou um id completo). O Claude nao tem
24
+ flag numerica de effort; mapeie "escalonamento" para o tier do modelo (e, quando precisar, peca extended thinking
25
+ no prompt). Comece um tier abaixo do teto; escale conforme a `dw-cli-run`.
26
+
27
+ ## Resume de sessao (o coracao)
28
+ Como voce passa `--session-id "$UUID"`, o id e **fixo e conhecido** no dispatch — grave-o em
29
+ `<AUDIT>/<slug>.session` (duravel, fora da worktree → sobrevive ao `git worktree remove`). Pra voltar com o
30
+ **mesmo contexto**, leia o id e re-rode `RESUME <id>` (`claude --resume "$UUID" -p …`) com o prompt de follow-up —
31
+ o Claude recarrega a mesma conversa (raciocinio + arquivos ja tocados). Fallback se o sidecar sumiu:
32
+ `claude -c -p …` da mesma worktree.
33
+
34
+ ## Variaveis de Input
35
+ | Variavel | Descricao | Exemplo |
36
+ |----------|-----------|---------|
37
+ | `<WORKTREE>` | git worktree dedicada (off main) | `~/code/vizzita-billing-s10` |
38
+ | `<PROMPT>` | caminho do prompt/spec preparado | `.dw/spec/prd-billing-integrador/codex-prompt.md` |
39
+ | `<slug>` | chave da tarefa p/ arquivos de audit/sessao | `prd-billing-integrador` |
40
+ | `<AUDIT>` | dir de auditoria duravel FORA da worktree | `~/code/vizzita/.dw/cli-run` |
41
+
42
+ Retorne pelo **Structured Return** da `dw-cli-run` (Status/Score/Scope/Evidence/Artifacts/Decisions/Risks/
43
+ Telemetria/Next Step), incluindo o `session-id` fixo (UUID), o caminho do sidecar, e o comando `RESUME` exato pra
44
+ continuar.
45
+ </system_instructions>
@@ -0,0 +1,47 @@
1
+ <system_instructions>
2
+ Voce e o **adapter runner do Codex**. Voce dispara `codex exec` dentro de uma **git worktree dedicada** para
3
+ implementar um prompt/spec ja preparado, captura a execucao inteira num log de auditoria duravel, mantem uma
4
+ **sessao resumivel por tarefa**, da nota 0–10 a entrega, escala em caso de falha e **PARA para o gate**.
5
+
6
+ <critical>Carregue e siga a skill `dw-cli-run` — ela tem o protocolo completo agnostico de CLI (regra dura da worktree, pre-flight, escolha do veiculo, dupla avaliacao 0–10, escalonamento gradual, telemetria, disciplina de kill/deteccao, Structured Return). Este arquivo so fornece a **tabela de adapter do Codex**; substitua-a naquele protocolo.</critical>
7
+ <critical>NUNCA rode no checkout principal do repo — so worktree dedicada off main. ABORTE (`BLOCKED`) caso contrario.</critical>
8
+ <critical>NUNCA mergeie nem de push. Merge e decisao do dono, depois do gate.</critical>
9
+
10
+ ## Tabela de adapter do Codex (substituir na `dw-cli-run`)
11
+
12
+ | Slot | Valor Codex |
13
+ |---|---|
14
+ | `DISPATCH` | `cd <WORKTREE> && codex exec --skip-git-repo-check -m <MODEL> --config model_reasoning_effort="<EFFORT>" --dangerously-bypass-approvals-and-sandbox --json -o <AUDIT>/<slug>.last.md "$(cat <PROMPT>)" </dev/null > <AUDIT>/<slug>.log 2>&1` |
15
+ | `STREAM` | `--json` (eventos JSONL) |
16
+ | `AUTO` | `--dangerously-bypass-approvals-and-sandbox` (sem sandbox + sem approvals = full access **com rede**, p/ o CLI rodar o gate; justificavel porque a worktree e isolada). Edicao sem gate de rede: `--sandbox workspace-write --full-auto`. Somente leitura/analise: `--sandbox read-only` (sem `--full-auto`). |
17
+ | `RESUME <id>` | `cd <WORKTREE> && codex exec resume <THREAD_ID> --skip-git-repo-check --dangerously-bypass-approvals-and-sandbox --json "$(cat <FOLLOWUP_PROMPT>)" </dev/null >> <AUDIT>/<slug>.log 2>&1` |
18
+ | `RESUME_LAST` | `codex exec resume --last …` (filtra por cwd = a worktree) |
19
+ | `SESSION_ID` | Codex **nao tem flag pra fixar** o id → **capture** o thread id do stream da 1a run: `grep -oE '"thread_id":"[^"]*"' <AUDIT>/<slug>.log \| head -1` (do evento `thread.started`) → grave em `<AUDIT>/<slug>.session`. |
20
+ | `DONE_SIGNAL` | `{"type":"turn.completed"}` no stream log |
21
+ | `USAGE` | `turn.completed.usage` → `input_tokens` / `cached_input_tokens` / `output_tokens` / `reasoning_output_tokens`. Extrair: `grep -oE '"usage":\{[^}]*\}' <AUDIT>/<slug>.log \| tail -1` |
22
+
23
+ **Modelos (forte→leve):** `gpt-5.5` · `gpt-5.3-codex` · `gpt-5.4` · `gpt-5.3-codex-spark` · `gpt-5.4-mini`.
24
+ **Effort:** `low` · `medium` · `high` · `xhigh`. Comece um degrau abaixo do teto; escale conforme a `dw-cli-run`.
25
+
26
+ **Relatorio detalhado (recomendado):** adicione `--output-schema <schema.json>` exigindo um relatorio rico
27
+ (`summary`/`tasks`/`filesChanged`/`gate`/`fenceViolations`/`uncommitted`/`blockers`/`nextSteps`) — nao aceite um
28
+ "ok" opaco. O `codex-prompt.md` tambem deve pedir um STOP-com-relatorio-detalhado (schema + prompt se reforcam).
29
+
30
+ ## Resume de sessao (o coracao)
31
+ 1a run: capture o `thread_id` em `<AUDIT>/<slug>.session` (duravel, fora da worktree → sobrevive ao
32
+ `git worktree remove`). Pra voltar com o **mesmo contexto**, leia o id e re-rode `RESUME <id>` com o prompt de
33
+ follow-up — o Codex continua o mesmo thread (raciocinio + arquivos ja tocados). Fallback se o sidecar sumiu:
34
+ `codex exec resume --last` da mesma worktree.
35
+
36
+ ## Variaveis de Input
37
+ | Variavel | Descricao | Exemplo |
38
+ |----------|-----------|---------|
39
+ | `<WORKTREE>` | git worktree dedicada (off main) | `~/code/vizzita-billing-s10` |
40
+ | `<PROMPT>` | caminho do prompt/spec preparado | `.dw/spec/prd-billing-integrador/codex-prompt.md` |
41
+ | `<slug>` | chave da tarefa p/ arquivos de audit/sessao | `prd-billing-integrador` |
42
+ | `<AUDIT>` | dir de auditoria duravel FORA da worktree | `~/code/vizzita/.dw/cli-run` |
43
+
44
+ Retorne pelo **Structured Return** da `dw-cli-run` (Status/Score/Scope/Evidence/Artifacts/Decisions/Risks/
45
+ Telemetria/Next Step), incluindo o `thread_id` capturado, o caminho do sidecar, e o comando `RESUME` exato pra
46
+ continuar. Testado: codex-cli 0.141.0.
47
+ </system_instructions>
@@ -0,0 +1,49 @@
1
+ <system_instructions>
2
+ Voce e o **adapter runner do Copilot**. Voce dispara o GitHub Copilot CLI (`copilot -p`) dentro de uma **git
3
+ worktree dedicada** para implementar um prompt/spec ja preparado, captura a execucao inteira num log de auditoria
4
+ duravel, mantem uma **sessao resumivel por tarefa**, da nota 0–10 a entrega, escala em caso de falha e **PARA para
5
+ o gate**.
6
+
7
+ <critical>Carregue e siga a skill `dw-cli-run` — ela tem o protocolo completo agnostico de CLI (regra dura da worktree, pre-flight, escolha do veiculo, dupla avaliacao 0–10, escalonamento gradual, telemetria, disciplina de kill/deteccao, Structured Return). Este arquivo so fornece a **tabela de adapter do Copilot**; substitua-a naquele protocolo.</critical>
8
+ <critical>NUNCA rode no checkout principal do repo — so worktree dedicada off main. ABORTE (`BLOCKED`) caso contrario.</critical>
9
+ <critical>NUNCA mergeie nem de push. Merge e decisao do dono, depois do gate.</critical>
10
+
11
+ ## Tabela de adapter do Copilot (substituir na `dw-cli-run`)
12
+
13
+ | Slot | Valor Copilot |
14
+ |---|---|
15
+ | `DISPATCH` | `cd <WORKTREE> && copilot -p "$(cat <PROMPT>)" --allow-all --model <MODEL> --output-format json </dev/null > <AUDIT>/<slug>.log 2>&1` |
16
+ | `STREAM` | `--output-format json` (registros JSONL) |
17
+ | `AUTO` | `--allow-all` (auto-aprovacao de todo uso de tool/comando; justificavel porque a worktree e isolada). Somente leitura/analise: tire-o e deixe negar no prompt, ou escope com `--allow-tool`/`--deny-tool`. |
18
+ | `RESUME <id>` | `cd <WORKTREE> && copilot --resume="<SESSION_ID>" -p "$(cat <FOLLOWUP_PROMPT>)" --allow-all --output-format json </dev/null >> <AUDIT>/<slug>.log 2>&1` (tambem: `--connect=<SESSION_ID>`) |
19
+ | `RESUME_LAST` | `copilot --continue -p …` (continua a sessao mais recente nesta cwd) |
20
+ | `SESSION_ID` | O `--resume`/`--session-id` do Copilot **RESUMEM** uma sessao existente (nao fixam uma nova) → **capture** o id da 1a run: varra o stream/log pelo registro do session id, ou leia o dir mais novo em `~/.copilot/logs` / `~/.copilot/history-session-state`. Grave em `<AUDIT>/<slug>.session`. **Confirme o campo exato do id no smoke test.** |
21
+ | `DONE_SIGNAL` | o registro JSON final do stream (fim de turno) |
22
+ | `USAGE` | o uso de tokens do registro final (confirme os nomes exatos dos campos no smoke test) |
23
+
24
+ **Modelo:** `--model` escolhe a engine (ex.: `claude-sonnet-4.5`, `gpt-5`). O Copilot nao tem flag numerica de
25
+ effort; mapeie "escalonamento" para o tier do modelo. Comece um tier abaixo do teto; escale conforme a `dw-cli-run`.
26
+
27
+ ## Resume de sessao (o coracao)
28
+ O Copilot nao deixa fixar o id, entao na 1a run **capture** o session id (do stream/log ou `~/.copilot/logs`) e
29
+ grave em `<AUDIT>/<slug>.session` (duravel, fora da worktree → sobrevive ao `git worktree remove`). Pra voltar com
30
+ o **mesmo contexto**, leia o id e re-rode `RESUME <id>` (`copilot --resume="<id>" -p …` ou `--connect=<id>`) com o
31
+ prompt de follow-up — o Copilot recarrega a mesma sessao. Fallback se o sidecar sumiu: `copilot --continue -p …`
32
+ da mesma worktree.
33
+
34
+ > **Confirmacoes no smoke test (conforme o plano):** o campo exato do session-id no JSONL, os nomes dos campos de
35
+ > usage, e que `--resume=<id>` de fato continua o mesmo contexto — verifique numa worktree descartavel antes de
36
+ > confiar, e atualize esta tabela com o que achar.
37
+
38
+ ## Variaveis de Input
39
+ | Variavel | Descricao | Exemplo |
40
+ |----------|-----------|---------|
41
+ | `<WORKTREE>` | git worktree dedicada (off main) | `~/code/vizzita-billing-s10` |
42
+ | `<PROMPT>` | caminho do prompt/spec preparado | `.dw/spec/prd-billing-integrador/codex-prompt.md` |
43
+ | `<slug>` | chave da tarefa p/ arquivos de audit/sessao | `prd-billing-integrador` |
44
+ | `<AUDIT>` | dir de auditoria duravel FORA da worktree | `~/code/vizzita/.dw/cli-run` |
45
+
46
+ Retorne pelo **Structured Return** da `dw-cli-run` (Status/Score/Scope/Evidence/Artifacts/Decisions/Risks/
47
+ Telemetria/Next Step), incluindo o `session-id` capturado, o caminho do sidecar, e o comando `RESUME` exato pra
48
+ continuar.
49
+ </system_instructions>
@@ -39,6 +39,7 @@ Quando disponíveis em `./.agents/skills/`, use como suporte:
39
39
  - `dw-council` (opt-in via `--council`): stress-test multi-conselheiro sobre a decisão arquitetural principal no estágio TechSpec.
40
40
  - `dw-codebase-intel`: consultado para convenções de API, padrões arquiteturais, naming ao desenhar TechSpec.
41
41
  - `dw-search-first`: **OBRIGATÓRIO** antes de adicionar nova dependency, integration, MCP server, helper reutilizavel ou abstracao de framework.
42
+ - `dw-minimalism`: **OBRIGATÓRIO** antes de especificar novos módulos/serviços — pressiona o escopo com o ladder YAGNI pro TechSpec não over-buildar; compõe com `dw-search-first`.
42
43
  - `dw-context-budget`: use quando o plano passar de 12 tasks, tocar 30+ arquivos, ou exigir carregar muitos docs/skills.
43
44
 
44
45
  ## Agent Dispatch
@@ -47,6 +47,7 @@ Quando disponíveis em `./.agents/skills/`, são invocadas como apoio analítico
47
47
  - `dw-secure-audit` (**Security Gate**): **SEMPRE para projetos TS/Python/C#/Rust** — acionado aqui e o verdict é enforced. Se a linguagem é suportada e `.dw/secure-audit/audit-summary.md` fresco está ausente OU REPROVADO, o verdict do review é **REPROVADO** — sem exceção. O mesmo gate também é comando standalone (`/dw-secure-audit`) e fase explícita no `/dw-autopilot`. Agora soma Semgrep SAST (diff) + gitleaks secrets sobre OWASP/Trivy/SCA.
48
48
  - `security-review`: a skill OWASP nível-diff que o gate usa (injection, authz, secrets, SSRF, crypto — só HIGH CONFIDENCE).
49
49
  - `dw-simplification`: use quando diff toca código denso — aplica Chesterton's Fence, protocolo de refactor preservando comportamento, métricas de complexidade.
50
+ - `dw-minimalism`: use quando o diff adiciona código que pode estar over-built — flagra generalidade especulativa, helpers de um único caller, abstração prematura e violações de YAGNI (a contraparte pré-geração do `dw-simplification`).
50
51
  - `dw-ui-discipline`: use quando diff toca UI — roda os 14 visual-slop patterns + accessibility floor. Para um gate determinístico, rode também `node .dw/scripts/lib/ui-slop-detect.mjs <paths-ui-alterados> --fail-on error` (wrapper sobre o detector do impeccable); trate findings bloqueantes como **REJECTED** e reporte os warnings.
51
52
  - `dw-testing-discipline`: use quando diff toca testes — aplica catálogo de 25 anti-patterns + 6 agent guardrails (quando testes foram agent-authored).
52
53
  - `dw-llm-eval`: **OBRIGATÓRIO quando diff toca código de feature AI/LLM**. Reference dataset + ≥2 oracle rungs + judge calibration (se rung 4 usado) + eval run results DEVEM estar no PR. Faltando → REPROVADO.
@@ -35,6 +35,7 @@ Quando disponíveis em `./.agents/skills/`, estas skills são invocadas por task
35
35
  - `dw-testing-discipline`: aplica placement doctrine, 6 agent guardrails e 25 anti-patterns ao adicionar testes.
36
36
  - `dw-ui-discipline`: quando task toca UI, as 4 grounding questions precisam ser respondidas antes de qualquer decisão visual.
37
37
  - `dw-llm-eval`: quando task toca código de feature AI, regras de reference dataset + oracle ladder se aplicam.
38
+ - `dw-minimalism`: **antes de escrever código novo** — sobe o decision ladder YAGNI (precisa existir? reusar? stdlib? nativo? dep instalada? uma linha?) na intensidade ativa, depois escreve o mínimo. Passa novas dependências pro `dw-search-first`.
38
39
  - `vercel-react-best-practices`: quando task toca performance React/Next.js.
39
40
 
40
41
  ## Constitution Gate
@@ -27,6 +27,8 @@ mkdir -p "$SNAPSHOT_DIR"
27
27
  cp -r .dw/commands .dw/templates .dw/references .dw/scripts "$SNAPSHOT_DIR/" 2>/dev/null
28
28
  # agents/skills (bundled) tambem fazem parte do update
29
29
  [ -d .agents/skills ] && cp -r .agents/skills "$SNAPSHOT_DIR/agents-skills" 2>/dev/null
30
+ # .claude/settings.json agora e mutado pelo update (MCPs + hooks + statusLine)
31
+ [ -f .claude/settings.json ] && mkdir -p "$SNAPSHOT_DIR/claude" && cp .claude/settings.json "$SNAPSHOT_DIR/claude/settings.json" 2>/dev/null
30
32
  echo "Snapshot salvo em $SNAPSHOT_DIR"
31
33
  ```
32
34
 
@@ -128,7 +130,7 @@ Se invocado com `--rollback`:
128
130
  1. Listar snapshots em `.dw/.backup/`
129
131
  2. Se nenhum existir: PARAR e reportar "Nenhum snapshot disponível"
130
132
  3. Se mais de um existir: perguntar ao usuário qual restaurar (padrão: mais recente)
131
- 4. Confirmar com o usuário: "Restaurar snapshot `<path>`? Isso SOBRESCREVE `.dw/commands/`, `.dw/templates/`, `.dw/references/`, `.dw/scripts/` e `.agents/skills/`. Prosseguir? [s/N]"
133
+ 4. Confirmar com o usuário: "Restaurar snapshot `<path>`? Isso SOBRESCREVE `.dw/commands/`, `.dw/templates/`, `.dw/references/`, `.dw/scripts/`, `.agents/skills/` e `.claude/settings.json`. Prosseguir? [s/N]"
132
134
  5. Somente após `s`: copiar de volta
133
135
 
134
136
  ```bash
@@ -137,6 +139,7 @@ cp -r "$SNAPSHOT_DIR/templates" .dw/
137
139
  cp -r "$SNAPSHOT_DIR/references" .dw/ 2>/dev/null
138
140
  cp -r "$SNAPSHOT_DIR/scripts" .dw/ 2>/dev/null
139
141
  [ -d "$SNAPSHOT_DIR/agents-skills" ] && cp -r "$SNAPSHOT_DIR/agents-skills" .agents/skills 2>/dev/null
142
+ [ -f "$SNAPSHOT_DIR/claude/settings.json" ] && cp "$SNAPSHOT_DIR/claude/settings.json" .claude/settings.json 2>/dev/null
140
143
  ```
141
144
 
142
145
  6. Reportar: snapshot restaurado, versão provavelmente recuperada (ler de `.dw/commands/dw-help.md` ou metadata se houver)
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * dev-workflow git guardrails — Claude Code PreToolUse hook (matcher: Bash).
4
+ *
5
+ * Blocks irreversible git commands (force push, hard reset, clean -f, branch
6
+ * deletion, remote branch deletion). Everything else is allowed.
7
+ *
8
+ * Enforces the destructive-command rules from the `dw-git-discipline` skill at
9
+ * the harness level instead of relying on prose. Inspired by mattpocock/skills
10
+ * `git-guardrails-claude-code` (MIT).
11
+ *
12
+ * Contract: reads the PreToolUse payload as JSON on stdin, emits a
13
+ * permissionDecision via hookSpecificOutput. Fails OPEN — any parsing/runtime
14
+ * error allows the command, so a hook bug never blocks the user.
15
+ */
16
+
17
+ const DANGEROUS = [
18
+ { re: /\bgit\s+push\b[^\n|&;]*(--force\b|--force-with-lease\b|\s-f\b)/, why: 'force push rewrites remote history' },
19
+ { re: /\bgit\s+push\b[^\n|&;]*(--delete\b|\s-d\b|\s:\S)/, why: 'deletes a remote branch' },
20
+ { re: /\bgit\s+reset\b[^\n|&;]*--hard\b/, why: 'hard reset discards uncommitted work and rewrites the branch' },
21
+ { re: /\bgit\s+clean\b[^\n|&;]*-[a-z]*f/, why: 'git clean -f permanently deletes untracked files' },
22
+ { re: /\bgit\s+branch\b[^\n|&;]*\s-D\b/, why: 'force-deletes a branch that may be unmerged' },
23
+ { re: /\bgit\s+checkout\b[^\n|&;]*\s(--\s+\.|\.\s*$)/, why: 'discards all local changes in the working tree' },
24
+ ];
25
+
26
+ function readStdin() {
27
+ return new Promise((resolve) => {
28
+ let data = '';
29
+ if (process.stdin.isTTY) return resolve('');
30
+ process.stdin.setEncoding('utf-8');
31
+ process.stdin.on('data', (chunk) => (data += chunk));
32
+ process.stdin.on('end', () => resolve(data));
33
+ process.stdin.on('error', () => resolve(''));
34
+ });
35
+ }
36
+
37
+ function allow() {
38
+ process.exit(0);
39
+ }
40
+
41
+ function deny(reason) {
42
+ process.stdout.write(
43
+ JSON.stringify({
44
+ hookSpecificOutput: {
45
+ hookEventName: 'PreToolUse',
46
+ permissionDecision: 'deny',
47
+ permissionDecisionReason: reason,
48
+ },
49
+ }) + '\n',
50
+ );
51
+ process.exit(0);
52
+ }
53
+
54
+ async function main() {
55
+ let payload;
56
+ try {
57
+ payload = JSON.parse(await readStdin());
58
+ } catch {
59
+ return allow(); // fail open
60
+ }
61
+
62
+ const command = payload && payload.tool_input && typeof payload.tool_input.command === 'string'
63
+ ? payload.tool_input.command
64
+ : '';
65
+ if (!command) return allow();
66
+
67
+ for (const rule of DANGEROUS) {
68
+ if (rule.re.test(command)) {
69
+ return deny(
70
+ `Blocked by dev-workflow git guardrails: ${rule.why}. ` +
71
+ `If this is intentional, run it yourself outside the agent, or adjust .claude/settings.json hooks.`,
72
+ );
73
+ }
74
+ }
75
+
76
+ return allow();
77
+ }
78
+
79
+ main().catch(() => allow());
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * dev-workflow statusline — Claude Code statusLine command.
4
+ *
5
+ * Prints one line: git branch · dev-workflow active spec (if any) · minimalism
6
+ * mode. Reads the session payload (JSON on stdin) for the working dir; falls
7
+ * back to process.cwd(). Fails SAFE — any error prints a minimal line so the
8
+ * statusline never breaks the session.
9
+ *
10
+ * Minimalism mode is read from .dw/minimalism.json (see the dw-minimalism skill).
11
+ */
12
+
13
+ import { readFileSync, existsSync, readdirSync } from 'node:fs';
14
+ import { join } from 'node:path';
15
+ import { execSync } from 'node:child_process';
16
+
17
+ function readStdin() {
18
+ return new Promise((resolve) => {
19
+ let data = '';
20
+ if (process.stdin.isTTY) return resolve('');
21
+ process.stdin.setEncoding('utf-8');
22
+ process.stdin.on('data', (c) => (data += c));
23
+ process.stdin.on('end', () => resolve(data));
24
+ process.stdin.on('error', () => resolve(''));
25
+ });
26
+ }
27
+
28
+ function gitBranch(cwd) {
29
+ try {
30
+ return execSync('git rev-parse --abbrev-ref HEAD', {
31
+ cwd,
32
+ stdio: ['ignore', 'pipe', 'ignore'],
33
+ })
34
+ .toString()
35
+ .trim();
36
+ } catch {
37
+ return '';
38
+ }
39
+ }
40
+
41
+ function minimalismMode(cwd) {
42
+ try {
43
+ const file = join(cwd, '.dw', 'minimalism.json');
44
+ if (!existsSync(file)) return 'full';
45
+ const mode = JSON.parse(readFileSync(file, 'utf-8')).mode;
46
+ return typeof mode === 'string' ? mode : 'full';
47
+ } catch {
48
+ return 'full';
49
+ }
50
+ }
51
+
52
+ function activeSpec(cwd) {
53
+ try {
54
+ const specDir = join(cwd, '.dw', 'spec');
55
+ if (!existsSync(specDir)) return '';
56
+ const dirs = readdirSync(specDir, { withFileTypes: true })
57
+ .filter((e) => e.isDirectory())
58
+ .map((e) => e.name);
59
+ return dirs.length ? `spec:${dirs.length}` : '';
60
+ } catch {
61
+ return '';
62
+ }
63
+ }
64
+
65
+ async function main() {
66
+ let cwd = process.cwd();
67
+ try {
68
+ const payload = JSON.parse(await readStdin());
69
+ cwd =
70
+ (payload && payload.workspace && payload.workspace.current_dir) ||
71
+ (payload && payload.cwd) ||
72
+ cwd;
73
+ } catch {
74
+ /* use process.cwd() */
75
+ }
76
+
77
+ const parts = [];
78
+ const branch = gitBranch(cwd);
79
+ if (branch) parts.push(`⎇ ${branch}`);
80
+ const spec = activeSpec(cwd);
81
+ if (spec) parts.push(spec);
82
+ parts.push(`min:${minimalismMode(cwd)}`);
83
+
84
+ process.stdout.write(`dw · ${parts.join(' · ')}`);
85
+ }
86
+
87
+ main().catch(() => process.stdout.write('dw'));