@brunosps00/dev-workflow 1.0.4 → 1.0.5

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 (66) hide show
  1. package/README.md +58 -14
  2. package/bin/dev-workflow.js +29 -3
  3. package/lib/agents.js +410 -0
  4. package/lib/constants.js +12 -0
  5. package/lib/doctor.js +213 -0
  6. package/lib/init.js +96 -8
  7. package/lib/install-state.js +57 -0
  8. package/lib/list-installed.js +27 -0
  9. package/lib/migrate-skills.js +26 -2
  10. package/lib/profiles.js +44 -0
  11. package/lib/skill-registry.js +109 -0
  12. package/lib/subtasks.js +264 -0
  13. package/lib/uninstall.js +21 -12
  14. package/lib/utils.js +42 -1
  15. package/lib/wrappers.js +2 -1
  16. package/package.json +1 -1
  17. package/scaffold/agent-registry.json +272 -0
  18. package/scaffold/agents/core/dw-build-fixer.md +21 -0
  19. package/scaffold/agents/core/dw-code-explorer.md +32 -0
  20. package/scaffold/agents/core/dw-code-reviewer.md +28 -0
  21. package/scaffold/agents/core/dw-planner.md +23 -0
  22. package/scaffold/agents/core/dw-test-author.md +21 -0
  23. package/scaffold/agents/csharp/dw-csharp-reviewer.md +15 -0
  24. package/scaffold/agents/csharp/dw-dotnet-build-fixer.md +15 -0
  25. package/scaffold/agents/frontend/dw-qa-runner.md +21 -0
  26. package/scaffold/agents/python/dw-python-build-fixer.md +15 -0
  27. package/scaffold/agents/python/dw-python-reviewer.md +15 -0
  28. package/scaffold/agents/rust/dw-rust-build-fixer.md +15 -0
  29. package/scaffold/agents/rust/dw-rust-reviewer.md +15 -0
  30. package/scaffold/agents/security/dw-security-reviewer.md +24 -0
  31. package/scaffold/agents/security/dw-silent-failure-hunter.md +22 -0
  32. package/scaffold/agents/typescript/dw-typescript-build-fixer.md +15 -0
  33. package/scaffold/agents/typescript/dw-typescript-reviewer.md +15 -0
  34. package/scaffold/en/agent-instructions.md +44 -1
  35. package/scaffold/en/commands/dw-bugfix.md +9 -0
  36. package/scaffold/en/commands/dw-context-budget.md +28 -0
  37. package/scaffold/en/commands/dw-harness-audit.md +31 -0
  38. package/scaffold/en/commands/dw-help.md +15 -5
  39. package/scaffold/en/commands/dw-intel.md +6 -0
  40. package/scaffold/en/commands/dw-plan.md +11 -0
  41. package/scaffold/en/commands/dw-review.md +12 -0
  42. package/scaffold/en/commands/dw-skill-health.md +29 -0
  43. package/scaffold/en/commands/dw-subtask-complete.md +40 -0
  44. package/scaffold/en/commands/dw-subtask-resume.md +21 -0
  45. package/scaffold/en/commands/dw-subtask-start.md +22 -0
  46. package/scaffold/pt-br/agent-instructions.md +44 -1
  47. package/scaffold/pt-br/commands/dw-bugfix.md +9 -0
  48. package/scaffold/pt-br/commands/dw-context-budget.md +28 -0
  49. package/scaffold/pt-br/commands/dw-harness-audit.md +31 -0
  50. package/scaffold/pt-br/commands/dw-help.md +15 -5
  51. package/scaffold/pt-br/commands/dw-intel.md +6 -0
  52. package/scaffold/pt-br/commands/dw-plan.md +11 -0
  53. package/scaffold/pt-br/commands/dw-review.md +12 -0
  54. package/scaffold/pt-br/commands/dw-skill-health.md +29 -0
  55. package/scaffold/pt-br/commands/dw-subtask-complete.md +40 -0
  56. package/scaffold/pt-br/commands/dw-subtask-resume.md +21 -0
  57. package/scaffold/pt-br/commands/dw-subtask-start.md +22 -0
  58. package/scaffold/skill-registry.json +258 -0
  59. package/scaffold/skills/dw-codebase-intel/SKILL.md +12 -5
  60. package/scaffold/skills/dw-context-budget/SKILL.md +45 -0
  61. package/scaffold/skills/dw-search-first/SKILL.md +31 -0
  62. package/scaffold/skills/dw-silent-failure/SKILL.md +33 -0
  63. package/scaffold/skills/dw-verify/SKILL.md +2 -29
  64. package/scaffold/skills/dw-verify/references/verification-discovery-and-attribution.md +32 -0
  65. package/scaffold/skills/humanizer/SKILL.md +7 -412
  66. package/scaffold/skills/humanizer/references/ai-writing-patterns.md +418 -0
package/README.md CHANGED
@@ -10,11 +10,11 @@ npx @brunosps00/dev-workflow init
10
10
 
11
11
  This will:
12
12
  1. Ask you to select a language (English or Portuguese)
13
- 2. Create `.dw/commands/` with 20 workflow commands
13
+ 2. Create `.dw/commands/` with 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
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
- 6. Generate skill wrappers for Claude Code, Codex, Copilot, and OpenCode
17
+ 6. Generate skill wrappers and project agents for Claude Code, Codex, Copilot, and OpenCode
18
18
  7. Configure MCP servers (Context7 + Playwright)
19
19
 
20
20
  > **Compozy-inspired disciplines.** Since 0.5.0, dev-workflow bundles three primitives — `dw-verify`, `dw-memory`, `dw-review-rigor` — adapted from the [Compozy](https://github.com/compozy/compozy) project and invoked internally by existing commands. See [docs/compozy-integration.md](docs/compozy-integration.md) for what was ported and what was not.
@@ -26,7 +26,7 @@ npx @brunosps00/dev-workflow install-deps
26
26
 
27
27
  ## Commands
28
28
 
29
- dev-workflow v1.0.4 ships **24 commands** organized into four tiers. Most users only invoke Tier 1 + Tier 2.
29
+ dev-workflow v1.0.5 ships **30 commands** organized into four tiers. Most users only invoke Tier 1 + Tier 2.
30
30
 
31
31
  ### Tier 1 — Gateway (3)
32
32
 
@@ -52,19 +52,22 @@ Use these when you want step-by-step control instead of `/dw-autopilot`.
52
52
  | **`/dw-commit`** | Atomic Conventional Commits for pending changes. Applies `dw-git-discipline` (one intent per commit, lint+tests+build green before). |
53
53
  | **`/dw-generate-pr [target]`** | Push the branch, draft a PR body with summary + test plan, open the browser. Hard gates: dw-verify PASS + secure-audit. |
54
54
 
55
- ### Tier 3 — Specialty (5)
55
+ ### Tier 3 — Specialty (8)
56
56
 
57
57
  | Command | What |
58
58
  |---------|------|
59
59
  | **`/dw-analyze-project`** | Scans the repo, writes `.dw/rules/` (per-module conventions, anti-patterns, naming). Step 8 offers to generate `.dw/constitution.md` (declarative principles the team commits to). Step 9 generates `.dw/rules/concerns.md` (risk map: hot spots, fragile integrations, hostile code, bug history). Run once per project; refresh after major refactors. |
60
60
  | **`/dw-redesign-ui "target"`** | Audits a frontend page, runs the `dw-ui-discipline` 4-question grounding, proposes 2-3 design directions, ships the redesign. WCAG 2.2 AA accessibility floor is non-negotiable. |
61
61
  | **`/dw-functional-doc`** | Maps screens + user flows into a functional doc, validated end-to-end with Playwright. |
62
+ | **`/dw-context-budget`** | Audits context overhead from commands, skills, agents, instruction files, and MCPs. |
63
+ | **`/dw-harness-audit`** | Deterministic health scorecard for the dev-workflow install, agents, wrappers, MCPs, and gates. |
64
+ | **`/dw-skill-health`** | Audits installed skills and agents for bloat, duplication, and missing references. |
62
65
  | **`/dw-new-project`** | Bootstrap a new project from empty directory. Stack interview, wraps official `create-*` tools, composes docker-compose for dev, seeds `.env`, scripts, CI, `.dw/rules/`. |
63
66
  | **`/dw-dockerize`** | Reads existing project, detects stack + runtime deps, proposes Dockerfile + docker-compose for dev/prod with explicit trade-offs (Conservative/Balanced/Bold). |
64
67
  | **`/dw-install-azure-skills`** | **Opt-in.** Clones curated Azure skills from [`MicrosoftDocs/Agent-Skills`](https://github.com/MicrosoftDocs/Agent-Skills) (CC-BY-4.0) into `.agents/skills/azure/` and registers the [Microsoft Learn MCP Server](https://learn.microsoft.com/en-us/training/support/mcp-get-started) (HTTP, no-auth). Interactive category selection (Compute / Data & Storage / AI & ML / Networking / Identity & Security / DevOps / Observability / Integration / Architecture / All). Re-run to refresh from upstream. Also available as CLI: `npx @brunosps00/dev-workflow install-azure-skills`. |
65
68
  | **`/dw-install-aws-skills`** | **Opt-in.** Clones curated AWS skills from [`aws/agent-toolkit-for-aws`](https://github.com/aws/agent-toolkit-for-aws) (Apache 2.0) into `.agents/skills/aws/` and registers the unified [AWS MCP Server](https://docs.aws.amazon.com/aws-mcp/) (stdio via `uvx mcp-proxy-for-aws@latest`). **Requires `uv`, `aws cli ≥ 2.32.0`, and AWS credentials.** Interactive category selection (Core / Analytics / Database / EC2 / Migration / Networking / Operations / Security / Serverless / Storage / All). The agent gains `aws___call_aws` (executes 15,000+ AWS APIs) and `aws___run_script` (Python sandboxed) — review `.dw/references/aws-mcp-instructions.md` for the destructive-operations protocol. Also available as CLI: `npx @brunosps00/dev-workflow install-aws-skills [--region=<aws-region>]`. |
66
69
 
67
- ### Tier 4 — Hidden/Internal (5)
70
+ ### Tier 4 — Hidden/Internal (8)
68
71
 
69
72
  These are auto-invoked by Tier 1-3 commands. Available standalone via `/dw-help --advanced`.
70
73
 
@@ -75,6 +78,9 @@ These are auto-invoked by Tier 1-3 commands. Available standalone via `/dw-help
75
78
  | **`/dw-secure-audit`** | Unified security: OWASP + Trivy SCA/secret/IaC + lockfile + supply-chain check. Hard gate. Flags: `--scan-only`, `--plan`, `--execute`. | `/dw-review`, `/dw-generate-pr` (for TS/Python/C#/Rust) |
76
79
  | **`/dw-find-skills "query"`** | Searches `npx skills` ecosystem, vets, installs. | manual when extending the bundle |
77
80
  | **`/dw-update`** | Updates dev-workflow to latest npm release with rollback snapshot. | manual maintenance |
81
+ | **`/dw-subtask-start`** | Creates a minimal input packet for a subagent without injecting the parent transcript. | parent agent before delegation |
82
+ | **`/dw-subtask-complete`** | Records a structured child-session handoff. | subagent / child session |
83
+ | **`/dw-subtask-resume`** | Consumes and archives pending handoffs for parent synthesis. | parent agent after delegation |
78
84
 
79
85
  ## Workflow
80
86
 
@@ -157,7 +163,7 @@ npx @brunosps00/dev-workflow update
157
163
  |----------|-----------------|--------|
158
164
  | Claude Code | `.claude/skills/` | Full support |
159
165
  | Codex CLI | `.agents/skills/` | Full support |
160
- | Copilot | `.agents/skills/` | Full support |
166
+ | Copilot | `.agents/skills/` + `.github/agents/` | Full support |
161
167
  | OpenCode | `.opencode/commands/` | Full support |
162
168
 
163
169
  All wrappers point to `.dw/commands/` as the single source of truth.
@@ -167,29 +173,67 @@ All wrappers point to `.dw/commands/` as the single source of truth.
167
173
  ```
168
174
  your-project/
169
175
  ├── .dw/
170
- │ ├── commands/ # 22 workflow command files (v1.0.2)
176
+ │ ├── commands/ # workflow command files
171
177
  │ ├── templates/ # Document templates (PRD, TechSpec, state, concerns, bugfix-summary, etc.)
172
178
  │ │ └── overrides/ # Project-local template customizations (override > core)
173
179
  │ ├── rules/ # Project-specific rules (run /dw-analyze-project)
174
180
  │ │ └── concerns.md # Risk map: hot spots, fragile integrations, bug history (Step 9 of /dw-analyze-project)
175
181
  │ ├── constitution.md # Declarative principles (auto-installed when missing)
182
+ │ ├── skill-registry.json # Local skill taxonomy, triggers, owners, load policy, and context limits
176
183
  │ ├── references/ # Reference documentation
177
184
  │ ├── scripts/ # Utility scripts
178
185
  │ ├── spec/ # PRD directories — each contains tasks-validation.md
179
186
  │ ├── bugfixes/ # Persistent bugfix records: NNN-<slug>/{TASK.md, SUMMARY.md, fix-report.md} + review/, QA/
187
+ │ ├── subtasks/ # Local ephemeral subagent input packets and handoffs (pending/archive ignored by Git)
180
188
  │ └── STATE.md # Session state: Decisions, Blockers, Todos, Open Loops, Deferred Ideas, Lessons, Preferences (managed by /dw-pause + /dw-resume)
181
189
  ├── CLAUDE.md # Auto-trigger decision tree for Claude Code (merge-aware, includes Auto-Sizing Matrix)
182
190
  ├── AGENTS.md # Same content for Codex / Copilot / OpenCode
183
191
  ├── .claude/
184
192
  │ ├── skills/ # Claude Code wrappers
193
+ │ ├── agents/ # Claude Code project agents
185
194
  │ └── settings.json # MCP servers (Context7, Playwright)
186
195
  ├── .agents/skills/ # Codex/Copilot wrappers + bundled skills
187
- └── .opencode/commands/ # OpenCode wrappers
196
+ ├── .agents/agents/ # Codex/Copilot fallback agent definitions
197
+ ├── .github/agents/ # GitHub Copilot custom agents
198
+ ├── .opencode/commands/ # OpenCode wrappers
199
+ └── .opencode/agent/ # OpenCode project agents
200
+ ```
201
+
202
+ ## Agents
203
+
204
+ `dev-workflow` installs a compact agent layer in addition to skills. Skills remain protocols and reference material; agents are dispatchable roles such as `dw-code-explorer`, `dw-build-fixer`, `dw-code-reviewer`, and language-specific reviewers.
205
+
206
+ Profiles control agent breadth:
207
+
208
+ ```bash
209
+ npx @brunosps00/dev-workflow init --profile=core
210
+ npx @brunosps00/dev-workflow init --profile=standard
211
+ npx @brunosps00/dev-workflow init --profile=full
212
+ npx @brunosps00/dev-workflow init --modules=typescript,python
213
+ ```
214
+
215
+ Claude Code and OpenCode receive native project-agent files. Copilot receives `.github/agents/*.agent.md`. Codex receives fallback agent definitions and dispatch instructions through `AGENTS.md`.
216
+
217
+ Subagent handoffs use local packets under `.dw/subtasks/`:
218
+
219
+ ```bash
220
+ npx @brunosps00/dev-workflow subtask create --agent=dw-code-explorer --goal="Map the auth flow"
221
+ npx @brunosps00/dev-workflow subtask complete --slug=<slug> --file=<handoff.md>
222
+ npx @brunosps00/dev-workflow subtask consume
188
223
  ```
189
224
 
190
225
  ## Bundled Skills
191
226
 
192
- Skills installed to `.agents/skills/` for use by all commands.
227
+ Skills installed to `.agents/skills/` for use by all commands. The bundle is governed by `scaffold/skill-registry.json`, which records each skill's kind, tier, owner, trigger, expected output, load policy, and context limit.
228
+
229
+ Skill kinds:
230
+
231
+ - `protocol`: execution discipline or gate used by commands.
232
+ - `domain-pack`: deeper expertise for a domain such as security, UI, testing, React, Remotion, incident response, or LLM evals.
233
+ - `recipe-pack`: tactical recipes for a narrow implementation surface.
234
+ - `asset-pack`: reusable non-code material, prompts, templates, or editorial references.
235
+
236
+ The rule is deliberate: `SKILL.md` should be a compact entrypoint. Large examples, rules, assets, and checklists live under `references/`, `assets/`, `scripts/`, or `rules/` and are loaded only when the trigger actually needs them. `dev-workflow doctor` validates the registry, installed bundled skills, and context-size limits; `/dw-skill-health` is the agent-facing audit for overlap, bloat, and weak triggers.
193
237
 
194
238
  ### Workflow discipline (invoked internally by dw-* commands)
195
239
 
@@ -273,7 +317,7 @@ Incident response (`dw-incident-response`) adapted from [`wilsto/claude-code-sta
273
317
 
274
318
  LLM evaluation (`dw-llm-eval`) trajectory-match modes (strict / unordered / subset / superset) and tool-argument matching strategies adapted from [`langchain-ai/agentevals`](https://github.com/langchain-ai/agentevals) (MIT). The broader oracle-ladder framing, judge-calibration discipline, and reference-dataset principle are distilled from the open evaluations literature (OpenAI evals cookbook, Anthropic evals guidance, the academic eval-of-LLM body of work) and rewritten in our voice.
275
319
 
276
- Optional AWS integration (v1.0.4). The `/dw-install-aws-skills` command and `npx @brunosps00/dev-workflow install-aws-skills` CLI pull curated agent skills from [`aws/agent-toolkit-for-aws`](https://github.com/aws/agent-toolkit-for-aws) (Apache 2.0, by AWS) into `.agents/skills/aws/` and register the unified [AWS MCP Server](https://docs.aws.amazon.com/aws-mcp/) via [`mcp-proxy-for-aws`](https://github.com/aws/mcp-proxy-for-aws) (stdio transport with SigV4 authentication). Unlike the Azure equivalent, the AWS MCP Server requires `uv`, `aws cli ≥ 2.32.0`, and valid AWS credentials configured via `aws login` or an IAM profile — the command detects each prerequisite and prints OS-specific install instructions if missing (without auto-installing anything). Capability includes `aws___search_documentation`, `aws___read_documentation`, `aws___retrieve_skill`, plus `aws___call_aws` (executes any of 15,000+ AWS APIs with the user's IAM permissions) and `aws___run_script` (Python sandboxed). `.dw/references/aws-mcp-instructions.md` encodes the destructive-operations protocol — agents must confirm before any `create*`/`update*`/`delete*`/`modify*` call, IAM change, or billing-affecting operation. The AWS Knowledge MCP (HTTP, no-auth) was considered for symmetry with Microsoft Learn MCP but is officially deprecated by AWS in favor of the unified server, which AWS explicitly recommends against running alongside the legacy endpoint ("tool conflicts that confuse AI agents"). Default endpoint is `us-east-1` with `eu-central-1` available; region overridable via `--region=<aws-region>` or by editing `.claude/settings.json` directly. Not installed by default; user explicitly invokes the command. Re-run refreshes from upstream; `dev-workflow update` deliberately does not touch `.agents/skills/aws/`.
320
+ Optional AWS integration (v1.0.5). The `/dw-install-aws-skills` command and `npx @brunosps00/dev-workflow install-aws-skills` CLI pull curated agent skills from [`aws/agent-toolkit-for-aws`](https://github.com/aws/agent-toolkit-for-aws) (Apache 2.0, by AWS) into `.agents/skills/aws/` and register the unified [AWS MCP Server](https://docs.aws.amazon.com/aws-mcp/) via [`mcp-proxy-for-aws`](https://github.com/aws/mcp-proxy-for-aws) (stdio transport with SigV4 authentication). Unlike the Azure equivalent, the AWS MCP Server requires `uv`, `aws cli ≥ 2.32.0`, and valid AWS credentials configured via `aws login` or an IAM profile — the command detects each prerequisite and prints OS-specific install instructions if missing (without auto-installing anything). Capability includes `aws___search_documentation`, `aws___read_documentation`, `aws___retrieve_skill`, plus `aws___call_aws` (executes any of 15,000+ AWS APIs with the user's IAM permissions) and `aws___run_script` (Python sandboxed). `.dw/references/aws-mcp-instructions.md` encodes the destructive-operations protocol — agents must confirm before any `create*`/`update*`/`delete*`/`modify*` call, IAM change, or billing-affecting operation. The AWS Knowledge MCP (HTTP, no-auth) was considered for symmetry with Microsoft Learn MCP but is officially deprecated by AWS in favor of the unified server, which AWS explicitly recommends against running alongside the legacy endpoint ("tool conflicts that confuse AI agents"). Default endpoint is `us-east-1` with `eu-central-1` available; region overridable via `--region=<aws-region>` or by editing `.claude/settings.json` directly. Not installed by default; user explicitly invokes the command. Re-run refreshes from upstream; `dev-workflow update` deliberately does not touch `.agents/skills/aws/`.
277
321
 
278
322
  Optional Azure integration (v1.0.3). The `/dw-install-azure-skills` command and `npx @brunosps00/dev-workflow install-azure-skills` CLI pull curated agent skills from [`MicrosoftDocs/Agent-Skills`](https://github.com/MicrosoftDocs/Agent-Skills) (CC-BY-4.0, by Microsoft) into `.agents/skills/azure/` and register the [Microsoft Learn MCP Server](https://learn.microsoft.com/en-us/training/support/mcp-get-started) (HTTP endpoint, no authentication required) into `.claude/settings.json`. The MCP server exposes three tools — `microsoft_docs_search`, `microsoft_docs_fetch`, `microsoft_code_sample_search` — that give the agent live access to Microsoft Learn documentation. **Not installed by default**: `init` and `update` do not touch `.agents/skills/azure/` or register the MCP. Users explicitly invoke the command when they begin Azure-focused work. The 10 categories (Compute, Data & Storage, AI & ML, Networking, Identity & Security, DevOps, Observability, Integration, Architecture, All) are dev-workflow's curated grouping over the 200+ skills in the upstream repo; the `--products=<csv>` flag lets advanced users pick individual services. Re-running the command refreshes from upstream; `dev-workflow update` deliberately does not touch these external skills so the Microsoft upstream release cadence is decoupled from the dev-workflow npm release cadence. Skills are copied verbatim from the upstream repo (CC-BY-4.0 permits this with attribution); the agent-facing `.dw/references/azure-mcp-instructions.md` is a clean-room adaptation of Microsoft's "Set instructions" guidance.
279
323
 
@@ -283,7 +327,7 @@ Four patterns from [`mattpocock/skills`](https://github.com/mattpocock/skills) b
283
327
 
284
328
  ## Migration from v0.x (1.0.0 is a consolidation release)
285
329
 
286
- v1.0.0 consolidates 30 commands → 20. **The `dev-workflow update` command auto-removes obsolete wrappers** via the migrator that landed in v0.13.0; no manual action required.
330
+ v1.0.0 consolidated the legacy command surface into the current `dw-*` pipeline. **The `dev-workflow init`, `update`, and `repair` flows auto-remove obsolete wrappers and known removed command sources**; no manual action required.
287
331
 
288
332
  ### Command renames (15 → 7 merged)
289
333
 
@@ -319,8 +363,8 @@ On the next `npx @brunosps00/dev-workflow update`, the following happens automat
319
363
 
320
364
  1. The 15 renamed commands' wrappers are detected as orphans (their names no longer exist in `lib/constants.js`) and removed from `.claude/skills/`, `.agents/skills/`, and `.opencode/commands/`.
321
365
  2. The migrator prints each removal with the friendly "old → new" mapping (e.g., `[orphan] Removing wrapper .agents/skills/dw-create-prd (replaced in v1.0.0 by 'dw-plan prd')`).
322
- 3. The 20 new wrappers are installed for the consolidated commands.
323
- 4. The 17 bundled skills are refreshed.
366
+ 3. The current command wrappers are installed for the consolidated commands.
367
+ 4. The bundled skills are refreshed.
324
368
 
325
369
  ### Backwards compatibility
326
370
 
@@ -332,7 +376,7 @@ The Trigger Map block (between `<!-- dev-workflow:start -->` and `<!-- dev-workf
332
376
 
333
377
  ### Skill conventions
334
378
 
335
- Skill description format ("pushy" trigger phrases ≤200 chars, "Use when X. Triggers on Y." pattern) and structural conventions (`SKILL.md` + `references/` / `scripts/` / `assets/` / `agents/` subdirectories, explicit `allowed-tools` in frontmatter) follow the official guidance from [`anthropics/skills/skill-creator`](https://github.com/anthropics/skills/tree/main/skills/skill-creator) (Apache 2.0). dev-workflow's 20 bundled skills are not derived from skill-creator's content — only its conventions are followed for auto-trigger reliability across Claude Code, Codex CLI, Copilot, and OpenCode.
379
+ Skill description format ("pushy" trigger phrases ≤200 chars, "Use when X. Triggers on Y." pattern) and structural conventions (`SKILL.md` + `references/` / `scripts/` / `assets/` / `agents/` subdirectories, explicit `allowed-tools` in frontmatter) follow the official guidance from [`anthropics/skills/skill-creator`](https://github.com/anthropics/skills/tree/main/skills/skill-creator) (Apache 2.0). dev-workflow's bundled skills are not derived from skill-creator's content — only its conventions are followed for auto-trigger reliability across Claude Code, Codex CLI, Copilot, and OpenCode.
336
380
 
337
381
  ## License
338
382
 
@@ -22,8 +22,16 @@ const HELP_TEXT = `
22
22
 
23
23
  Usage:
24
24
  npx dev-workflow init [--force] [--lang=en|pt-br]
25
- npx dev-workflow update [--lang=en|pt-br]
25
+ npx dev-workflow init [--force] [--lang=en|pt-br] [--profile=core|standard|full] [--modules=<csv>]
26
+ npx dev-workflow update [--lang=en|pt-br] [--profile=core|standard|full] [--modules=<csv>]
26
27
  npx dev-workflow install-deps
28
+ npx dev-workflow list-installed
29
+ npx dev-workflow doctor
30
+ npx dev-workflow repair
31
+ npx dev-workflow subtask create --agent=<name> --goal="<goal>"
32
+ npx dev-workflow subtask complete --slug=<slug> --file=<handoff.md>
33
+ npx dev-workflow subtask consume
34
+ npx dev-workflow subtask list
27
35
  npx dev-workflow install-azure-skills [--products=<csv>]
28
36
  npx dev-workflow install-aws-skills [--region=<aws-region>]
29
37
  npx dev-workflow help
@@ -32,6 +40,10 @@ const HELP_TEXT = `
32
40
  init Scaffold .dw/ (commands, templates, references, scripts, skills, rules, MCPs)
33
41
  update Update managed files (commands, templates, references, scripts, skills, wrappers, MCPs)
34
42
  Preserves: .dw/rules/, .dw/spec/, .dw/bugfixes/, .dw/STATE.md, .agents/skills/azure/, user data
43
+ list-installed Show dev-workflow install state for this project
44
+ doctor Check managed files, wrappers, agents, and MCP configuration
45
+ repair Reconcile managed files using the recorded install state
46
+ subtask Create, complete, consume, and list local subagent handoffs
35
47
  install-deps Install system dependencies (Playwright browsers, MCP servers)
36
48
  install-azure-skills Opt-in: clone curated Azure skills from MicrosoftDocs/Agent-Skills
37
49
  into .agents/skills/azure/ and register the Microsoft Learn MCP
@@ -47,6 +59,8 @@ const HELP_TEXT = `
47
59
  Options:
48
60
  --force Overwrite existing files (init only; update always overwrites managed files)
49
61
  --lang=LANG Set language without prompt (en or pt-br)
62
+ --profile=NAME Install profile for agents (core, standard, full)
63
+ --modules=CSV Extra agent modules to install (typescript, python, csharp, rust, security, frontend)
50
64
 
51
65
  Examples:
52
66
  npx dev-workflow init # Interactive language selection
@@ -61,10 +75,22 @@ const HELP_TEXT = `
61
75
  async function main() {
62
76
  switch (command) {
63
77
  case 'init':
64
- await run({ force: !!flags.force, lang: flags.lang, mode: 'init' });
78
+ await run({ force: !!flags.force, lang: flags.lang, mode: 'init', profile: flags.profile, modules: flags.modules });
65
79
  break;
66
80
  case 'update':
67
- await run({ force: !!flags.force, lang: flags.lang, mode: 'update' });
81
+ await run({ force: !!flags.force, lang: flags.lang, mode: 'update', profile: flags.profile, modules: flags.modules });
82
+ break;
83
+ case 'list-installed':
84
+ require('../lib/list-installed').run();
85
+ break;
86
+ case 'doctor':
87
+ require('../lib/doctor').run({ repair: false });
88
+ break;
89
+ case 'repair':
90
+ await run({ force: true, lang: flags.lang, mode: 'repair', profile: flags.profile, modules: flags.modules });
91
+ break;
92
+ case 'subtask':
93
+ require('../lib/subtasks').run(args.slice(1));
68
94
  break;
69
95
  case 'install-deps':
70
96
  installDeps.run();
package/lib/agents.js ADDED
@@ -0,0 +1,410 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const { ensureDir, readJson, writeFile, log } = require('./utils');
4
+
5
+ const SCAFFOLD_DIR = path.join(__dirname, '..', 'scaffold');
6
+ const REGISTRY_PATH = path.join(SCAFFOLD_DIR, 'agent-registry.json');
7
+
8
+ const AGENT_TARGETS = {
9
+ claude: {
10
+ dir: '.claude/agents',
11
+ fileName: (name) => `${name}.md`,
12
+ render: renderClaudeAgent,
13
+ },
14
+ opencode: {
15
+ dir: '.opencode/agent',
16
+ fileName: (name) => `${name}.md`,
17
+ render: renderOpenCodeAgent,
18
+ },
19
+ agents: {
20
+ dir: '.agents/agents',
21
+ fileName: (name) => `${name}.md`,
22
+ render: renderFallbackAgent,
23
+ },
24
+ copilot: {
25
+ dir: '.github/agents',
26
+ fileName: (name) => `${name}.agent.md`,
27
+ render: renderCopilotAgent,
28
+ },
29
+ };
30
+
31
+ const LEGACY_AGENT_TARGETS = {
32
+ copilot: {
33
+ dir: '.github/copilot/agents',
34
+ fileName: (name) => `${name}.agent.md`,
35
+ },
36
+ };
37
+
38
+ const REQUIRED_AGENT_FIELDS = [
39
+ 'name',
40
+ 'module',
41
+ 'description',
42
+ 'mode',
43
+ 'context_mode',
44
+ 'tool_policy',
45
+ 'max_turns',
46
+ 'input_budget_words',
47
+ 'output_budget_words',
48
+ 'parallel_safe',
49
+ 'handoff_required',
50
+ 'skill_policy',
51
+ 'recommended_for',
52
+ 'avoid_when',
53
+ ];
54
+
55
+ function readAgentRegistry() {
56
+ const registry = readJson(REGISTRY_PATH, null);
57
+ if (!registry || !Array.isArray(registry.agents)) {
58
+ throw new Error('Invalid scaffold/agent-registry.json');
59
+ }
60
+ return registry;
61
+ }
62
+
63
+ function validateAgentRegistry(registry = readAgentRegistry()) {
64
+ const issues = [];
65
+ const warnings = [];
66
+ if (registry.schema_version !== '2.0') {
67
+ issues.push('Agent registry must use schema_version 2.0.');
68
+ }
69
+
70
+ const names = new Set();
71
+ for (const agent of registry.agents || []) {
72
+ for (const field of REQUIRED_AGENT_FIELDS) {
73
+ if (agent[field] === undefined || agent[field] === null || agent[field] === '') {
74
+ issues.push(`Agent ${agent.name || '<unnamed>'} is missing required field: ${field}`);
75
+ }
76
+ }
77
+ if (names.has(agent.name)) issues.push(`Duplicate agent name: ${agent.name}`);
78
+ names.add(agent.name);
79
+
80
+ if (!Array.isArray(agent.recommended_for)) {
81
+ issues.push(`Agent ${agent.name} recommended_for must be an array.`);
82
+ }
83
+ if (!Array.isArray(agent.avoid_when)) {
84
+ issues.push(`Agent ${agent.name} avoid_when must be an array.`);
85
+ }
86
+ if (agent.mode === 'read-only' && agent.tool_policy !== 'read-only') {
87
+ issues.push(`Read-only agent ${agent.name} must use tool_policy read-only.`);
88
+ }
89
+ if (agent.output_budget_words > 1500) {
90
+ warnings.push(`Agent ${agent.name} output budget is above 1500 words.`);
91
+ }
92
+ }
93
+
94
+ for (const [commandName, agents] of Object.entries(registry.commands || {})) {
95
+ if (!Array.isArray(agents)) {
96
+ issues.push(`Agent registry command ${commandName} must map to an array.`);
97
+ continue;
98
+ }
99
+ for (const agentName of agents) {
100
+ if (!names.has(agentName)) issues.push(`Agent registry references missing agent: ${agentName}`);
101
+ }
102
+ }
103
+
104
+ return { issues, warnings };
105
+ }
106
+
107
+ function selectAgents(modules) {
108
+ const registry = readAgentRegistry();
109
+ const validation = validateAgentRegistry(registry);
110
+ if (validation.issues.length) {
111
+ throw new Error(`Invalid scaffold/agent-registry.json:\n- ${validation.issues.join('\n- ')}`);
112
+ }
113
+ const selectedModules = new Set(modules || []);
114
+ return registry.agents.filter((agent) => selectedModules.has(agent.module));
115
+ }
116
+
117
+ function generateAgents(projectRoot, modules, force = false) {
118
+ const results = { created: 0, skipped: 0, overwritten: 0, files: [] };
119
+ const agents = selectAgents(modules);
120
+
121
+ if (force) removeLegacyAgentTargets(projectRoot, agents);
122
+
123
+ for (const agent of agents) {
124
+ const source = readAgentSource(agent);
125
+ for (const target of Object.values(AGENT_TARGETS)) {
126
+ const dest = path.join(projectRoot, target.dir, target.fileName(agent.name));
127
+ const status = writeFile(dest, target.render(agent, source), force);
128
+ results[status]++;
129
+ results.files.push(dest);
130
+ log(status, dest);
131
+ }
132
+ }
133
+
134
+ writeAgentIndex(projectRoot, agents, force);
135
+ const indexPath = path.join(projectRoot, '.agents', 'agents', 'README.md');
136
+ results.files.push(indexPath);
137
+
138
+ return results;
139
+ }
140
+
141
+ function readAgentSource(agent) {
142
+ const src = path.join(SCAFFOLD_DIR, 'agents', agent.module, `${agent.name}.md`);
143
+ if (!fs.existsSync(src)) {
144
+ throw new Error(`Agent source missing: ${path.relative(process.cwd(), src)}`);
145
+ }
146
+ const raw = fs.readFileSync(src, 'utf-8');
147
+ const parsed = parseMarkdownFrontmatter(raw);
148
+ return {
149
+ path: src,
150
+ metadata: parsed.metadata,
151
+ body: parsed.body.trim(),
152
+ };
153
+ }
154
+
155
+ function parseMarkdownFrontmatter(raw) {
156
+ if (!raw.startsWith('---\n')) return { metadata: {}, body: raw };
157
+ const end = raw.indexOf('\n---', 4);
158
+ if (end === -1) return { metadata: {}, body: raw };
159
+ const metadata = {};
160
+ const frontmatter = raw.slice(4, end).trim();
161
+ for (const line of frontmatter.split('\n')) {
162
+ const match = line.match(/^([A-Za-z0-9_-]+):\s*(.*)$/);
163
+ if (!match) continue;
164
+ metadata[match[1]] = match[2].replace(/^["']|["']$/g, '');
165
+ }
166
+ return {
167
+ metadata,
168
+ body: raw.slice(end + 4).replace(/^\s+/, ''),
169
+ };
170
+ }
171
+
172
+ function renderClaudeAgent(agent, source) {
173
+ const tools = claudeToolsFor(agent, source);
174
+ const lines = [
175
+ '---',
176
+ `name: ${agent.name}`,
177
+ `description: "${yamlString(agent.description)}"`,
178
+ `tools: ${tools.join(', ')}`,
179
+ `model: ${source.metadata.model || 'sonnet'}`,
180
+ `permissionMode: ${agent.tool_policy === 'read-only' ? 'plan' : 'default'}`,
181
+ `maxTurns: ${agent.max_turns}`,
182
+ '---',
183
+ '',
184
+ renderContract(agent, 'Claude Code project subagent'),
185
+ '',
186
+ source.body,
187
+ '',
188
+ ];
189
+ return lines.join('\n');
190
+ }
191
+
192
+ function renderOpenCodeAgent(agent, source) {
193
+ const canWrite = agent.tool_policy !== 'read-only';
194
+ const lines = [
195
+ '---',
196
+ 'mode: subagent',
197
+ `description: "${yamlString(agent.description)}"`,
198
+ `steps: ${agent.max_turns}`,
199
+ 'permission:',
200
+ ` edit: ${canWrite ? 'allow' : 'deny'}`,
201
+ ` write: ${canWrite ? 'allow' : 'deny'}`,
202
+ ` bash: ${agent.tool_policy === 'read-only' ? 'deny' : 'allow'}`,
203
+ '---',
204
+ '',
205
+ renderContract(agent, 'OpenCode project subagent'),
206
+ '',
207
+ source.body,
208
+ '',
209
+ ];
210
+ return lines.join('\n');
211
+ }
212
+
213
+ function renderCopilotAgent(agent, source) {
214
+ const tools = copilotToolsFor(agent);
215
+ const lines = [
216
+ '---',
217
+ `name: ${agent.name}`,
218
+ `description: "${yamlString(agent.description)}"`,
219
+ `tools: ${tools.join(', ')}`,
220
+ '---',
221
+ '',
222
+ renderContract(agent, 'GitHub Copilot custom agent'),
223
+ '',
224
+ source.body,
225
+ '',
226
+ ];
227
+ return lines.join('\n');
228
+ }
229
+
230
+ function renderFallbackAgent(agent, source) {
231
+ const lines = [
232
+ '---',
233
+ `name: ${agent.name}`,
234
+ `description: "${yamlString(agent.description)}"`,
235
+ `mode: ${agent.mode}`,
236
+ `context_mode: ${agent.context_mode}`,
237
+ `tool_policy: ${agent.tool_policy}`,
238
+ `max_turns: ${agent.max_turns}`,
239
+ `input_budget_words: ${agent.input_budget_words}`,
240
+ `output_budget_words: ${agent.output_budget_words}`,
241
+ `parallel_safe: ${agent.parallel_safe}`,
242
+ '---',
243
+ '',
244
+ renderContract(agent, 'Fallback prompt profile'),
245
+ '',
246
+ source.body,
247
+ '',
248
+ ];
249
+ return lines.join('\n');
250
+ }
251
+
252
+ function renderContract(agent, targetLabel) {
253
+ return [
254
+ `# ${agent.name}`,
255
+ '',
256
+ `Provider target: ${targetLabel}.`,
257
+ '',
258
+ '## Dispatch Contract',
259
+ '',
260
+ `- Context mode: \`${agent.context_mode}\`.`,
261
+ `- Tool policy: \`${agent.tool_policy}\`.`,
262
+ `- Max turns: ${agent.max_turns}.`,
263
+ `- Input budget: ${agent.input_budget_words} words.`,
264
+ `- Output budget: ${agent.output_budget_words} words.`,
265
+ `- Parallel safe: ${agent.parallel_safe ? 'yes' : 'no'}.`,
266
+ `- Handoff required: ${agent.handoff_required ? 'yes' : 'no'}.`,
267
+ `- Skill policy: \`${agent.skill_policy}\`; do not preload large skills.`,
268
+ '',
269
+ '## Use When',
270
+ ...agent.recommended_for.map((item) => `- ${item}.`),
271
+ '',
272
+ '## Do Not Use When',
273
+ ...agent.avoid_when.map((item) => `- ${item}.`),
274
+ '',
275
+ '## Input Packet Expected',
276
+ '',
277
+ '- Objective and stop condition.',
278
+ '- Allowed files, folders, commands, and write boundaries.',
279
+ '- Relevant constraints from `.dw/rules/`, `.dw/intel/`, or the parent session.',
280
+ '- Expected return packet shape and verification command, when applicable.',
281
+ '',
282
+ '## Context Rules',
283
+ '',
284
+ '- Do not request or paste the full parent transcript.',
285
+ '- Read only the files needed for the objective.',
286
+ '- Summarize logs; include only failing lines, paths, commands, and decisions.',
287
+ '',
288
+ '## Tool/Write Boundaries',
289
+ '',
290
+ toolBoundary(agent),
291
+ '',
292
+ '## Return Packet',
293
+ '',
294
+ '- Result: pass, findings, changed files, or blocked.',
295
+ '- Files read and files changed.',
296
+ '- Decisions made and risks that remain.',
297
+ '- Verification run, including command and outcome.',
298
+ '- Recommended next step for the parent session.',
299
+ '',
300
+ '## Stop Conditions',
301
+ '',
302
+ '- Stop when the requested packet is complete.',
303
+ '- Stop if required context exceeds the input budget.',
304
+ '- Stop if the task needs broader architecture, product, or permission decisions.',
305
+ ].join('\n');
306
+ }
307
+
308
+ function toolBoundary(agent) {
309
+ if (agent.tool_policy === 'read-only') {
310
+ return '- Read-only. Do not edit, write, delete, or format files.';
311
+ }
312
+ if (agent.tool_policy === 'qa-write') {
313
+ return '- Write only QA artifacts, test scripts, traces, screenshots, and reports unless the parent explicitly assigns a fix.';
314
+ }
315
+ if (agent.tool_policy === 'shell-limited') {
316
+ return '- Shell commands are allowed only for inspection and targeted verification. Do not edit files unless explicitly assigned.';
317
+ }
318
+ return '- Edits are allowed only inside the files or module boundaries named in the input packet.';
319
+ }
320
+
321
+ function claudeToolsFor(agent, source) {
322
+ if (source.metadata.tools) {
323
+ return source.metadata.tools.split(',').map((tool) => tool.trim()).filter(Boolean);
324
+ }
325
+ return agent.tool_policy === 'read-only'
326
+ ? ['Read', 'Grep', 'Glob']
327
+ : ['Read', 'Write', 'Edit', 'Bash', 'Grep', 'Glob'];
328
+ }
329
+
330
+ function copilotToolsFor(agent) {
331
+ return agent.tool_policy === 'read-only'
332
+ ? ['read', 'grep']
333
+ : ['read', 'edit', 'terminal'];
334
+ }
335
+
336
+ function yamlString(value) {
337
+ return String(value).replace(/\\/g, '\\\\').replace(/"/g, '\\"');
338
+ }
339
+
340
+ function writeAgentIndex(projectRoot, agents, force) {
341
+ const lines = [
342
+ '# dev-workflow Agents',
343
+ '',
344
+ 'These files are fallback prompt profiles for harnesses that do not expose native project subagents.',
345
+ 'Claude Code uses `.claude/agents/`; OpenCode uses `.opencode/agent/`; Copilot receives `.github/agents/*.agent.md`.',
346
+ 'Codex should treat this directory as delegable profiles when subagents are available, or as a manual prompt pack otherwise.',
347
+ '',
348
+ '| Agent | Module | Mode | Context | Output Budget | Purpose |',
349
+ '|---|---|---|---|---:|---|',
350
+ ];
351
+
352
+ for (const agent of agents) {
353
+ lines.push(`| \`${agent.name}\` | \`${agent.module}\` | \`${agent.mode}\` | \`${agent.context_mode}\` | ${agent.output_budget_words} words | ${agent.description} |`);
354
+ }
355
+
356
+ const content = lines.join('\n') + '\n';
357
+ writeFile(path.join(projectRoot, '.agents', 'agents', 'README.md'), content, force);
358
+ }
359
+
360
+ function listExpectedAgentFiles(projectRoot, modules) {
361
+ const files = [];
362
+ for (const agent of selectAgents(modules)) {
363
+ for (const target of Object.values(AGENT_TARGETS)) {
364
+ files.push(path.join(projectRoot, target.dir, target.fileName(agent.name)));
365
+ }
366
+ }
367
+ files.push(path.join(projectRoot, '.agents', 'agents', 'README.md'));
368
+ return files;
369
+ }
370
+
371
+ function listLegacyAgentFiles(projectRoot, modules) {
372
+ const files = [];
373
+ for (const agent of selectAgents(modules)) {
374
+ for (const target of Object.values(LEGACY_AGENT_TARGETS)) {
375
+ files.push(path.join(projectRoot, target.dir, target.fileName(agent.name)));
376
+ }
377
+ }
378
+ return files;
379
+ }
380
+
381
+ function ensureAgentDirs(projectRoot) {
382
+ for (const target of Object.values(AGENT_TARGETS)) {
383
+ ensureDir(path.join(projectRoot, target.dir));
384
+ }
385
+ }
386
+
387
+ function removeLegacyAgentTargets(projectRoot, agents) {
388
+ for (const target of Object.values(LEGACY_AGENT_TARGETS)) {
389
+ for (const agent of agents) {
390
+ const file = path.join(projectRoot, target.dir, target.fileName(agent.name));
391
+ if (fs.existsSync(file)) fs.rmSync(file);
392
+ }
393
+ const dir = path.join(projectRoot, target.dir);
394
+ if (fs.existsSync(dir) && fs.readdirSync(dir).length === 0) {
395
+ fs.rmSync(dir, { recursive: true, force: true });
396
+ }
397
+ }
398
+ }
399
+
400
+ module.exports = {
401
+ AGENT_TARGETS,
402
+ LEGACY_AGENT_TARGETS,
403
+ readAgentRegistry,
404
+ validateAgentRegistry,
405
+ selectAgents,
406
+ generateAgents,
407
+ listExpectedAgentFiles,
408
+ listLegacyAgentFiles,
409
+ ensureAgentDirs,
410
+ };