@brunosps00/dev-workflow 1.0.6 → 1.1.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.
Files changed (55) hide show
  1. package/README.md +51 -29
  2. package/bin/dev-workflow.js +6 -0
  3. package/lib/constants.js +2 -2
  4. package/lib/init.js +13 -3
  5. package/lib/install-deps.js +88 -3
  6. package/lib/migrate-gsd.js +1 -1
  7. package/lib/post-update.js +153 -0
  8. package/lib/setup-wsl-browser.js +149 -0
  9. package/lib/uninstall.js +1 -1
  10. package/package.json +1 -1
  11. package/scaffold/en/agent-instructions.md +1 -1
  12. package/scaffold/en/commands/dw-analyze-project.md +22 -0
  13. package/scaffold/en/commands/dw-autopilot.md +3 -1
  14. package/scaffold/en/commands/dw-functional-doc.md +11 -3
  15. package/scaffold/en/commands/dw-generate-pr.md +2 -2
  16. package/scaffold/en/commands/dw-help.md +29 -14
  17. package/scaffold/en/commands/dw-qa.md +1 -1
  18. package/scaffold/en/commands/dw-redesign-ui.md +2 -2
  19. package/scaffold/en/commands/dw-review.md +7 -5
  20. package/scaffold/en/commands/dw-secure-audit.md +72 -15
  21. package/scaffold/en/commands/dw-update.md +16 -1
  22. package/scaffold/en/templates/constitution-template.md +8 -3
  23. package/scaffold/en/templates/functional-doc/playwright.flow.mjs.tpl +17 -0
  24. package/scaffold/pt-br/agent-instructions.md +1 -1
  25. package/scaffold/pt-br/commands/dw-analyze-project.md +22 -0
  26. package/scaffold/pt-br/commands/dw-autopilot.md +3 -1
  27. package/scaffold/pt-br/commands/dw-functional-doc.md +11 -3
  28. package/scaffold/pt-br/commands/dw-generate-pr.md +2 -2
  29. package/scaffold/pt-br/commands/dw-help.md +29 -14
  30. package/scaffold/pt-br/commands/dw-qa.md +1 -1
  31. package/scaffold/pt-br/commands/dw-redesign-ui.md +2 -2
  32. package/scaffold/pt-br/commands/dw-review.md +7 -5
  33. package/scaffold/pt-br/commands/dw-secure-audit.md +72 -15
  34. package/scaffold/pt-br/commands/dw-update.md +16 -1
  35. package/scaffold/pt-br/templates/constitution-template.md +8 -3
  36. package/scaffold/pt-br/templates/functional-doc/playwright.flow.mjs.tpl +17 -0
  37. package/scaffold/scripts/cdp-relay/Cargo.toml +16 -0
  38. package/scaffold/scripts/cdp-relay/src/main.rs +49 -0
  39. package/scaffold/scripts/functional-doc/generate-dossier.mjs +7 -9
  40. package/scaffold/scripts/functional-doc/run-playwright-flow.mjs +192 -183
  41. package/scaffold/scripts/lib/capture-screenshots.mjs +133 -0
  42. package/scaffold/scripts/lib/resolve-browser.mjs +405 -0
  43. package/scaffold/scripts/lib/ui-slop-detect.mjs +102 -0
  44. package/scaffold/skills/dw-testing-discipline/references/playwright-recipes.md +50 -0
  45. package/scaffold/skills/dw-ui-discipline/SKILL.md +5 -0
  46. package/scaffold/skills/dw-ui-discipline/references/color-oklch.md +60 -0
  47. package/scaffold/skills/dw-ui-discipline/references/motion.md +52 -0
  48. package/scaffold/skills/dw-ui-discipline/references/responsive.md +52 -0
  49. package/scaffold/skills/dw-ui-discipline/references/type-scale.md +48 -0
  50. package/scaffold/skills/dw-ui-discipline/references/ux-writing.md +52 -0
  51. package/scaffold/skills/security-review/SKILL.md +19 -0
  52. package/scaffold/skills/security-review/references/sast.md +67 -0
  53. package/scaffold/skills/security-review/references/secrets.md +46 -0
  54. package/scaffold/en/templates/functional-doc/playwright.spec.ts.tpl +0 -19
  55. package/scaffold/pt-br/templates/functional-doc/playwright.spec.ts.tpl +0 -19
package/README.md CHANGED
@@ -19,24 +19,24 @@ This will:
19
19
 
20
20
  > **Compozy-inspired disciplines.** Since 0.5.0, dev-workflow bundles three primitives — `dw-verify`, `dw-memory`, `dw-review-rigor` — adapted from the [Compozy](https://github.com/compozy/compozy) project and invoked internally by existing commands. See [docs/compozy-integration.md](docs/compozy-integration.md) for what was ported and what was not.
21
21
 
22
- Optional dependencies (Playwright browsers, react-doctor, Trivy, Docker):
22
+ Optional dependencies (Playwright browsers, react-doctor, Trivy, Semgrep, gitleaks, syft, Docker):
23
23
  ```bash
24
24
  npx @brunosps00/dev-workflow install-deps
25
25
  ```
26
26
 
27
27
  ## Commands
28
28
 
29
- dev-workflow v1.0.6 ships **31 commands** organized into four tiers. Most users only invoke Tier 1 + Tier 2.
29
+ dev-workflow v1.1.1 ships **31 commands** organized into four tiers. Most users only invoke Tier 1 + Tier 2.
30
30
 
31
31
  ### Tier 1 — Gateway (3)
32
32
 
33
33
  | Command | When |
34
34
  |---------|------|
35
- | **`/dw-autopilot "wish"`** | Default entry point in two invocations. First run completes PRD → TechSpec → Tasks and stops. Second run resumes from state, executes `/dw-goal --from-autopilot <slug>` for Run → Review → QA/Fix → Review, then Commit → PR. |
35
+ | **`/dw-autopilot "wish"`** | Default entry point in two invocations. First run completes PRD → TechSpec → Tasks and stops. Second run resumes from state, executes `/dw-goal --from-autopilot <slug>` for Run → Review → QA/Fix → Review, then Security Gate → Commit → PR. |
36
36
  | **`/dw-bugfix "description"`** | A bug report or pasted error. Triages bug-vs-feature-vs-scope, surgical fix or routes to a PRD. |
37
37
  | **`/dw-help [keyword]`** | Discover commands. Pass a keyword for shortcuts; `--advanced` reveals internal commands. |
38
38
 
39
- ### Tier 2 — Pipeline granular (7)
39
+ ### Tier 2 — Pipeline granular (9)
40
40
 
41
41
  Use these when you want step-by-step control instead of `/dw-autopilot`.
42
42
 
@@ -52,13 +52,13 @@ Use these when you want step-by-step control instead of `/dw-autopilot`.
52
52
  | **`/dw-commit`** | Atomic Conventional Commits for pending changes. Applies `dw-git-discipline` (one intent per commit, lint+tests+build green before). |
53
53
  | **`/dw-generate-pr [target]`** | Push the branch, draft a PR body with summary + test plan, open the browser. Hard gates: dw-verify PASS + secure-audit. |
54
54
 
55
- ### Tier 3 — Specialty (8)
55
+ ### Tier 3 — Specialty (10)
56
56
 
57
57
  | Command | What |
58
58
  |---------|------|
59
- | **`/dw-analyze-project`** | Scans the repo, writes `.dw/rules/` (per-module conventions, anti-patterns, naming). Step 8 offers to generate `.dw/constitution.md` (declarative principles the team commits to). Step 9 generates `.dw/rules/concerns.md` (risk map: hot spots, fragile integrations, hostile code, bug history). Run once per project; refresh after major refactors. |
60
- | **`/dw-redesign-ui "target"`** | Audits a frontend page, runs the `dw-ui-discipline` 4-question grounding, proposes 2-3 design directions, ships the redesign. WCAG 2.2 AA accessibility floor is non-negotiable. |
61
- | **`/dw-functional-doc`** | Maps screens + user flows into a functional doc, validated end-to-end with Playwright. |
59
+ | **`/dw-analyze-project`** | Scans the repo, writes `.dw/rules/` (per-module conventions, anti-patterns, naming). Step 8 offers `.dw/constitution.md`; Step 9 writes `.dw/rules/concerns.md`; Step 10 can synthesize a frontend `DESIGN.md` from existing tokens. Run once per project; refresh after major refactors. |
60
+ | **`/dw-redesign-ui "target"`** | Audits a frontend page, runs the `dw-ui-discipline` 4-question grounding, proposes 2-3 design directions, ships the redesign. WCAG 2.2 AA accessibility floor is non-negotiable; UI diffs can also run the deterministic impeccable slop detector. |
61
+ | **`/dw-functional-doc`** | Maps screens + user flows into a functional doc, validated end-to-end with Playwright. Uses the WSL-resilient browser resolver and can capture guided functional video evidence. |
62
62
  | **`/dw-context-budget`** | Audits context overhead from commands, skills, agents, instruction files, and MCPs. |
63
63
  | **`/dw-harness-audit`** | Deterministic health scorecard for the dev-workflow install, agents, wrappers, MCPs, and gates. |
64
64
  | **`/dw-skill-health`** | Audits installed skills and agents for bloat, duplication, and missing references. |
@@ -75,7 +75,7 @@ These are auto-invoked by Tier 1-3 commands. Available standalone via `/dw-help
75
75
  |---------|------|------------|
76
76
  | **`/dw-adr "decision"`** | Records an Architecture Decision Record at `.dw/spec/<prd>/adrs/`. | `/dw-plan techspec --council`; deviations from constitution |
77
77
  | **`/dw-intel "question"`** | Query codebase intelligence (`.dw/intel/`). `--build` (re)creates the index. | `/dw-plan`, `/dw-review`, `/dw-bugfix` |
78
- | **`/dw-secure-audit`** | Unified security: OWASP + Trivy SCA/secret/IaC + lockfile + supply-chain check. Hard gate. Flags: `--scan-only`, `--plan`, `--execute`. | `/dw-review`, `/dw-generate-pr` (for TS/Python/C#/Rust) |
78
+ | **`/dw-secure-audit`** | **Security Gate** (phase after review/QA, before commit/PR): OWASP + Semgrep SAST (diff/generated code) + gitleaks secrets + Trivy SCA/IaC + lockfile + supply-chain + outdated. Rigoroso: secrets/CRITICAL/HIGH block (secrets have no ADR escape). Flags: `--scan-only`, `--plan`, `--execute`. See [docs/security-gate.md](docs/security-gate.md). | `/dw-review`, `/dw-autopilot` (explicit step), enforced by `/dw-generate-pr` |
79
79
  | **`/dw-goal "<objective>"`** | Durable objective contract. Uses Codex native `/goal` when available and `.dw/goals/` everywhere for Codex, Copilot, Claude Code, and OpenCode. | `/dw-autopilot` after planning |
80
80
  | **`/dw-find-skills "query"`** | Searches `npx skills` ecosystem, vets, installs. | manual when extending the bundle |
81
81
  | **`/dw-update`** | Updates dev-workflow to latest npm release with rollback snapshot. | manual maintenance |
@@ -87,17 +87,17 @@ These are auto-invoked by Tier 1-3 commands. Available standalone via `/dw-help
87
87
 
88
88
  ```
89
89
  /dw-autopilot "wish" ------> First invocation: PRD → TechSpec → Tasks → STOP
90
- /dw-autopilot ------> Second invocation: /dw-goal → Commit → PR
90
+ /dw-autopilot ------> Second invocation: /dw-goal → Security Gate → Commit → PR
91
91
  --- OR step-by-step ---
92
92
 
93
93
  /dw-brainstorm --> /dw-plan --> .dw/spec/prd-{name}/{prd,techspec,tasks}.md
94
94
  |
95
- /dw-goal --> /dw-run → /dw-review → /dw-qa → /dw-review
95
+ /dw-goal --> /dw-run → /dw-review → /dw-qa → /dw-review → /dw-secure-audit
96
96
  |
97
97
  /dw-commit + /dw-generate-pr
98
98
 
99
99
  Manual alternative after /dw-plan:
100
- /dw-run → /dw-review → /dw-qa → /dw-review → /dw-commit → /dw-generate-pr
100
+ /dw-run → /dw-review → /dw-qa → /dw-review → /dw-secure-audit → /dw-commit → /dw-generate-pr
101
101
 
102
102
  Shortcuts:
103
103
  /dw-intel "question" Query codebase intelligence
@@ -116,19 +116,30 @@ A **constitution** is a declarative list of principles your team commits to (e.g
116
116
  **How it works:**
117
117
 
118
118
  - `/dw-analyze-project` offers three paths: synthesize from observed patterns (with your approval), install canonical defaults, or skip.
119
- - If `/dw-create-prd`, `/dw-create-techspec`, or `/dw-code-review` run **without** a constitution, they auto-install the defaults template (10 canonical principles at `severity: info`), notify in chat, and continue. Ausência nunca bloqueia.
119
+ - If `/dw-plan` or `/dw-review` run **without** a constitution, they auto-install the defaults template (10 canonical principles at `severity: info`), notify in chat, and continue. Ausência nunca bloqueia.
120
120
  - Once principles exist:
121
121
  - `severity: info` → reported, never blocks.
122
122
  - `severity: high` → blocks PR/techspec when violated, unless an ADR justifies the deviation.
123
123
  - `severity: critical` → blocks plus requires reviewer sign-off in the ADR.
124
124
  - Defaults start at `info`; you promote severities as your team trusts enforcement.
125
125
 
126
- **Tasks consistency check.** At the end of `/dw-create-tasks`, a 5-dimension consistency check validates PRD ↔ TechSpec ↔ Tasks alignment (FR coverage, task grounding, test coverage, dependency DAG, constitution alignment) and writes `.dw/spec/prd-<feature>/tasks-validation.md`. Any FAIL blocks user approval until resolved or explicitly overridden.
126
+ **Tasks consistency check.** At the end of `/dw-plan tasks`, a 5-dimension consistency check validates PRD ↔ TechSpec ↔ Tasks alignment (FR coverage, task grounding, test coverage, dependency DAG, constitution alignment) and writes `.dw/spec/prd-<feature>/tasks-validation.md`. Any FAIL blocks user approval until resolved or explicitly overridden.
127
127
 
128
128
  ## Template Overrides
129
129
 
130
130
  Customize templates locally without losing dev-workflow updates. Drop a file at `.dw/templates/overrides/<name>.md`; the override is used in place of the bundled core template on every `update`. Subdirectories work too (e.g., `.dw/templates/overrides/functional-doc/e2e-runbook.md`). See `.dw/templates/overrides/README.md` (created on init) for the workflow and `diff` cadence guidance.
131
131
 
132
+ ## Post-Update Actions
133
+
134
+ `dev-workflow update` refreshes managed files only: commands, templates, references, scripts, bundled skills, wrappers, agents, and MCP config. It does **not** overwrite project-derived docs such as `.dw/rules/`, `.dw/constitution.md`, `.dw/rules/concerns.md`, `.dw/intel/`, or frontend `DESIGN.md`.
135
+
136
+ After an update, the CLI prints **Post-update agent actions**. When `/dw-update` runs inside an agent, it should execute the listed commands in order:
137
+
138
+ 1. `/dw-analyze-project` when project-derived docs are missing or need refresh; this owns `.dw/rules/`, constitution, concerns map, and frontend `DESIGN.md`.
139
+ 2. `/dw-intel --build` when the codebase index is missing or stale.
140
+ 3. `/dw-harness-audit` to validate the install after managed files changed.
141
+ 4. `/dw-skill-health` to inspect refreshed skills and agents.
142
+
132
143
  ## Auto-Trigger (CLAUDE.md / AGENTS.md)
133
144
 
134
145
  `dev-workflow init` seeds two files at the project root with the same content: `CLAUDE.md` (read by Claude Code) and `AGENTS.md` (read by Codex CLI, Copilot CLI, and OpenCode). Together they tell the agent **when to invoke each `dw-*` command without being explicitly asked**.
@@ -188,6 +199,8 @@ your-project/
188
199
  │ ├── scripts/ # Utility scripts
189
200
  │ ├── spec/ # PRD directories — each contains tasks-validation.md
190
201
  │ ├── bugfixes/ # Persistent bugfix records: NNN-<slug>/{TASK.md, SUMMARY.md, fix-report.md} + review/, QA/
202
+ │ ├── goals/ # Durable goal state used by /dw-goal and /dw-autopilot
203
+ │ ├── secure-audit/ # Security Gate summaries and per-layer reports
191
204
  │ ├── subtasks/ # Local ephemeral subagent input packets and handoffs (pending/archive ignored by Git)
192
205
  │ └── STATE.md # Session state: Decisions, Blockers, Todos, Open Loops, Deferred Ideas, Lessons, Preferences (managed by /dw-pause + /dw-resume)
193
206
  ├── CLAUDE.md # Auto-trigger decision tree for Claude Code (merge-aware, includes Auto-Sizing Matrix)
@@ -224,6 +237,7 @@ Subagent handoffs use local packets under `.dw/subtasks/`:
224
237
  npx @brunosps00/dev-workflow subtask create --agent=dw-code-explorer --goal="Map the auth flow"
225
238
  npx @brunosps00/dev-workflow subtask complete --slug=<slug> --file=<handoff.md>
226
239
  npx @brunosps00/dev-workflow subtask consume
240
+ npx @brunosps00/dev-workflow subtask list
227
241
  ```
228
242
 
229
243
  ## Bundled Skills
@@ -245,15 +259,15 @@ These are not slash commands — they are primitives other commands call to enfo
245
259
 
246
260
  | Skill | Description | Invoked by | Inspired by |
247
261
  |-------|-------------|------------|-------------|
248
- | **dw-verify** | Enforces fresh verification evidence before any completion, commit, or PR claim — with Iron Law, gate function, and Verification Report template | `dw-run-task`, `dw-run-plan`, `dw-fix-qa`, `dw-bugfix`, `dw-code-review`, `dw-generate-pr` | [Compozy](https://github.com/compozy/compozy) `cy-final-verify` |
249
- | **dw-memory** | Two-tier workflow memory (shared `MEMORY.md` + per-task `<N>_memory.md`) with promotion test and compaction rules, so cross-task context persists cleanly | `dw-run-task`, `dw-run-plan`, `dw-autopilot` | [Compozy](https://github.com/compozy/compozy) `cy-workflow-memory` |
250
- | **dw-review-rigor** | Review discipline: de-duplication, severity ordering, verify-intent-before-flagging, skip-linter-issues, signal-over-volume | `dw-code-review`, `dw-review-implementation`, `dw-refactoring-analysis` | [Compozy](https://github.com/compozy/compozy) `cy-review-round` |
251
- | **dw-council** | Multi-advisor debate (3-5 archetypes) with steel-manning, concession tracking, and dissent-preserving synthesis. Opt-in only. | `dw-brainstorm --council`, `dw-create-techspec --council` | [Compozy](https://github.com/compozy/compozy) `cy-idea-factory` |
252
- | **dw-codebase-intel** | Codebase intelligence (`stack.json`, `files.json`, `apis.json`, `deps.json`, `arch.md`) with incremental updates and query patterns. Cross-cutting reference: `api-design-discipline` (Hyrum's Law, contract-first, error semantics) used when techspecs design API endpoints. | `/dw-intel`, `/dw-map-codebase`, `dw-create-techspec` | [`get-shit-done-cc`](https://github.com/gsd-build/get-shit-done) (MIT) + [`addyosmani/agent-skills`](https://github.com/addyosmani/agent-skills) (MIT) |
253
- | **dw-execute-phase** | Goal-backward 6-dimension plan verification (`plan-checker`) and wave-based parallel task execution (`executor`) with atomic commit, deviation handling, and checkpoint recovery | `dw-run-plan`, `dw-autopilot` | [`get-shit-done-cc`](https://github.com/gsd-build/get-shit-done) (MIT) |
254
- | **dw-source-grounding** | Detect → Fetch → Implement → Cite protocol with `[source: <url>, version: X.Y, retrieved: YYYY-MM-DD]` citations. Strict source-priority hierarchy (Tier 1 official docs > Tier 2 maintainer blogs > Tier 3 Stack Overflow as discovery only). | `dw-create-techspec`, `dw-deps-audit`, `dw-deep-research` | [`addyosmani/agent-skills`](https://github.com/addyosmani/agent-skills) (MIT) |
255
- | **dw-simplification** | Chesterton's Fence (understand WHY before changing), behavior-preserving refactor protocol (test gate before/after), complexity metrics (cyclomatic, cognitive, depth, fan-out), Rule of 500 for large refactors | `dw-code-review`, `dw-refactoring-analysis` | [`addyosmani/agent-skills`](https://github.com/addyosmani/agent-skills) (MIT) |
256
- | **dw-debug-protocol** | Stop-the-line discipline plus six-step triage (Reproduce → Localize → Reduce → Fix Root Cause → Guard → Verify End-to-End). Error categorization matrix; instrument-first non-reproducible-bug strategy. | `dw-bugfix`, `dw-fix-qa` | [`addyosmani/agent-skills`](https://github.com/addyosmani/agent-skills) (MIT) |
262
+ | **dw-verify** | Enforces fresh verification evidence before any completion, commit, or PR claim — with Iron Law, gate function, and Verification Report template | `/dw-run`, `/dw-goal`, `/dw-qa --fix`, `/dw-bugfix`, `/dw-review`, `/dw-generate-pr` | [Compozy](https://github.com/compozy/compozy) `cy-final-verify` |
263
+ | **dw-memory** | Two-tier workflow memory (shared `MEMORY.md` + per-task `<N>_memory.md`) with promotion test and compaction rules, so cross-task context persists cleanly | `/dw-run`, `/dw-goal`, `/dw-autopilot`, `/dw-pause`, `/dw-resume` | [Compozy](https://github.com/compozy/compozy) `cy-workflow-memory` |
264
+ | **dw-review-rigor** | Review discipline: de-duplication, severity ordering, verify-intent-before-flagging, skip-linter-issues, signal-over-volume | `/dw-review`, `/dw-brainstorm --refactor` | [Compozy](https://github.com/compozy/compozy) `cy-review-round` |
265
+ | **dw-council** | Multi-advisor debate (3-5 archetypes) with steel-manning, concession tracking, and dissent-preserving synthesis. Opt-in only. | `/dw-brainstorm --council`, `/dw-plan techspec --council` | [Compozy](https://github.com/compozy/compozy) `cy-idea-factory` |
266
+ | **dw-codebase-intel** | Codebase intelligence (`stack.json`, `files.json`, `apis.json`, `deps.json`, `arch.md`) with incremental updates and query patterns. Cross-cutting reference: `api-design-discipline` (Hyrum's Law, contract-first, error semantics) used when techspecs design API endpoints. | `/dw-intel`, `/dw-intel --build`, `/dw-plan techspec` | [`get-shit-done-cc`](https://github.com/gsd-build/get-shit-done) (MIT) + [`addyosmani/agent-skills`](https://github.com/addyosmani/agent-skills) (MIT) |
267
+ | **dw-execute-phase** | Goal-backward 6-dimension plan verification (`plan-checker`) and wave-based parallel task execution (`executor`) with atomic commit, deviation handling, and checkpoint recovery | `/dw-run`, `/dw-goal`, `/dw-autopilot` | [`get-shit-done-cc`](https://github.com/gsd-build/get-shit-done) (MIT) |
268
+ | **dw-source-grounding** | Detect → Fetch → Implement → Cite protocol with `[source: <url>, version: X.Y, retrieved: YYYY-MM-DD]` citations. Strict source-priority hierarchy (Tier 1 official docs > Tier 2 maintainer blogs > Tier 3 Stack Overflow as discovery only). | `/dw-plan techspec`, `/dw-secure-audit --plan`, `/dw-brainstorm --research` | [`addyosmani/agent-skills`](https://github.com/addyosmani/agent-skills) (MIT) |
269
+ | **dw-simplification** | Chesterton's Fence (understand WHY before changing), behavior-preserving refactor protocol (test gate before/after), complexity metrics (cyclomatic, cognitive, depth, fan-out), Rule of 500 for large refactors | `/dw-review`, `/dw-brainstorm --refactor` | [`addyosmani/agent-skills`](https://github.com/addyosmani/agent-skills) (MIT) |
270
+ | **dw-debug-protocol** | Stop-the-line discipline plus six-step triage (Reproduce → Localize → Reduce → Fix Root Cause → Guard → Verify End-to-End). Error categorization matrix; instrument-first non-reproducible-bug strategy. | `/dw-bugfix`, `/dw-qa --fix` | [`addyosmani/agent-skills`](https://github.com/addyosmani/agent-skills) (MIT) |
257
271
  | **dw-git-discipline** | Trunk-based pattern (1-3 day branches, daily rebase, feature flags), atomic commit discipline (one intent per commit; refactor separate from feature), Conventional Commits, branch hygiene | `dw-commit`, `dw-generate-pr` | [`addyosmani/agent-skills`](https://github.com/addyosmani/agent-skills) (MIT) |
258
272
 
259
273
  ### Domain expertise
@@ -278,7 +292,10 @@ Installed via `npx @brunosps00/dev-workflow install-deps`:
278
292
  | **Playwright** | Browser automation for QA, E2E tests, and visual validation | [playwright.dev](https://playwright.dev/) |
279
293
  | **Context7 MCP** | Contextual documentation lookup for AI assistants | [upstash/context7-mcp](https://github.com/upstash/context7-mcp) |
280
294
  | **react-doctor** | Health score and diagnostics for React projects | [react.doctor](https://www.react.doctor/) |
281
- | **Trivy** | Native binary scanner used by `/dw-security-check` for CVE, secret, and IaC scanning. `install-deps` detects presence and prints OS-specific install instructions (brew / curl script / choco / Docker) — does not install automatically. | [aquasecurity.github.io/trivy](https://aquasecurity.github.io/trivy/) |
295
+ | **Trivy** | Native binary scanner used by `/dw-secure-audit` for CVE, secret, and IaC scanning. `install-deps` detects presence and prints OS-specific install instructions (brew / curl script / choco / Docker) — does not install automatically. | [aquasecurity.github.io/trivy](https://aquasecurity.github.io/trivy/) |
296
+ | **Semgrep** | SAST layer for `/dw-secure-audit`, focused on generated-code diffs with pinned security rulesets. `install-deps` detects presence and prints OS-specific install instructions. | [semgrep.dev](https://semgrep.dev/) |
297
+ | **gitleaks** | Dedicated secret scanner for `/dw-secure-audit`; any confirmed secret blocks without ADR exception. `install-deps` detects presence and prints OS-specific install instructions. | [github.com/gitleaks/gitleaks](https://github.com/gitleaks/gitleaks) |
298
+ | **syft** | Optional SBOM/license inventory layer for `/dw-secure-audit`; advisory and non-blocking. `install-deps` detects presence and prints OS-specific install instructions. | [github.com/anchore/syft](https://github.com/anchore/syft) |
282
299
  | **Docker + Docker Compose** | Required by `/dw-new-project` and `/dw-dockerize` for dev dependency seeding and image generation. `install-deps` detects presence and prints OS-specific install instructions — does not install automatically. | [docs.docker.com](https://docs.docker.com/engine/install/) |
283
300
 
284
301
  ## Options
@@ -288,12 +305,17 @@ npx @brunosps00/dev-workflow init # Interactive languag
288
305
  npx @brunosps00/dev-workflow init --lang=en # English, skip prompt
289
306
  npx @brunosps00/dev-workflow init --lang=pt-br # Portuguese, skip prompt
290
307
  npx @brunosps00/dev-workflow init --force # Overwrite existing files
291
- npx @brunosps00/dev-workflow update # Update commands/templates only
292
- npx @brunosps00/dev-workflow install-deps # Install Playwright, react-doctor; check Trivy, Docker
308
+ npx @brunosps00/dev-workflow update # Update managed files + print post-update agent actions
309
+ npx @brunosps00/dev-workflow list-installed # Show managed install state
310
+ npx @brunosps00/dev-workflow doctor # Check wrappers, agents, skills, MCPs, gates
311
+ npx @brunosps00/dev-workflow repair # Reconcile managed files from recorded install state
312
+ npx @brunosps00/dev-workflow install-deps # Install Playwright, react-doctor; check security scanners + Docker
313
+ npx @brunosps00/dev-workflow setup-wsl-browser # WSL NAT: build CDP relay + add Hyper-V firewall rule
293
314
  npx @brunosps00/dev-workflow install-azure-skills # Opt-in: Azure skills + Microsoft Learn MCP
294
315
  npx @brunosps00/dev-workflow install-azure-skills --products=azure-aks,azure-openai # Subset override
295
316
  npx @brunosps00/dev-workflow install-aws-skills # Opt-in: AWS skills + AWS MCP Server (needs uv + aws cli + creds)
296
317
  npx @brunosps00/dev-workflow install-aws-skills --region=eu-central-1 # Region override
318
+ npx @brunosps00/dev-workflow uninstall # Remove managed files while preserving user data
297
319
  npx @brunosps00/dev-workflow help # Show help
298
320
  ```
299
321
 
@@ -304,12 +326,12 @@ After running `npx @brunosps00/dev-workflow init`:
304
326
  1. **Run `/dw-analyze-project`** in your AI assistant to generate project rules
305
327
  2. **Run `/dw-brainstorm`** to start planning a new feature
306
328
  3. **Run `/dw-help`** to see all available commands and workflows
307
- 4. **(Optional) Run `npx @brunosps00/dev-workflow install-deps`** to install Playwright + react-doctor and check Trivy + Docker
308
- 5. **Run `/dw-map-codebase`** once your project has source files to build the queryable index in `.dw/intel/`
329
+ 4. **(Optional) Run `npx @brunosps00/dev-workflow install-deps`** to install Playwright + react-doctor and check Trivy/Semgrep/gitleaks/syft + Docker
330
+ 5. **Run `/dw-intel --build`** once your project has source files to build the queryable index in `.dw/intel/`
309
331
 
310
332
  ## Acknowledgements
311
333
 
312
- Codebase intelligence (`/dw-intel`, `/dw-map-codebase`, the `dw-codebase-intel` bundled skill) and phase execution patterns (the `dw-execute-phase` bundled skill, with its `plan-checker` and `executor` agents) were adapted from [`get-shit-done-cc`](https://github.com/gsd-build/get-shit-done) by gsd-build (MIT). Schemas (`stack.json`, `files.json`, `apis.json`, `deps.json`, `arch.md`), the goal-backward verification protocol, and the wave-based parallel execution pattern come from there. dev-workflow specifics: `.dw/` namespace instead of `.planning/`, agent-driven runtime instead of `gsd-sdk` CLI, integration with the rest of the `dw-*` command surface.
334
+ Codebase intelligence (`/dw-intel`, `/dw-intel --build`, the `dw-codebase-intel` bundled skill) and phase execution patterns (the `dw-execute-phase` bundled skill, with its `plan-checker` and `executor` agents) were adapted from [`get-shit-done-cc`](https://github.com/gsd-build/get-shit-done) by gsd-build (MIT). Schemas (`stack.json`, `files.json`, `apis.json`, `deps.json`, `arch.md`), the goal-backward verification protocol, and the wave-based parallel execution pattern come from there. dev-workflow specifics: `.dw/` namespace instead of `.planning/`, agent-driven runtime instead of `gsd-sdk` CLI, integration with the rest of the `dw-*` command surface.
313
335
 
314
336
  Source-driven development, code simplification, debugging discipline, and git workflow patterns adapted from [`addyosmani/agent-skills`](https://github.com/addyosmani/agent-skills) by Addy Osmani (MIT) into the bundled `dw-source-grounding`, `dw-simplification`, `dw-debug-protocol`, and `dw-git-discipline` skills. Performance-optimization workflow (`vercel-react-best-practices/references/perf-discipline.md`) and API-design discipline (`dw-codebase-intel/references/api-design-discipline.md`) also incorporated as enhancements to existing bundled skills. Browser security-boundary and three-workflow-patterns (originally from `addyosmani/agent-skills/browser-devtools`) now live inside `dw-testing-discipline/references/`.
315
337
 
@@ -5,6 +5,7 @@ const installDeps = require('../lib/install-deps');
5
5
  const installAzureSkills = require('../lib/install-azure-skills');
6
6
  const installAwsSkills = require('../lib/install-aws-skills');
7
7
  const uninstall = require('../lib/uninstall');
8
+ const setupWslBrowser = require('../lib/setup-wsl-browser');
8
9
 
9
10
  const args = process.argv.slice(2);
10
11
  const command = args[0];
@@ -39,12 +40,14 @@ const HELP_TEXT = `
39
40
  Commands:
40
41
  init Scaffold .dw/ (commands, templates, references, scripts, skills, rules, MCPs)
41
42
  update Update managed files (commands, templates, references, scripts, skills, wrappers, MCPs)
43
+ and print post-update agent actions for project-derived docs/health checks
42
44
  Preserves: .dw/rules/, .dw/spec/, .dw/bugfixes/, .dw/STATE.md, .agents/skills/azure/, user data
43
45
  list-installed Show dev-workflow install state for this project
44
46
  doctor Check managed files, wrappers, agents, and MCP configuration
45
47
  repair Reconcile managed files using the recorded install state
46
48
  subtask Create, complete, consume, and list local subagent handoffs
47
49
  install-deps Install system dependencies (Playwright browsers, MCP servers)
50
+ setup-wsl-browser (WSL) Build the CDP relay on Windows + add the Hyper-V firewall rule so flows can drive the real Windows browser
48
51
  install-azure-skills Opt-in: clone curated Azure skills from MicrosoftDocs/Agent-Skills
49
52
  into .agents/skills/azure/ and register the Microsoft Learn MCP
50
53
  server (HTTP, no-auth). Interactive category selection.
@@ -95,6 +98,9 @@ async function main() {
95
98
  case 'install-deps':
96
99
  installDeps.run();
97
100
  break;
101
+ case 'setup-wsl-browser':
102
+ setupWslBrowser.run();
103
+ break;
98
104
  case 'install-azure-skills':
99
105
  await installAzureSkills.run();
100
106
  break;
package/lib/constants.js CHANGED
@@ -25,7 +25,7 @@ const COMMANDS = {
25
25
  { name: 'dw-resume', description: 'Trigger when user says "resume work", "where did we stop?", or starts a session in a project with an existing .dw/STATE.md. Reads STATE.md, presents a TLDR, and suggests the next dw-* command.' },
26
26
  { name: 'dw-review', description: 'Trigger when user asks to review code, check quality, or verify PR readiness. Default runs L2 (PRD coverage) + L3 (code quality). Flags --coverage-only / --code-only / --bugfix <slug>.' },
27
27
  { name: 'dw-run', description: 'Trigger when user wants to execute tasks. Default runs all pending in dependency order; \'run <task-id>\' runs one; \'run --resume\' continues an interrupted plan.' },
28
- { name: 'dw-secure-audit', description: 'Unified security audit: OWASP + Trivy SCA/secret/IaC + lockfile + supply-chain compromise check. Hidden; auto-invoked by /dw-review and /dw-generate-pr.' },
28
+ { name: 'dw-secure-audit', description: 'Security Gate: OWASP + Semgrep SAST (diff) + gitleaks secrets + Trivy SCA/IaC + lockfile + supply-chain + outdated. Rigoroso: secrets/CRITICAL/HIGH block. Auto-invoked by /dw-review and /dw-generate-pr, explicit phase in /dw-autopilot, and runnable standalone.' },
29
29
  { name: 'dw-skill-health', description: 'Audits installed skills and agents for bloat, duplication, missing references, and stale or unused modules.' },
30
30
  { name: 'dw-subtask-start', description: 'Creates a minimal input packet for a subagent without injecting the parent transcript.' },
31
31
  { name: 'dw-subtask-complete', description: 'Records a structured subagent handoff with result, files, decisions, risks, verification, and blockers.' },
@@ -58,7 +58,7 @@ const COMMANDS = {
58
58
  { name: 'dw-resume', description: 'Trigger quando usuario diz "retoma", "onde paramos?" ou comeca sessao num projeto com .dw/STATE.md existente. Le STATE.md, apresenta TLDR e sugere proximo comando dw-*.' },
59
59
  { name: 'dw-review', description: 'Trigger quando usuario pede pra revisar codigo, checar qualidade ou validar prontidao pra PR. Default roda L2 (cobertura PRD) + L3 (qualidade). Flags --coverage-only / --code-only / --bugfix <slug>.' },
60
60
  { name: 'dw-run', description: 'Trigger quando usuario quer executar tasks. Default roda todas pendentes em ordem de dependencia; \'run <task-id>\' roda uma; \'run --resume\' continua plan interrompido.' },
61
- { name: 'dw-secure-audit', description: 'Audit unificado de seguranca: OWASP + Trivy SCA/secret/IaC + lockfile + supply-chain compromise. Hidden; auto-invocado por /dw-review e /dw-generate-pr.' },
61
+ { name: 'dw-secure-audit', description: 'Security Gate: OWASP + Semgrep SAST (diff) + gitleaks secrets + Trivy SCA/IaC + lockfile + supply-chain + outdated. Rigoroso: secrets/CRITICAL/HIGH bloqueiam. Auto-invocado por /dw-review e /dw-generate-pr, fase explicita no /dw-autopilot, e executavel standalone.' },
62
62
  { name: 'dw-skill-health', description: 'Audita skills e agentes instalados por bloat, duplicacao, referencias quebradas e modulos sem uso.' },
63
63
  { name: 'dw-subtask-start', description: 'Cria um input packet minimo para subagente sem injetar transcript bruto do parent.' },
64
64
  { name: 'dw-subtask-complete', description: 'Registra handoff estruturado do subagente com resultado, arquivos, decisoes, riscos, verificacao e bloqueios.' },
package/lib/init.js CHANGED
@@ -10,6 +10,7 @@ const { migrate: migrateSkills } = require('./migrate-skills');
10
10
  const { hasExistingInstall, readInstallState, writeInstallState, listManagedFiles } = require('./install-state');
11
11
  const { resolveInstallSelection } = require('./profiles');
12
12
  const { ensureSubtaskLayout } = require('./subtasks');
13
+ const { printPostUpdateActions } = require('./post-update');
13
14
 
14
15
  const SCAFFOLD_DIR = path.join(__dirname, '..', 'scaffold');
15
16
 
@@ -315,10 +316,19 @@ async function run({ force = false, lang = null, mode = 'init', profile = null,
315
316
  console.log(` ${'='.repeat(40)}`);
316
317
  console.log(` Done! ${totalCreated} created, ${totalSkipped} skipped, ${totalOverwritten} overwritten`);
317
318
  console.log();
319
+ if (isUpdate) {
320
+ printPostUpdateActions(projectRoot);
321
+ }
318
322
  console.log(' Next steps:');
319
- console.log(' 1. Run /dw-analyze-project to generate project rules');
320
- console.log(' 2. Run /dw-brainstorm to start a new feature');
321
- console.log(' 3. Run /dw-help to see all available commands');
323
+ if (isUpdate) {
324
+ console.log(' 1. If running inside an agent, run the post-update actions now');
325
+ console.log(' 2. Otherwise reload/restart the agent session before invoking them');
326
+ console.log(' 3. Run /dw-help to see all available commands');
327
+ } else {
328
+ console.log(' 1. Run /dw-analyze-project to generate project rules');
329
+ console.log(' 2. Run /dw-brainstorm to start a new feature');
330
+ console.log(' 3. Run /dw-help to see all available commands');
331
+ }
322
332
  console.log();
323
333
  }
324
334
 
@@ -6,9 +6,9 @@ function run() {
6
6
 
7
7
  const deps = [
8
8
  {
9
- name: 'Playwright browsers',
9
+ name: 'Playwright browsers (Chromium + deps)',
10
10
  check: 'npx playwright --version',
11
- install: 'npx playwright install --with-deps',
11
+ install: 'npx playwright install --with-deps chromium',
12
12
  },
13
13
  {
14
14
  name: 'Context7 MCP',
@@ -31,7 +31,44 @@ function run() {
31
31
  ' Windows: choco install trivy (or: scoop install trivy)',
32
32
  ' Docker: docker pull aquasec/trivy:latest (use via alias or wrapper)',
33
33
  '',
34
- 'Once installed, /dw-security-check will use it for CVE, secret, and IaC scanning.',
34
+ 'Once installed, /dw-secure-audit will use it for CVE, secret, and IaC scanning.',
35
+ ],
36
+ },
37
+ {
38
+ name: 'Semgrep (SAST)',
39
+ check: 'semgrep --version',
40
+ install: null,
41
+ instructions: [
42
+ 'Semgrep powers the SAST layer of /dw-secure-audit (semantic analysis of generated code).',
43
+ ' pipx: pipx install semgrep (recommended — isolated)',
44
+ ' pip: python3 -m pip install --user semgrep',
45
+ ' macOS: brew install semgrep',
46
+ ' Docker: docker pull semgrep/semgrep:latest (use via alias or wrapper)',
47
+ '',
48
+ 'The gate runs pinned rulesets (p/security-audit, p/owasp-top-ten, p/secrets) on the diff.',
49
+ ],
50
+ },
51
+ {
52
+ name: 'gitleaks (secret scanner)',
53
+ check: 'gitleaks version',
54
+ install: null,
55
+ instructions: [
56
+ 'gitleaks is the dedicated secret scanner for /dw-secure-audit (any hit blocks the gate).',
57
+ ' macOS: brew install gitleaks',
58
+ ' Linux: download from https://github.com/gitleaks/gitleaks/releases (or: go install github.com/gitleaks/gitleaks/v8@latest)',
59
+ ' Windows: scoop install gitleaks (or: choco install gitleaks)',
60
+ ' Docker: docker pull zricethezav/gitleaks:latest',
61
+ ],
62
+ },
63
+ {
64
+ name: 'syft (SBOM, optional)',
65
+ check: 'syft version',
66
+ install: null,
67
+ instructions: [
68
+ 'syft generates the SBOM for the advisory SBOM/license layer of /dw-secure-audit (optional, non-blocking).',
69
+ ' macOS: brew install syft',
70
+ ' Linux: curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin',
71
+ ' Windows: scoop install syft',
35
72
  ],
36
73
  },
37
74
  {
@@ -93,6 +130,54 @@ function run() {
93
130
  if (failed) parts.push(`${failed} failed`);
94
131
  console.log(` Done! ${parts.join(', ')}`);
95
132
  console.log();
133
+
134
+ checkPlaywrightVersion();
135
+ printBrowserGuidance();
136
+ }
137
+
138
+ // page.screencast (used by /dw-functional-doc to record video, including over CDP) needs
139
+ // Playwright >= 1.60. Warn if the installed version is older.
140
+ function checkPlaywrightVersion() {
141
+ try {
142
+ const raw = execSync('npx playwright --version', { stdio: 'pipe', timeout: 15000 }).toString();
143
+ const match = raw.match(/(\d+)\.(\d+)\.(\d+)/);
144
+ if (!match) return;
145
+ const [, major, minor] = match.map(Number);
146
+ if (major < 1 || (major === 1 && minor < 60)) {
147
+ console.log(` \x1b[33m⚠ Playwright ${match[0]} detected.\x1b[0m /dw-functional-doc video needs >= 1.60 (page.screencast).`);
148
+ console.log(' Upgrade in your project: npm i -D @playwright/test@latest');
149
+ console.log();
150
+ }
151
+ } catch {
152
+ // playwright not resolvable here; the flow runner reports it at runtime
153
+ }
154
+ }
155
+
156
+ function isWsl() {
157
+ if (process.env.WSL_DISTRO_NAME) return true;
158
+ try {
159
+ return /microsoft/i.test(require('fs').readFileSync('/proc/version', 'utf8'));
160
+ } catch {
161
+ return false;
162
+ }
163
+ }
164
+
165
+ function printBrowserGuidance() {
166
+ if (!isWsl()) return;
167
+ const mirrored = require('fs').existsSync('/sys/class/net/loopback0');
168
+ console.log(' Browser automation on WSL (dw-qa / dw-functional-doc / dw-redesign-ui):');
169
+ console.log(' Default: full headless Chromium (desktop-faithful, no WSLg) — works out of the box.');
170
+ console.log(' To drive the real Windows browser, set BROWSER_TEST to its exe path, e.g.');
171
+ console.log(' BROWSER_TEST="/mnt/c/Program Files (x86)/Microsoft/Edge/Application/msedge.exe".');
172
+ if (mirrored) {
173
+ console.log(' Mirrored networking detected — connects to the Windows browser on 127.0.0.1 directly.');
174
+ } else {
175
+ console.log(' NAT networking — run `npx @brunosps00/dev-workflow setup-wsl-browser` once to build the');
176
+ console.log(' cdp-relay.exe (needs Rust on Windows) and add the Hyper-V firewall rule. Otherwise flows');
177
+ console.log(' fall back to the local headless Chromium (faithful video, no Windows browser).');
178
+ }
179
+ console.log(' Details: .dw/skills/dw-testing-discipline/references/playwright-recipes.md ("Browser on WSL").');
180
+ console.log();
96
181
  }
97
182
 
98
183
  module.exports = { run };
@@ -124,7 +124,7 @@ function migrate(projectRoot) {
124
124
  if (stats.agents_removed) console.log(` - .claude/agents/gsd-*.md (${stats.agents_removed} files removed; native dw-* agents bundled in skills)`);
125
125
  if (stats.hooks_removed) console.log(` - .claude/hooks/gsd-*.js (${stats.hooks_removed} files removed; not used by dev-workflow)`);
126
126
  if (stats.manifest_removed) console.log(' - .claude/gsd-file-manifest.json (removed)');
127
- console.log(' Done. Native /dw-intel, /dw-map-codebase, /dw-run-plan (with bundled phase-execution agents) now provide what GSD provided.');
127
+ console.log(' Done. Native /dw-intel, /dw-intel --build, and /dw-run (with bundled phase-execution agents) now provide what GSD provided.');
128
128
  console.log();
129
129
 
130
130
  return stats;
@@ -0,0 +1,153 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ const SKIP_DIRS = new Set([
5
+ '.git',
6
+ '.dw',
7
+ '.agents',
8
+ '.claude',
9
+ '.codex',
10
+ '.github',
11
+ '.opencode',
12
+ 'node_modules',
13
+ 'dist',
14
+ 'build',
15
+ 'coverage',
16
+ '.next',
17
+ 'out',
18
+ ]);
19
+
20
+ const FRONTEND_DEPS = [
21
+ '@angular/core',
22
+ '@remix-run/react',
23
+ 'astro',
24
+ 'next',
25
+ 'nuxt',
26
+ 'react',
27
+ 'solid-js',
28
+ 'svelte',
29
+ 'vue',
30
+ ];
31
+
32
+ function listPostUpdateActions(projectRoot) {
33
+ const actions = [];
34
+ const analysisReasons = [];
35
+
36
+ if (!exists(projectRoot, '.dw/rules/index.md')) {
37
+ analysisReasons.push('missing .dw/rules/index.md');
38
+ }
39
+ if (!exists(projectRoot, '.dw/rules/concerns.md')) {
40
+ analysisReasons.push('missing .dw/rules/concerns.md');
41
+ }
42
+ if (!exists(projectRoot, '.dw/constitution.md')) {
43
+ analysisReasons.push('missing .dw/constitution.md');
44
+ }
45
+
46
+ const frontendProjects = findFrontendProjects(projectRoot);
47
+ const missingDesignAuthority = frontendProjects.filter((dir) => !hasDesignAuthority(dir));
48
+ if (missingDesignAuthority.length) {
49
+ analysisReasons.push(
50
+ `frontend design authority missing for ${formatPaths(projectRoot, missingDesignAuthority)}`,
51
+ );
52
+ }
53
+
54
+ if (analysisReasons.length) {
55
+ actions.push({
56
+ command: '/dw-analyze-project',
57
+ reason: `refresh project-derived docs (${analysisReasons.join('; ')})`,
58
+ });
59
+ }
60
+
61
+ if (!hasCodebaseIntel(projectRoot)) {
62
+ actions.push({
63
+ command: '/dw-intel --build',
64
+ reason: 'build .dw/intel/ codebase index for the refreshed command surface',
65
+ });
66
+ }
67
+
68
+ actions.push({
69
+ command: '/dw-harness-audit',
70
+ reason: 'validate commands, wrappers, agents, MCPs, and gates after update',
71
+ });
72
+ actions.push({
73
+ command: '/dw-skill-health',
74
+ reason: 'audit refreshed bundled skills and agents for bloat, duplication, and stale references',
75
+ });
76
+
77
+ return actions;
78
+ }
79
+
80
+ function printPostUpdateActions(projectRoot) {
81
+ const actions = listPostUpdateActions(projectRoot);
82
+ console.log(' Post-update agent actions:');
83
+ console.log(' The CLI refreshed managed files. Project-derived docs require the agent to run commands:');
84
+ for (const action of actions) {
85
+ console.log(` - ${action.command} - ${action.reason}`);
86
+ }
87
+ console.log(' /dw-update consumes this list and runs the applicable commands after the update.');
88
+ console.log();
89
+ }
90
+
91
+ function hasCodebaseIntel(projectRoot) {
92
+ return ['.dw/intel/stack.json', '.dw/intel/files.json', '.dw/intel/arch.md'].every((rel) =>
93
+ exists(projectRoot, rel),
94
+ );
95
+ }
96
+
97
+ function findFrontendProjects(projectRoot) {
98
+ const projects = [];
99
+ walk(projectRoot, (dir) => {
100
+ const pkgPath = path.join(dir, 'package.json');
101
+ if (!fs.existsSync(pkgPath)) return;
102
+ try {
103
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
104
+ const deps = {
105
+ ...(pkg.dependencies || {}),
106
+ ...(pkg.devDependencies || {}),
107
+ ...(pkg.peerDependencies || {}),
108
+ };
109
+ if (FRONTEND_DEPS.some((dep) => Object.prototype.hasOwnProperty.call(deps, dep))) {
110
+ projects.push(dir);
111
+ }
112
+ } catch {
113
+ // Ignore malformed package.json here; doctor handles managed-file validation.
114
+ }
115
+ });
116
+ return projects;
117
+ }
118
+
119
+ function walk(dir, visit) {
120
+ if (!fs.existsSync(dir)) return;
121
+ visit(dir);
122
+ let entries;
123
+ try {
124
+ entries = fs.readdirSync(dir, { withFileTypes: true });
125
+ } catch {
126
+ return;
127
+ }
128
+ for (const entry of entries) {
129
+ if (!entry.isDirectory() || SKIP_DIRS.has(entry.name)) continue;
130
+ walk(path.join(dir, entry.name), visit);
131
+ }
132
+ }
133
+
134
+ function hasDesignAuthority(projectDir) {
135
+ return ['DESIGN.md', 'BRAND.md', 'STYLE_GUIDE.md'].some((name) =>
136
+ fs.existsSync(path.join(projectDir, name)),
137
+ );
138
+ }
139
+
140
+ function exists(projectRoot, relativePath) {
141
+ return fs.existsSync(path.join(projectRoot, relativePath));
142
+ }
143
+
144
+ function formatPaths(projectRoot, dirs) {
145
+ const formatted = dirs.slice(0, 3).map((dir) => path.relative(projectRoot, dir) || '.');
146
+ if (dirs.length > formatted.length) formatted.push(`+${dirs.length - formatted.length} more`);
147
+ return formatted.join(', ');
148
+ }
149
+
150
+ module.exports = {
151
+ listPostUpdateActions,
152
+ printPostUpdateActions,
153
+ };