@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.
- package/README.md +78 -6
- package/lib/constants.js +20 -20
- package/lib/init.js +44 -4
- package/lib/migrate-skills.js +129 -0
- package/lib/removed-bundled-skills.js +16 -0
- package/lib/uninstall.js +6 -2
- package/lib/utils.js +51 -4
- package/package.json +1 -1
- package/scaffold/en/agent-instructions.md +68 -0
- package/scaffold/en/commands/dw-analyze-project.md +61 -0
- package/scaffold/en/commands/dw-autopilot.md +1 -1
- package/scaffold/en/commands/dw-brainstorm.md +1 -1
- package/scaffold/en/commands/dw-bugfix.md +3 -3
- package/scaffold/en/commands/dw-code-review.md +28 -0
- package/scaffold/en/commands/dw-create-prd.md +16 -0
- package/scaffold/en/commands/dw-create-tasks.md +42 -0
- package/scaffold/en/commands/dw-create-techspec.md +18 -1
- package/scaffold/en/commands/dw-deps-audit.md +1 -1
- package/scaffold/en/commands/dw-fix-qa.md +1 -1
- package/scaffold/en/commands/dw-functional-doc.md +2 -2
- package/scaffold/en/commands/dw-help.md +1 -1
- package/scaffold/en/commands/dw-redesign-ui.md +7 -7
- package/scaffold/en/commands/dw-run-qa.md +4 -4
- package/scaffold/en/commands/dw-run-task.md +2 -2
- package/scaffold/en/templates/constitution-template.md +111 -0
- package/scaffold/pt-br/agent-instructions.md +68 -0
- package/scaffold/pt-br/commands/dw-analyze-project.md +61 -0
- package/scaffold/pt-br/commands/dw-autopilot.md +1 -1
- package/scaffold/pt-br/commands/dw-brainstorm.md +1 -1
- package/scaffold/pt-br/commands/dw-bugfix.md +3 -3
- package/scaffold/pt-br/commands/dw-code-review.md +28 -0
- package/scaffold/pt-br/commands/dw-create-prd.md +16 -0
- package/scaffold/pt-br/commands/dw-create-tasks.md +42 -0
- package/scaffold/pt-br/commands/dw-create-techspec.md +18 -1
- package/scaffold/pt-br/commands/dw-deps-audit.md +1 -1
- package/scaffold/pt-br/commands/dw-fix-qa.md +1 -1
- package/scaffold/pt-br/commands/dw-functional-doc.md +2 -2
- package/scaffold/pt-br/commands/dw-help.md +1 -1
- package/scaffold/pt-br/commands/dw-redesign-ui.md +7 -7
- package/scaffold/pt-br/commands/dw-run-qa.md +4 -4
- package/scaffold/pt-br/commands/dw-run-task.md +2 -2
- package/scaffold/pt-br/templates/constitution-template.md +111 -0
- package/scaffold/skills/dw-council/SKILL.md +1 -1
- package/scaffold/skills/dw-testing-discipline/SKILL.md +148 -0
- package/scaffold/skills/dw-testing-discipline/references/ai-agent-gates.md +170 -0
- package/scaffold/skills/dw-testing-discipline/references/anti-patterns.md +336 -0
- package/scaffold/skills/dw-testing-discipline/references/flaky-discipline.md +163 -0
- package/scaffold/skills/dw-testing-discipline/references/iron-laws.md +128 -0
- package/scaffold/skills/dw-testing-discipline/references/playwright-recipes.md +282 -0
- package/scaffold/skills/dw-testing-discipline/references/positive-patterns.md +241 -0
- package/scaffold/skills/{webapp-testing → dw-testing-discipline}/references/security-boundary.md +1 -1
- package/scaffold/skills/dw-ui-discipline/SKILL.md +128 -0
- package/scaffold/skills/dw-ui-discipline/references/accessibility-floor.md +225 -0
- package/scaffold/skills/dw-ui-discipline/references/anti-slop.md +162 -0
- package/scaffold/skills/dw-ui-discipline/references/curated-defaults.md +195 -0
- package/scaffold/skills/dw-ui-discipline/references/hard-gate.md +142 -0
- package/scaffold/skills/dw-ui-discipline/references/state-matrix.md +101 -0
- package/scaffold/templates-overrides-readme.md +75 -0
- package/scaffold/skills/ui-ux-pro-max/LICENSE +0 -21
- package/scaffold/skills/ui-ux-pro-max/SKILL.md +0 -659
- package/scaffold/skills/ui-ux-pro-max/data/_sync_all.py +0 -414
- package/scaffold/skills/ui-ux-pro-max/data/app-interface.csv +0 -31
- package/scaffold/skills/ui-ux-pro-max/data/charts.csv +0 -26
- package/scaffold/skills/ui-ux-pro-max/data/colors.csv +0 -162
- package/scaffold/skills/ui-ux-pro-max/data/design.csv +0 -1776
- package/scaffold/skills/ui-ux-pro-max/data/draft.csv +0 -1779
- package/scaffold/skills/ui-ux-pro-max/data/google-fonts.csv +0 -1924
- package/scaffold/skills/ui-ux-pro-max/data/icons.csv +0 -106
- package/scaffold/skills/ui-ux-pro-max/data/landing.csv +0 -35
- package/scaffold/skills/ui-ux-pro-max/data/products.csv +0 -162
- package/scaffold/skills/ui-ux-pro-max/data/react-performance.csv +0 -45
- package/scaffold/skills/ui-ux-pro-max/data/stacks/angular.csv +0 -51
- package/scaffold/skills/ui-ux-pro-max/data/stacks/astro.csv +0 -54
- package/scaffold/skills/ui-ux-pro-max/data/stacks/flutter.csv +0 -53
- package/scaffold/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +0 -56
- package/scaffold/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +0 -53
- package/scaffold/skills/ui-ux-pro-max/data/stacks/laravel.csv +0 -51
- package/scaffold/skills/ui-ux-pro-max/data/stacks/nextjs.csv +0 -53
- package/scaffold/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +0 -51
- package/scaffold/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +0 -59
- package/scaffold/skills/ui-ux-pro-max/data/stacks/react-native.csv +0 -52
- package/scaffold/skills/ui-ux-pro-max/data/stacks/react.csv +0 -54
- package/scaffold/skills/ui-ux-pro-max/data/stacks/shadcn.csv +0 -61
- package/scaffold/skills/ui-ux-pro-max/data/stacks/svelte.csv +0 -54
- package/scaffold/skills/ui-ux-pro-max/data/stacks/swiftui.csv +0 -51
- package/scaffold/skills/ui-ux-pro-max/data/stacks/threejs.csv +0 -54
- package/scaffold/skills/ui-ux-pro-max/data/stacks/vue.csv +0 -50
- package/scaffold/skills/ui-ux-pro-max/data/styles.csv +0 -85
- package/scaffold/skills/ui-ux-pro-max/data/typography.csv +0 -74
- package/scaffold/skills/ui-ux-pro-max/data/ui-reasoning.csv +0 -162
- package/scaffold/skills/ui-ux-pro-max/data/ux-guidelines.csv +0 -100
- package/scaffold/skills/ui-ux-pro-max/scripts/core.py +0 -262
- package/scaffold/skills/ui-ux-pro-max/scripts/design_system.py +0 -1148
- package/scaffold/skills/ui-ux-pro-max/scripts/search.py +0 -114
- package/scaffold/skills/ui-ux-pro-max/skills/brand/SKILL.md +0 -97
- package/scaffold/skills/ui-ux-pro-max/skills/design/SKILL.md +0 -302
- package/scaffold/skills/ui-ux-pro-max/skills/design-system/SKILL.md +0 -244
- package/scaffold/skills/ui-ux-pro-max/templates/base/quick-reference.md +0 -297
- package/scaffold/skills/ui-ux-pro-max/templates/base/skill-content.md +0 -358
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/agent.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/augment.json +0 -18
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/claude.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/codebuddy.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/codex.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/continue.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/copilot.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/cursor.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/droid.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/gemini.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/kilocode.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/kiro.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/opencode.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/qoder.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/roocode.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/trae.json +0 -21
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/warp.json +0 -18
- package/scaffold/skills/ui-ux-pro-max/templates/platforms/windsurf.json +0 -21
- package/scaffold/skills/webapp-testing/SKILL.md +0 -138
- package/scaffold/skills/webapp-testing/assets/test-helper.js +0 -56
- /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-
|
|
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,
|
|
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
|
|
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-
|
|
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`)
|
|
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: '
|
|
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: '
|
|
8
|
-
{ name: 'dw-code-review', description: '
|
|
9
|
-
{ name: 'dw-commit', description: '
|
|
10
|
-
{ name: 'dw-create-prd', description: '
|
|
11
|
-
{ name: 'dw-create-tasks', description: '
|
|
12
|
-
{ name: 'dw-create-techspec', description: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
40
|
-
{ name: 'dw-code-review', description: '
|
|
41
|
-
{ name: 'dw-commit', description: '
|
|
42
|
-
{ name: 'dw-create-prd', description: '
|
|
43
|
-
{ name: 'dw-create-tasks', description: '
|
|
44
|
-
{ name: 'dw-create-techspec', description: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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.
|
|
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"
|