@brunosps00/dev-workflow 0.10.0 → 0.13.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.
Files changed (120) hide show
  1. package/README.md +78 -6
  2. package/lib/constants.js +20 -20
  3. package/lib/init.js +44 -4
  4. package/lib/migrate-skills.js +129 -0
  5. package/lib/removed-bundled-skills.js +16 -0
  6. package/lib/uninstall.js +6 -2
  7. package/lib/utils.js +51 -4
  8. package/package.json +1 -1
  9. package/scaffold/en/agent-instructions.md +68 -0
  10. package/scaffold/en/commands/dw-analyze-project.md +61 -0
  11. package/scaffold/en/commands/dw-autopilot.md +1 -1
  12. package/scaffold/en/commands/dw-brainstorm.md +1 -1
  13. package/scaffold/en/commands/dw-bugfix.md +3 -3
  14. package/scaffold/en/commands/dw-code-review.md +28 -0
  15. package/scaffold/en/commands/dw-create-prd.md +16 -0
  16. package/scaffold/en/commands/dw-create-tasks.md +42 -0
  17. package/scaffold/en/commands/dw-create-techspec.md +18 -1
  18. package/scaffold/en/commands/dw-deps-audit.md +1 -1
  19. package/scaffold/en/commands/dw-fix-qa.md +1 -1
  20. package/scaffold/en/commands/dw-functional-doc.md +2 -2
  21. package/scaffold/en/commands/dw-help.md +1 -1
  22. package/scaffold/en/commands/dw-redesign-ui.md +7 -7
  23. package/scaffold/en/commands/dw-run-qa.md +4 -4
  24. package/scaffold/en/commands/dw-run-task.md +2 -2
  25. package/scaffold/en/templates/constitution-template.md +111 -0
  26. package/scaffold/pt-br/agent-instructions.md +68 -0
  27. package/scaffold/pt-br/commands/dw-analyze-project.md +61 -0
  28. package/scaffold/pt-br/commands/dw-autopilot.md +1 -1
  29. package/scaffold/pt-br/commands/dw-brainstorm.md +1 -1
  30. package/scaffold/pt-br/commands/dw-bugfix.md +3 -3
  31. package/scaffold/pt-br/commands/dw-code-review.md +28 -0
  32. package/scaffold/pt-br/commands/dw-create-prd.md +16 -0
  33. package/scaffold/pt-br/commands/dw-create-tasks.md +42 -0
  34. package/scaffold/pt-br/commands/dw-create-techspec.md +18 -1
  35. package/scaffold/pt-br/commands/dw-deps-audit.md +1 -1
  36. package/scaffold/pt-br/commands/dw-fix-qa.md +1 -1
  37. package/scaffold/pt-br/commands/dw-functional-doc.md +2 -2
  38. package/scaffold/pt-br/commands/dw-help.md +1 -1
  39. package/scaffold/pt-br/commands/dw-redesign-ui.md +7 -7
  40. package/scaffold/pt-br/commands/dw-run-qa.md +4 -4
  41. package/scaffold/pt-br/commands/dw-run-task.md +2 -2
  42. package/scaffold/pt-br/templates/constitution-template.md +111 -0
  43. package/scaffold/skills/dw-council/SKILL.md +1 -1
  44. package/scaffold/skills/dw-testing-discipline/SKILL.md +148 -0
  45. package/scaffold/skills/dw-testing-discipline/references/ai-agent-gates.md +170 -0
  46. package/scaffold/skills/dw-testing-discipline/references/anti-patterns.md +336 -0
  47. package/scaffold/skills/dw-testing-discipline/references/flaky-discipline.md +163 -0
  48. package/scaffold/skills/dw-testing-discipline/references/iron-laws.md +128 -0
  49. package/scaffold/skills/dw-testing-discipline/references/playwright-recipes.md +282 -0
  50. package/scaffold/skills/dw-testing-discipline/references/positive-patterns.md +241 -0
  51. package/scaffold/skills/{webapp-testing → dw-testing-discipline}/references/security-boundary.md +1 -1
  52. package/scaffold/skills/dw-ui-discipline/SKILL.md +128 -0
  53. package/scaffold/skills/dw-ui-discipline/references/accessibility-floor.md +225 -0
  54. package/scaffold/skills/dw-ui-discipline/references/anti-slop.md +162 -0
  55. package/scaffold/skills/dw-ui-discipline/references/curated-defaults.md +195 -0
  56. package/scaffold/skills/dw-ui-discipline/references/hard-gate.md +142 -0
  57. package/scaffold/skills/dw-ui-discipline/references/state-matrix.md +101 -0
  58. package/scaffold/templates-overrides-readme.md +75 -0
  59. package/scaffold/skills/ui-ux-pro-max/LICENSE +0 -21
  60. package/scaffold/skills/ui-ux-pro-max/SKILL.md +0 -659
  61. package/scaffold/skills/ui-ux-pro-max/data/_sync_all.py +0 -414
  62. package/scaffold/skills/ui-ux-pro-max/data/app-interface.csv +0 -31
  63. package/scaffold/skills/ui-ux-pro-max/data/charts.csv +0 -26
  64. package/scaffold/skills/ui-ux-pro-max/data/colors.csv +0 -162
  65. package/scaffold/skills/ui-ux-pro-max/data/design.csv +0 -1776
  66. package/scaffold/skills/ui-ux-pro-max/data/draft.csv +0 -1779
  67. package/scaffold/skills/ui-ux-pro-max/data/google-fonts.csv +0 -1924
  68. package/scaffold/skills/ui-ux-pro-max/data/icons.csv +0 -106
  69. package/scaffold/skills/ui-ux-pro-max/data/landing.csv +0 -35
  70. package/scaffold/skills/ui-ux-pro-max/data/products.csv +0 -162
  71. package/scaffold/skills/ui-ux-pro-max/data/react-performance.csv +0 -45
  72. package/scaffold/skills/ui-ux-pro-max/data/stacks/angular.csv +0 -51
  73. package/scaffold/skills/ui-ux-pro-max/data/stacks/astro.csv +0 -54
  74. package/scaffold/skills/ui-ux-pro-max/data/stacks/flutter.csv +0 -53
  75. package/scaffold/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +0 -56
  76. package/scaffold/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +0 -53
  77. package/scaffold/skills/ui-ux-pro-max/data/stacks/laravel.csv +0 -51
  78. package/scaffold/skills/ui-ux-pro-max/data/stacks/nextjs.csv +0 -53
  79. package/scaffold/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +0 -51
  80. package/scaffold/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +0 -59
  81. package/scaffold/skills/ui-ux-pro-max/data/stacks/react-native.csv +0 -52
  82. package/scaffold/skills/ui-ux-pro-max/data/stacks/react.csv +0 -54
  83. package/scaffold/skills/ui-ux-pro-max/data/stacks/shadcn.csv +0 -61
  84. package/scaffold/skills/ui-ux-pro-max/data/stacks/svelte.csv +0 -54
  85. package/scaffold/skills/ui-ux-pro-max/data/stacks/swiftui.csv +0 -51
  86. package/scaffold/skills/ui-ux-pro-max/data/stacks/threejs.csv +0 -54
  87. package/scaffold/skills/ui-ux-pro-max/data/stacks/vue.csv +0 -50
  88. package/scaffold/skills/ui-ux-pro-max/data/styles.csv +0 -85
  89. package/scaffold/skills/ui-ux-pro-max/data/typography.csv +0 -74
  90. package/scaffold/skills/ui-ux-pro-max/data/ui-reasoning.csv +0 -162
  91. package/scaffold/skills/ui-ux-pro-max/data/ux-guidelines.csv +0 -100
  92. package/scaffold/skills/ui-ux-pro-max/scripts/core.py +0 -262
  93. package/scaffold/skills/ui-ux-pro-max/scripts/design_system.py +0 -1148
  94. package/scaffold/skills/ui-ux-pro-max/scripts/search.py +0 -114
  95. package/scaffold/skills/ui-ux-pro-max/skills/brand/SKILL.md +0 -97
  96. package/scaffold/skills/ui-ux-pro-max/skills/design/SKILL.md +0 -302
  97. package/scaffold/skills/ui-ux-pro-max/skills/design-system/SKILL.md +0 -244
  98. package/scaffold/skills/ui-ux-pro-max/templates/base/quick-reference.md +0 -297
  99. package/scaffold/skills/ui-ux-pro-max/templates/base/skill-content.md +0 -358
  100. package/scaffold/skills/ui-ux-pro-max/templates/platforms/agent.json +0 -21
  101. package/scaffold/skills/ui-ux-pro-max/templates/platforms/augment.json +0 -18
  102. package/scaffold/skills/ui-ux-pro-max/templates/platforms/claude.json +0 -21
  103. package/scaffold/skills/ui-ux-pro-max/templates/platforms/codebuddy.json +0 -21
  104. package/scaffold/skills/ui-ux-pro-max/templates/platforms/codex.json +0 -21
  105. package/scaffold/skills/ui-ux-pro-max/templates/platforms/continue.json +0 -21
  106. package/scaffold/skills/ui-ux-pro-max/templates/platforms/copilot.json +0 -21
  107. package/scaffold/skills/ui-ux-pro-max/templates/platforms/cursor.json +0 -21
  108. package/scaffold/skills/ui-ux-pro-max/templates/platforms/droid.json +0 -21
  109. package/scaffold/skills/ui-ux-pro-max/templates/platforms/gemini.json +0 -21
  110. package/scaffold/skills/ui-ux-pro-max/templates/platforms/kilocode.json +0 -21
  111. package/scaffold/skills/ui-ux-pro-max/templates/platforms/kiro.json +0 -21
  112. package/scaffold/skills/ui-ux-pro-max/templates/platforms/opencode.json +0 -21
  113. package/scaffold/skills/ui-ux-pro-max/templates/platforms/qoder.json +0 -21
  114. package/scaffold/skills/ui-ux-pro-max/templates/platforms/roocode.json +0 -21
  115. package/scaffold/skills/ui-ux-pro-max/templates/platforms/trae.json +0 -21
  116. package/scaffold/skills/ui-ux-pro-max/templates/platforms/warp.json +0 -18
  117. package/scaffold/skills/ui-ux-pro-max/templates/platforms/windsurf.json +0 -21
  118. package/scaffold/skills/webapp-testing/SKILL.md +0 -138
  119. package/scaffold/skills/webapp-testing/assets/test-helper.js +0 -56
  120. /package/scaffold/skills/{webapp-testing → dw-testing-discipline}/references/three-workflow-patterns.md +0 -0
package/README.md CHANGED
@@ -13,7 +13,7 @@ This will:
13
13
  2. Create `.dw/commands/` with 31 workflow commands
14
14
  3. Create `.dw/templates/` with document templates (PRD, TechSpec, Tasks, ADR, etc.)
15
15
  4. Create `.dw/rules/` (populated by `/dw-analyze-project`)
16
- 5. Install bundled skills (`dw-verify`, `dw-memory`, `dw-review-rigor`, `ui-ux-pro-max`, `security-review`, etc.) to `.agents/skills/`
16
+ 5. Install bundled skills (`dw-verify`, `dw-memory`, `dw-review-rigor`, `dw-ui-discipline`, `dw-testing-discipline`, `security-review`, etc.) to `.agents/skills/`
17
17
  6. Generate skill wrappers for Claude Code, Codex, Copilot, and OpenCode
18
18
  7. Configure MCP servers (Context7 + Playwright)
19
19
 
@@ -55,7 +55,7 @@ Executes all pending tasks via the `dw-execute-phase` bundled skill — gated by
55
55
  Analyzes and fixes bugs with automatic triage that distinguishes between bugs, feature requests, and excessive scope. Asks exactly 3 clarification questions before proposing a solution. Supports Direct mode (executes fix immediately) and Analysis mode (`--analysis`) that generates a document for the techspec/tasks pipeline.
56
56
 
57
57
  #### `/dw-redesign-ui`
58
- Audits existing frontend pages or components, proposes 2-3 design directions using `ui-ux-pro-max` (colors, typography, layout), waits for user approval, then implements the redesign following the project's CSS methodology. Framework-agnostic (React, Angular, Vue). Generates a design contract persisted for consistency across tasks.
58
+ Audits existing frontend pages or components, then runs the `dw-ui-discipline` hard-gate (brand authorities or curated defaults, surface job sentence, complete state matrix, scene sentence) before proposing 2-3 design directions. Each direction self-checks against the 14 anti-slop patterns. WCAG 2.2 AA floor is non-negotiable at validation. Framework-agnostic (React, Angular, Vue). Generates a design contract persisted for consistency across tasks.
59
59
 
60
60
  ### Quality
61
61
 
@@ -158,6 +158,59 @@ Shortcuts:
158
158
  /dw-redesign-ui "target" Visual redesign of a page or component
159
159
  ```
160
160
 
161
+ ## Constitution
162
+
163
+ A **constitution** is a declarative list of principles your team commits to (e.g., "every state-changing endpoint requires server-side authorization", "every bug fix ships with a regression test"). It lives at `.dw/constitution.md` and complements `.dw/rules/`:
164
+
165
+ | File | Type | Authored by |
166
+ |------|------|-------------|
167
+ | `.dw/rules/` | Analytical — describes what the code IS (observed patterns) | `/dw-analyze-project` |
168
+ | `.dw/constitution.md` | Declarative — describes what the code SHOULD BE (committed principles) | `/dw-analyze-project` (Step 8) or auto-installed defaults |
169
+
170
+ **How it works:**
171
+
172
+ - `/dw-analyze-project` offers three paths: synthesize from observed patterns (with your approval), install canonical defaults, or skip.
173
+ - 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.
174
+ - Once principles exist:
175
+ - `severity: info` → reported, never blocks.
176
+ - `severity: high` → blocks PR/techspec when violated, unless an ADR justifies the deviation.
177
+ - `severity: critical` → blocks plus requires reviewer sign-off in the ADR.
178
+ - Defaults start at `info`; you promote severities as your team trusts enforcement.
179
+
180
+ **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.
181
+
182
+ ## Template Overrides
183
+
184
+ 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.
185
+
186
+ ## Auto-Trigger (CLAUDE.md / AGENTS.md)
187
+
188
+ `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**.
189
+
190
+ **What's inside:**
191
+
192
+ - **Trigger Map** — 15 mappings from user intent ("Implement X", "Bug in Y", "Review my PR", ...) to the `dw-*` command the agent should run. `/dw-autopilot` is the safest default for non-trivial feature requests.
193
+ - **Hard Gates** — reminders that constitution violations (high/critical), missing `dw-verify` PASS, and security failures block downstream commands.
194
+ - **Escape Hatches** — explicit cases where the agent should NOT auto-trigger (typos, exploration, aesthetic edits, user opt-out).
195
+
196
+ **Why two files:** Claude Code, Codex, Copilot, and OpenCode all support agent-instruction conventions but use different filenames. Shipping both means every supported platform picks up the same trigger logic out of the box.
197
+
198
+ **Why descriptions, too:** every `dw-*` command's description leads with `Trigger when <user signal>...` so the agent can pick the right one even without consulting the trigger map. Both mechanisms reinforce each other.
199
+
200
+ **Merge-aware update.** The content lives between `<!-- dev-workflow:start -->` and `<!-- dev-workflow:end -->` markers. Anything you add **outside** the markers (your own house rules, project-specific guidelines) is preserved on every `dev-workflow update` — only the block inside is refreshed.
201
+
202
+ ```bash
203
+ # After init, both files exist at project root
204
+ ls CLAUDE.md AGENTS.md
205
+
206
+ # Edit OUTSIDE the markers freely — survives updates
207
+ echo "## My team's house rules" >> CLAUDE.md
208
+ echo "..." >> CLAUDE.md
209
+
210
+ # Run update — block is refreshed, your additions stay
211
+ npx @brunosps00/dev-workflow update
212
+ ```
213
+
161
214
  ## Platform Support
162
215
 
163
216
  | Platform | Wrapper Location | Status |
@@ -176,10 +229,14 @@ your-project/
176
229
  ├── .dw/
177
230
  │ ├── commands/ # 30 workflow command files
178
231
  │ ├── templates/ # Document templates (PRD, TechSpec, etc.)
232
+ │ │ └── overrides/ # Project-local template customizations (override > core)
179
233
  │ ├── rules/ # Project-specific rules (run /dw-analyze-project)
234
+ │ ├── constitution.md # Declarative principles (auto-installed when missing)
180
235
  │ ├── references/ # Reference documentation
181
236
  │ ├── scripts/ # Utility scripts
182
- │ └── spec/ # PRD directories created by commands
237
+ │ └── spec/ # PRD directories each contains tasks-validation.md
238
+ ├── CLAUDE.md # Auto-trigger decision tree for Claude Code (merge-aware)
239
+ ├── AGENTS.md # Same content for Codex / Copilot / OpenCode
183
240
  ├── .claude/
184
241
  │ ├── skills/ # Claude Code wrappers
185
242
  │ └── settings.json # MCP servers (Context7, Playwright)
@@ -212,12 +269,12 @@ These are not slash commands — they are primitives other commands call to enfo
212
269
 
213
270
  | Skill | Description | Source | License |
214
271
  |-------|-------------|--------|---------|
215
- | **ui-ux-pro-max** | Design intelligence: 50+ styles, 161 color palettes, 57 font pairings, 99 UX guidelines across 10 stacks | [Next Level Builder](https://github.com/skills-sh) | MIT |
272
+ | **dw-ui-discipline** | UI doctrine: 4-checkpoint hard-gate (brand authorities or curated defaults, surface job sentence, state matrix, scene sentence), 14 anti-slop patterns + 17 anti-defaults, WCAG 2.2 AA floor with verification recipes, 10 curated palette/font defaults for bootstrap | [pedronauck/skills](https://github.com/pedronauck/skills) `ui-craft` | MIT |
273
+ | **dw-testing-discipline** | Testing doctrine: Six Iron Laws, 12 positive patterns, 25 anti-patterns across 5 families (Brittleness/Flakiness/Mock-misuse/Process/AI-specific), 7 mandatory AI agent gates, flaky discipline + SLOs, Playwright recipes, browser security-boundary patterns | [pedronauck/skills](https://github.com/pedronauck/skills) `testing-boss` + [`addyosmani/agent-skills`](https://github.com/addyosmani/agent-skills) | MIT |
216
274
  | **vercel-react-best-practices** | 67 React/Next.js performance optimization rules across 8 priority categories. Wraps the rules with `references/perf-discipline.md` (measure → identify → fix → verify → guard) so perf work is data-driven, not vibes-based | [Vercel Labs](https://github.com/vercel-labs/agent-skills) + [`addyosmani/agent-skills`](https://github.com/addyosmani/agent-skills) | MIT |
217
275
  | **security-review** | Systematic vulnerability review based on OWASP with confidence-based reporting | [OWASP Cheat Sheet Series](https://cheatsheetseries.owasp.org/) | CC BY-SA 4.0 |
218
276
  | **humanizer** | Detects and removes 24 AI writing patterns based on Wikipedia's "Signs of AI Writing" guide | [Wikipedia AI Writing Guide](https://en.wikipedia.org/wiki/Wikipedia:Signs_of_AI_writing) | -- |
219
277
  | **remotion-best-practices** | 25+ rules for video creation in React with Remotion | [Remotion](https://www.remotion.dev/) | -- |
220
- | **webapp-testing** | Playwright-based browser testing toolkit for E2E validation and screenshots. Cross-cutting references: `security-boundary` (every byte from a browser is potentially attacker-controlled) and `three-workflow-patterns` (UI bugs vs network issues vs perf — distinct workflows, don't conflate) | [Playwright](https://playwright.dev/) + [`addyosmani/agent-skills`](https://github.com/addyosmani/agent-skills) | -- |
221
278
 
222
279
  ## Dependencies
223
280
 
@@ -257,7 +314,22 @@ After running `npx @brunosps00/dev-workflow init`:
257
314
 
258
315
  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.
259
316
 
260
- 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`), API-design discipline (`dw-codebase-intel/references/api-design-discipline.md`), and browser-DevTools patterns (`webapp-testing/references/{security-boundary, three-workflow-patterns}`) also incorporated as enhancements to existing bundled skills.
317
+ 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/`.
318
+
319
+ Spec-Driven Development patterns — declarative constitution (`.dw/constitution.md`), cross-artifact consistency check (PRD ↔ TechSpec ↔ Tasks), and template override layer (`.dw/templates/overrides/`) — adapted from [`github/spec-kit`](https://github.com/github/spec-kit) by GitHub (MIT). dev-workflow specifics: embedded into existing commands instead of new slash commands, severity-graded enforcement (`info`/`high`/`critical`) with ADR-justified deviation as the escape hatch, ausência-of-constitution never blocks (auto-installs defaults and continues), and integration with the analytical `.dw/rules/` already produced by `/dw-analyze-project`.
320
+
321
+ UI discipline (hard-gate, 14 anti-slop patterns, 17 anti-defaults, WCAG 2.2 AA floor) and testing doctrine (Six Iron Laws, 25 anti-patterns across 5 families, 7 AI agent gates, flaky discipline) adapted from [`pedronauck/skills`](https://github.com/pedronauck/skills) `ui-craft` and `testing-boss` (MIT) into the bundled `dw-ui-discipline` and `dw-testing-discipline` skills. dev-workflow specifics: 10 curated palette/font defaults bootstrap discipline when no design authority exists; Playwright recipes from earlier `webapp-testing` migrate into `dw-testing-discipline/references/playwright-recipes.md`; both skills wire into 11 commands across the pipeline.
322
+
323
+ ## Migration from v0.12.x
324
+
325
+ The `dev-workflow update` command automatically removes the two replaced skills and installs the new ones — no manual action required:
326
+
327
+ - `ui-ux-pro-max` → replaced by `dw-ui-discipline` (auto-removed on update)
328
+ - `webapp-testing` → replaced by `dw-testing-discipline` (auto-removed on update)
329
+
330
+ The cleanup also detects and removes any **orphan `dw-*` wrappers** in `.claude/skills/`, `.agents/skills/`, and `.opencode/commands/` whose names no longer exist in the current scaffold (e.g., commands removed in v0.10 like `dw-execute-phase`, `dw-quick` that may still have wrappers from older installs).
331
+
332
+ If you had **custom edits** inside `.agents/skills/ui-ux-pro-max/` or `.agents/skills/webapp-testing/`, back them up before running update — the migrator removes the entire directory. If you customized templates instead, those live in `.dw/templates/overrides/` (introduced in v0.11) and are preserved.
261
333
 
262
334
  ## License
263
335
 
package/lib/constants.js CHANGED
@@ -2,21 +2,21 @@ const COMMANDS = {
2
2
  en: [
3
3
  { name: 'dw-adr', description: 'Records an architectural decision and the trade-offs accepted, before they get lost.' },
4
4
  { name: 'dw-analyze-project', description: 'Scans the repo to learn its stack and conventions, then writes the rules other commands rely on.' },
5
- { name: 'dw-autopilot', description: 'Takes a wish and runs the full PRD-to-PR pipeline, stopping only at three approval gates.' },
5
+ { name: 'dw-autopilot', description: 'Trigger when user asks to implement, build, create, or add a feature non-trivially. Runs full PRD-to-PR pipeline with three gates.' },
6
6
  { name: 'dw-brainstorm', description: 'Refines an idea using the product\'s existing features as ground truth, before any PRD.' },
7
- { name: 'dw-bugfix', description: 'Triages a bug report, asks three sharp questions, then fixes it or routes it to a PRD.' },
8
- { name: 'dw-code-review', description: 'Level-3 review against PRD, rules, tests, and security; saves a verdict you can act on.' },
9
- { name: 'dw-commit', description: 'Groups changes by intent and writes Conventional Commits messages that read clean.' },
10
- { name: 'dw-create-prd', description: 'Writes a PRD after asking the questions that would otherwise haunt the techspec later.' },
11
- { name: 'dw-create-tasks', description: 'Breaks the PRD and techspec into tasks small enough to ship one at a time.' },
12
- { name: 'dw-create-techspec', description: 'Translates a finished PRD into a techspec the team can actually build from.' },
7
+ { name: 'dw-bugfix', description: 'Trigger when user reports a bug, pastes an error, or describes broken behavior. Triages with three questions, then fixes or routes to PRD.' },
8
+ { name: 'dw-code-review', description: 'Trigger when user asks to review code, check quality, or verify PR readiness. Level-3 review with APPROVED/REJECTED verdict.' },
9
+ { name: 'dw-commit', description: 'Trigger when implementation is complete and pending changes need to be committed. Atomic commits with Conventional Commits messages.' },
10
+ { name: 'dw-create-prd', description: 'Trigger when user has a feature idea and needs a written spec before implementation. Asks the questions a techspec would otherwise inherit.' },
11
+ { name: 'dw-create-tasks', description: 'Trigger after PRD + techspec exist and the team is ready to break work into shippable units. Includes a 5-dimension consistency check.' },
12
+ { name: 'dw-create-techspec', description: 'Trigger when a PRD is approved and architecture must be defined before tasks. Adds framework choices, test strategy, and constitution alignment.' },
13
13
  { name: 'dw-deep-research', description: 'Researches a topic across sources, tracks citations, and flags claims that don\'t check out.' },
14
14
  { name: 'dw-deps-audit', description: 'Finds outdated and supply-chain-compromised packages, drafts a per-package update plan, and runs scoped QA after each upgrade.' },
15
15
  { name: 'dw-dockerize', description: 'Reads a project, detects the stack and runtime deps, then proposes Dockerfile and docker-compose for dev and prod with explicit trade-offs.' },
16
16
  { name: 'dw-find-skills', description: 'Searches the npx skills ecosystem for a skill matching what you need, vets it, and installs it where you choose.' },
17
17
  { name: 'dw-fix-qa', description: 'Fixes bugs found in QA and retests them with screenshot evidence until they stay fixed.' },
18
18
  { name: 'dw-functional-doc', description: 'Maps screens and user flows into a functional doc, validated end-to-end with Playwright.' },
19
- { name: 'dw-generate-pr', description: 'Pushes the branch and opens a PR with a body that explains what changed and how to test it.' },
19
+ { name: 'dw-generate-pr', description: 'Trigger when commits are ready and the branch needs a PR. Pushes branch and opens PR with summary + test plan + hard verify gate.' },
20
20
  { name: 'dw-help', description: 'Lists every command and the flows that connect them. Pass a keyword for a contextual shortcut.' },
21
21
  { name: 'dw-intel', description: 'Answers questions about the codebase by querying .dw/intel/ (built by /dw-map-codebase) with .dw/rules/ and grep as fallbacks.' },
22
22
  { name: 'dw-map-codebase', description: 'Builds a queryable index in .dw/intel/ (stack, files, apis, deps, arch) so other commands stop re-exploring the codebase.' },
@@ -25,30 +25,30 @@ const COMMANDS = {
25
25
  { name: 'dw-refactoring-analysis', description: 'Catalogs code smells in Fowler\'s vocabulary and ranks them by impact, P0 to P3.' },
26
26
  { name: 'dw-review-implementation', description: 'Maps every PRD requirement to the code that delivers it, then runs /dw-code-review for the Level 3 quality layer.' },
27
27
  { name: 'dw-revert-task', description: 'Reverts the commits of one task, but only after checking nothing downstream depends on it.' },
28
- { name: 'dw-run-plan', description: 'Runs every pending task in order, with PRD-compliance review at the end.' },
28
+ { name: 'dw-run-plan', description: 'Trigger when user wants to execute all pending tasks. Goal-backward plan check, then wave-based parallel execution with atomic commits.' },
29
29
  { name: 'dw-run-qa', description: 'Drives the browser to test happy paths, edge cases, and accessibility, with screenshot proof.' },
30
- { name: 'dw-run-task', description: 'Implements one task, runs the validation that comes with it, and commits when it passes.' },
30
+ { name: 'dw-run-task', description: 'Trigger when user wants to execute one specific task by ID. Implements, validates with mandatory tests, commits when passing.' },
31
31
  { name: 'dw-security-check', description: 'OWASP review plus Trivy CVE/secret/IaC scan for TS, Python, C#, or Rust. CRITICAL or HIGH blocks the PR.' },
32
32
  { name: 'dw-update', description: 'Updates dev-workflow to the latest npm release in-place, with a snapshot you can roll back to.' },
33
33
  ],
34
34
  'pt-br': [
35
35
  { name: 'dw-adr', description: 'Registra uma decisao arquitetural e os trade-offs aceitos, antes que se percam.' },
36
36
  { name: 'dw-analyze-project', description: 'Escaneia o repo para aprender stack e convencoes, e escreve as regras que os outros commands usam.' },
37
- { name: 'dw-autopilot', description: 'Pega um desejo e roda do PRD ao PR, parando so em tres gates de aprovacao.' },
37
+ { name: 'dw-autopilot', description: 'Trigger quando usuario pede pra implementar, criar ou adicionar uma feature nao-trivial. Roda pipeline completo PRD-ao-PR com tres gates.' },
38
38
  { name: 'dw-brainstorm', description: 'Refina uma ideia usando as features existentes do produto como base, antes de qualquer PRD.' },
39
- { name: 'dw-bugfix', description: 'Tria um bug, faz tres perguntas certas, e entao corrige ou redireciona para PRD.' },
40
- { name: 'dw-code-review', description: 'Review Nivel 3 contra PRD, rules, testes e seguranca; gera um veredicto acionavel.' },
41
- { name: 'dw-commit', description: 'Agrupa as mudancas por intencao e escreve mensagens Conventional Commits limpas.' },
42
- { name: 'dw-create-prd', description: 'Escreve um PRD depois de fazer as perguntas que assombrariam o techspec depois.' },
43
- { name: 'dw-create-tasks', description: 'Quebra PRD e techspec em tasks pequenas o suficiente para entregar uma de cada vez.' },
44
- { name: 'dw-create-techspec', description: 'Traduz um PRD pronto em um techspec que o time consegue construir de fato.' },
39
+ { name: 'dw-bugfix', description: 'Trigger quando usuario reporta bug, cola erro ou descreve comportamento quebrado. Tria com tres perguntas, depois corrige ou roteia pra PRD.' },
40
+ { name: 'dw-code-review', description: 'Trigger quando usuario pede pra revisar codigo, checar qualidade ou validar prontidao pra PR. Review Nivel 3 com veredicto APROVADO/REPROVADO.' },
41
+ { name: 'dw-commit', description: 'Trigger quando implementacao esta completa e ha mudancas pendentes pra commit. Commits atomicos com mensagens Conventional Commits.' },
42
+ { name: 'dw-create-prd', description: 'Trigger quando usuario tem ideia de feature e precisa de spec escrito antes de implementar. Faz as perguntas que o techspec herdaria.' },
43
+ { name: 'dw-create-tasks', description: 'Trigger depois que PRD + techspec existem e o time vai quebrar em unidades entregaveis. Inclui consistency check em 5 dimensoes.' },
44
+ { name: 'dw-create-techspec', description: 'Trigger quando PRD esta aprovado e arquitetura precisa ser definida antes das tasks. Adiciona escolhas de framework, testes e alinhamento de constitution.' },
45
45
  { name: 'dw-deep-research', description: 'Pesquisa um topico em varias fontes, rastreia citacoes e marca o que nao confere.' },
46
46
  { name: 'dw-deps-audit', description: 'Encontra pacotes desatualizados e comprometidos por supply-chain, monta plano de update por pacote e roda QA do que foi afetado.' },
47
47
  { name: 'dw-dockerize', description: 'Le um projeto, detecta stack e deps de runtime, e propoe Dockerfile e docker-compose para dev e prod com trade-offs explicitos.' },
48
48
  { name: 'dw-find-skills', description: 'Busca no ecossistema npx skills uma skill que resolva o que voce precisa, valida e instala onde voce escolher.' },
49
49
  { name: 'dw-fix-qa', description: 'Corrige bugs do QA e retesta com evidencia em screenshot ate ficarem estaveis.' },
50
50
  { name: 'dw-functional-doc', description: 'Mapeia telas e fluxos em um dossie funcional, validado E2E com Playwright.' },
51
- { name: 'dw-generate-pr', description: 'Faz push da branch e abre um PR com corpo explicando o que mudou e como testar.' },
51
+ { name: 'dw-generate-pr', description: 'Trigger quando commits estao prontos e branch precisa de PR. Push da branch e abre PR com summary + test plan + hard verify gate.' },
52
52
  { name: 'dw-help', description: 'Lista todos os commands e os fluxos que os conectam. Passe uma keyword para atalho contextual.' },
53
53
  { name: 'dw-intel', description: 'Responde perguntas sobre o codebase consultando .dw/intel/ (do /dw-map-codebase) com .dw/rules/ e grep como fallback.' },
54
54
  { name: 'dw-map-codebase', description: 'Constroi um indice queryable em .dw/intel/ (stack, files, apis, deps, arch) para outros comandos pararem de re-explorar o codebase.' },
@@ -57,9 +57,9 @@ const COMMANDS = {
57
57
  { name: 'dw-refactoring-analysis', description: 'Cataloga code smells no vocabulario de Fowler e ranqueia por impacto, P0 a P3.' },
58
58
  { name: 'dw-review-implementation', description: 'Mapeia cada requisito do PRD ao codigo que o entrega, e roda /dw-code-review para a camada de qualidade Nivel 3.' },
59
59
  { name: 'dw-revert-task', description: 'Reverte os commits de uma task, mas so depois de checar que nada a frente depende dela.' },
60
- { name: 'dw-run-plan', description: 'Roda todas as tasks pendentes em ordem, com review de PRD compliance no final.' },
60
+ { name: 'dw-run-plan', description: 'Trigger quando usuario quer executar todas as tasks pendentes. Plan check goal-backward, depois execucao paralela em ondas com commits atomicos.' },
61
61
  { name: 'dw-run-qa', description: 'Pilota o browser para testar fluxo feliz, edge cases e acessibilidade, com screenshot.' },
62
- { name: 'dw-run-task', description: 'Implementa uma task, roda a validacao que vem com ela, e commita quando passa.' },
62
+ { name: 'dw-run-task', description: 'Trigger quando usuario quer executar uma task especifica por ID. Implementa, valida com testes obrigatorios, commita quando passa.' },
63
63
  { name: 'dw-security-check', description: 'Review OWASP + scan Trivy CVE/secret/IaC para TS, Python, C# ou Rust. CRITICAL ou HIGH bloqueia PR.' },
64
64
  { name: 'dw-update', description: 'Atualiza o dev-workflow para o release mais recente no npm, com snapshot para rollback.' },
65
65
  ],
package/lib/init.js CHANGED
@@ -1,10 +1,11 @@
1
1
  const path = require('path');
2
2
  const { COMMANDS } = require('./constants');
3
- const { ensureDir, copyDir, writeFile, log } = require('./utils');
3
+ const { ensureDir, copyDir, writeFile, upsertDelimitedBlock, log } = require('./utils');
4
4
  const { selectLanguage } = require('./prompts');
5
5
  const { generateWrappers } = require('./wrappers');
6
6
  const { installMCPs } = require('./mcp');
7
7
  const { migrate: migrateGsd } = require('./migrate-gsd');
8
+ const { migrate: migrateSkills } = require('./migrate-skills');
8
9
 
9
10
  const SCAFFOLD_DIR = path.join(__dirname, '..', 'scaffold');
10
11
 
@@ -20,8 +21,10 @@ async function run({ force = false, lang = null, mode = 'init' }) {
20
21
  console.log(` ${'='.repeat(40)}\n`);
21
22
 
22
23
  // 0. GSD migration (idempotent; only runs if legacy GSD artifacts are detected)
24
+ // 0.1. Skill migration: removed bundled skills + orphan dw-* wrappers (idempotent)
23
25
  if (isUpdate) {
24
26
  migrateGsd(projectRoot);
27
+ migrateSkills(projectRoot);
25
28
  }
26
29
 
27
30
  // 1. Select language
@@ -48,18 +51,35 @@ async function run({ force = false, lang = null, mode = 'init' }) {
48
51
  totalOverwritten += cmdResults.overwritten;
49
52
  console.log(` ${cmdResults.created} created, ${cmdResults.skipped} skipped, ${cmdResults.overwritten} overwritten\n`);
50
53
 
51
- // 3. Copy templates
54
+ // 3. Copy templates (override-aware: .dw/templates/overrides/<name> wins over scaffold core)
52
55
  console.log(' Templates:');
56
+ const templatesDir = path.join(projectRoot, '.dw', 'templates');
57
+ const overridesDir = path.join(templatesDir, 'overrides');
53
58
  const tplResults = copyDir(
54
59
  path.join(langDir, 'templates'),
55
- path.join(projectRoot, '.dw', 'templates'),
56
- managedForce
60
+ templatesDir,
61
+ managedForce,
62
+ overridesDir
57
63
  );
58
64
  totalCreated += tplResults.created;
59
65
  totalSkipped += tplResults.skipped;
60
66
  totalOverwritten += tplResults.overwritten;
61
67
  console.log(` ${tplResults.created} created, ${tplResults.skipped} skipped, ${tplResults.overwritten} overwritten\n`);
62
68
 
69
+ // 3.1. Seed .dw/templates/overrides/ with README on first init (never overwritten)
70
+ ensureDir(overridesDir);
71
+ const overridesReadmeSrc = path.join(SCAFFOLD_DIR, 'templates-overrides-readme.md');
72
+ const overridesReadmeDest = path.join(overridesDir, 'README.md');
73
+ if (require('fs').existsSync(overridesReadmeSrc)) {
74
+ const ovrStatus = writeFile(
75
+ overridesReadmeDest,
76
+ require('fs').readFileSync(overridesReadmeSrc, 'utf-8'),
77
+ false
78
+ );
79
+ if (ovrStatus === 'created') totalCreated++;
80
+ else totalSkipped++;
81
+ }
82
+
63
83
  // 3.5. Copy references (language-specific)
64
84
  const refsSrcDir = path.join(langDir, 'references');
65
85
  if (require('fs').existsSync(refsSrcDir)) {
@@ -127,6 +147,26 @@ async function run({ force = false, lang = null, mode = 'init' }) {
127
147
  console.log(` ${skillsResults.created} created, ${skillsResults.skipped} skipped, ${skillsResults.overwritten} overwritten\n`);
128
148
  }
129
149
 
150
+ // 5.7. Install CLAUDE.md + AGENTS.md with auto-trigger decision tree
151
+ // Both files receive the same content (Claude Code reads CLAUDE.md; Codex/Copilot/OpenCode
152
+ // converge on AGENTS.md). Merge-aware: user edits outside the dev-workflow markers are preserved.
153
+ const agentInstructionsSrc = path.join(langDir, 'agent-instructions.md');
154
+ if (require('fs').existsSync(agentInstructionsSrc)) {
155
+ console.log(' Agent instructions:');
156
+ const blockContent = require('fs').readFileSync(agentInstructionsSrc, 'utf-8');
157
+ const startMarker = '<!-- dev-workflow:start -->';
158
+ const endMarker = '<!-- dev-workflow:end -->';
159
+ for (const fileName of ['CLAUDE.md', 'AGENTS.md']) {
160
+ const target = path.join(projectRoot, fileName);
161
+ const status = upsertDelimitedBlock(target, blockContent, startMarker, endMarker);
162
+ log(status === 'unchanged' ? 'skipped' : (status === 'created' ? 'created' : 'overwritten'), target);
163
+ if (status === 'created') totalCreated++;
164
+ else if (status === 'updated') totalOverwritten++;
165
+ else totalSkipped++;
166
+ }
167
+ console.log();
168
+ }
169
+
130
170
  // 6. Create .opencode/package.json
131
171
  const opencodePackageJson = path.join(projectRoot, '.opencode', 'package.json');
132
172
  const opencodeContent = JSON.stringify({ dependencies: { '@opencode-ai/plugin': '1.2.17' } }, null, 2) + '\n';
@@ -0,0 +1,129 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const { COMMANDS } = require('./constants');
4
+ const removedSkills = require('./removed-bundled-skills');
5
+
6
+ /**
7
+ * Cleanup-on-update for dev-workflow.
8
+ *
9
+ * Two complementary scans:
10
+ *
11
+ * 1. Removed bundled skills (data-driven from `removed-bundled-skills.js`):
12
+ * Detects `.agents/skills/<name>/` directories that match the manifest of
13
+ * skills removed in past releases. Removes them and notes the replacement.
14
+ *
15
+ * 2. Orphan command wrappers (state-comparison vs `constants.js`):
16
+ * Lists `.claude/skills/dw-*`, `.agents/skills/dw-*`, and
17
+ * `.opencode/commands/dw-*.md` wrappers on disk. Any `dw-*` wrapper whose
18
+ * base name is NOT present in the current `COMMANDS[lang]` is removed.
19
+ *
20
+ * Only touches names with prefix `dw-` (or names explicitly listed in the
21
+ * manifest). Never touches third-party skills/commands.
22
+ *
23
+ * Idempotent: silent when nothing to clean.
24
+ *
25
+ * Run automatically from lib/init.js when mode === 'update'.
26
+ */
27
+ function migrate(projectRoot) {
28
+ const removed = scanRemovedBundledSkills(projectRoot);
29
+ const orphans = scanOrphanCommandWrappers(projectRoot);
30
+
31
+ if (removed.length === 0 && orphans.length === 0) {
32
+ return null; // silent — nothing to clean
33
+ }
34
+
35
+ console.log('\n Skill migration:');
36
+
37
+ for (const entry of removed) {
38
+ console.log(
39
+ ` \x1b[33m-\x1b[0m [v${entry.removedIn}] Removing legacy skill ${entry.name} (replaced by ${entry.replacedBy})`
40
+ );
41
+ rmRecursive(entry.path);
42
+ }
43
+
44
+ for (const entry of orphans) {
45
+ const rel = path.relative(projectRoot, entry.path);
46
+ console.log(
47
+ ` \x1b[33m-\x1b[0m [orphan] Removing wrapper ${rel} — command no longer exists`
48
+ );
49
+ rmRecursive(entry.path);
50
+ }
51
+
52
+ console.log();
53
+ return { removed: removed.length, orphans: orphans.length };
54
+ }
55
+
56
+ function scanRemovedBundledSkills(projectRoot) {
57
+ const matches = [];
58
+ const agentsSkillsDir = path.join(projectRoot, '.agents', 'skills');
59
+
60
+ if (!fs.existsSync(agentsSkillsDir)) return matches;
61
+
62
+ for (const entry of removedSkills) {
63
+ const target = path.join(agentsSkillsDir, entry.name);
64
+ if (fs.existsSync(target)) {
65
+ matches.push({ ...entry, path: target });
66
+ }
67
+ }
68
+ return matches;
69
+ }
70
+
71
+ function scanOrphanCommandWrappers(projectRoot) {
72
+ const orphans = [];
73
+
74
+ // Build the canonical "known names" set:
75
+ // - Commands from constants.js (en + pt-br union) — these become wrappers.
76
+ // - Bundled skills from scaffold/skills/ — these are copied verbatim into
77
+ // .agents/skills/ and .claude/skills/ alongside wrappers. They're NOT
78
+ // orphans even though they share the .agents/skills/ directory with
79
+ // command wrappers.
80
+ const canonical = new Set();
81
+ for (const lang of Object.keys(COMMANDS)) {
82
+ for (const cmd of COMMANDS[lang]) {
83
+ canonical.add(cmd.name);
84
+ }
85
+ }
86
+ const scaffoldSkillsDir = path.join(__dirname, '..', 'scaffold', 'skills');
87
+ if (fs.existsSync(scaffoldSkillsDir)) {
88
+ for (const entry of fs.readdirSync(scaffoldSkillsDir, { withFileTypes: true })) {
89
+ if (entry.isDirectory()) canonical.add(entry.name);
90
+ }
91
+ }
92
+
93
+ // Scan locations
94
+ const locations = [
95
+ { dir: path.join(projectRoot, '.claude', 'skills'), type: 'directory' },
96
+ { dir: path.join(projectRoot, '.agents', 'skills'), type: 'directory' },
97
+ { dir: path.join(projectRoot, '.opencode', 'commands'), type: 'file', suffix: '.md' },
98
+ ];
99
+
100
+ for (const loc of locations) {
101
+ if (!fs.existsSync(loc.dir)) continue;
102
+ const entries = fs.readdirSync(loc.dir, { withFileTypes: true });
103
+
104
+ for (const entry of entries) {
105
+ const name = loc.suffix ? entry.name.replace(loc.suffix, '') : entry.name;
106
+
107
+ // Only scan dw-* prefix
108
+ if (!name.startsWith('dw-')) continue;
109
+
110
+ // Skip if it matches a canonical command OR a bundled skill
111
+ if (canonical.has(name)) continue;
112
+
113
+ // Match the expected entry type (directory or file)
114
+ const isExpected = loc.type === 'directory' ? entry.isDirectory() : entry.isFile();
115
+ if (!isExpected) continue;
116
+
117
+ orphans.push({ path: path.join(loc.dir, entry.name) });
118
+ }
119
+ }
120
+
121
+ return orphans;
122
+ }
123
+
124
+ function rmRecursive(target) {
125
+ if (!fs.existsSync(target)) return;
126
+ fs.rmSync(target, { recursive: true, force: true });
127
+ }
128
+
129
+ module.exports = { migrate };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Manifest of bundled skills removed in past releases.
3
+ *
4
+ * APPEND-ONLY: never modify or remove entries. A removed skill stays in
5
+ * this manifest forever so old installs still get cleaned up when the
6
+ * user runs `dev-workflow update`.
7
+ *
8
+ * Each entry triggers `.agents/skills/<name>/` removal during update
9
+ * (see lib/migrate-skills.js).
10
+ */
11
+ module.exports = [
12
+ // v0.13.0 — replaced TASTE catalog (161 palettes) with discipline (hard-gate + anti-slop + WCAG floor)
13
+ { name: 'ui-ux-pro-max', removedIn: '0.13.0', replacedBy: 'dw-ui-discipline' },
14
+ // v0.13.0 — replaced Playwright recipes wrapper with full testing doctrine (Iron Laws + 25 anti-patterns + 7 AI gates)
15
+ { name: 'webapp-testing', removedIn: '0.13.0', replacedBy: 'dw-testing-discipline' },
16
+ ];
package/lib/uninstall.js CHANGED
@@ -56,13 +56,17 @@ function run() {
56
56
 
57
57
  // 3. Remove bundled skills from .agents/skills/
58
58
  console.log(' Bundled skills:');
59
+ // Currently-active bundled skills. If a skill is removed in a future release,
60
+ // add it to lib/removed-bundled-skills.js (append-only manifest used by
61
+ // migrate-skills.js during `dev-workflow update`); this list is just for
62
+ // wholesale uninstall.
59
63
  const bundledSkills = [
64
+ 'dw-ui-discipline',
65
+ 'dw-testing-discipline',
60
66
  'humanizer',
61
67
  'remotion-best-practices',
62
68
  'security-review',
63
- 'ui-ux-pro-max',
64
69
  'vercel-react-best-practices',
65
- 'webapp-testing',
66
70
  ];
67
71
  for (const skill of bundledSkills) {
68
72
  removeDir(path.join(projectRoot, '.agents', 'skills', skill));
package/lib/utils.js CHANGED
@@ -29,7 +29,7 @@ function writeFile(filePath, content, force = false) {
29
29
  return exists ? 'overwritten' : 'created';
30
30
  }
31
31
 
32
- function copyDir(srcDir, destDir, force = false) {
32
+ function copyDir(srcDir, destDir, force = false, overridesDir = null) {
33
33
  const results = { created: 0, skipped: 0, overwritten: 0 };
34
34
 
35
35
  if (!fs.existsSync(srcDir)) {
@@ -40,14 +40,19 @@ function copyDir(srcDir, destDir, force = false) {
40
40
  for (const entry of entries) {
41
41
  const srcPath = path.join(srcDir, entry.name);
42
42
  const destPath = path.join(destDir, entry.name);
43
+ const overridePath = overridesDir ? path.join(overridesDir, entry.name) : null;
43
44
 
44
45
  if (entry.isDirectory()) {
45
- const sub = copyDir(srcPath, destPath, force);
46
+ const subOverrides = overridePath && fs.existsSync(overridePath) ? overridePath : null;
47
+ const sub = copyDir(srcPath, destPath, force, subOverrides);
46
48
  results.created += sub.created;
47
49
  results.skipped += sub.skipped;
48
50
  results.overwritten += sub.overwritten;
49
51
  } else {
50
- const status = copyFile(srcPath, destPath, force);
52
+ // Override wins: copy from override path so dest reflects user customization.
53
+ // Always force-copy overrides so a manual edit to overrides/X.md propagates to templates/X.md on next update.
54
+ const effectiveSrc = overridePath && fs.existsSync(overridePath) ? overridePath : srcPath;
55
+ const status = copyFile(effectiveSrc, destPath, effectiveSrc === overridePath ? true : force);
51
56
  results[status]++;
52
57
  }
53
58
  }
@@ -55,6 +60,48 @@ function copyDir(srcDir, destDir, force = false) {
55
60
  return results;
56
61
  }
57
62
 
63
+ /**
64
+ * Upsert a delimited block inside an existing file.
65
+ *
66
+ * - If the file does not exist, creates it with the new block content.
67
+ * - If the file exists with markers, replaces only the content between markers.
68
+ * - If the file exists WITHOUT markers, appends the block (preserves existing content).
69
+ *
70
+ * Returns 'created' | 'updated' | 'unchanged'.
71
+ */
72
+ function upsertDelimitedBlock(filePath, blockContent, startMarker, endMarker) {
73
+ const exists = fileExists(filePath);
74
+ ensureDir(path.dirname(filePath));
75
+
76
+ // The block content already includes its own start/end markers (so the scaffold
77
+ // file can be read verbatim). Validate that.
78
+ if (!blockContent.includes(startMarker) || !blockContent.includes(endMarker)) {
79
+ throw new Error(`Block content for ${filePath} is missing its markers`);
80
+ }
81
+
82
+ if (!exists) {
83
+ fs.writeFileSync(filePath, blockContent.endsWith('\n') ? blockContent : blockContent + '\n', 'utf-8');
84
+ return 'created';
85
+ }
86
+
87
+ const current = fs.readFileSync(filePath, 'utf-8');
88
+ const hasMarkers = current.includes(startMarker) && current.includes(endMarker);
89
+
90
+ if (!hasMarkers) {
91
+ const separator = current.endsWith('\n') ? '\n' : '\n\n';
92
+ const next = current + separator + (blockContent.endsWith('\n') ? blockContent : blockContent + '\n');
93
+ fs.writeFileSync(filePath, next, 'utf-8');
94
+ return 'updated';
95
+ }
96
+
97
+ const before = current.slice(0, current.indexOf(startMarker));
98
+ const after = current.slice(current.indexOf(endMarker) + endMarker.length);
99
+ const next = before + blockContent.trim() + after;
100
+ if (next === current) return 'unchanged';
101
+ fs.writeFileSync(filePath, next, 'utf-8');
102
+ return 'updated';
103
+ }
104
+
58
105
  function log(status, filePath) {
59
106
  const icons = {
60
107
  created: '\x1b[32m+\x1b[0m',
@@ -66,4 +113,4 @@ function log(status, filePath) {
66
113
  console.log(` ${icon} ${relative} [${status}]`);
67
114
  }
68
115
 
69
- module.exports = { ensureDir, fileExists, copyFile, writeFile, copyDir, log };
116
+ module.exports = { ensureDir, fileExists, copyFile, writeFile, copyDir, upsertDelimitedBlock, log };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brunosps00/dev-workflow",
3
- "version": "0.10.0",
3
+ "version": "0.13.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"