@brunosps00/dev-workflow 1.7.0 → 2.0.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/.claude-plugin/plugin.json +2 -2
- package/CHANGELOG.md +201 -0
- package/README.md +2 -2
- package/lib/agents.js +6 -1
- package/lib/init.js +14 -0
- package/lib/install-deps.js +15 -0
- package/lib/install-open-design.js +39 -0
- package/lib/install-state.js +8 -4
- package/lib/utils.js +46 -6
- package/package.json +3 -2
- package/scaffold/agents/core/dw-build-fixer.md +0 -1
- package/scaffold/agents/core/dw-code-explorer.md +0 -1
- package/scaffold/agents/core/dw-code-reviewer.md +0 -1
- package/scaffold/agents/core/dw-planner.md +0 -1
- package/scaffold/agents/core/dw-test-author.md +0 -1
- package/scaffold/agents/csharp/dw-csharp-reviewer.md +0 -1
- package/scaffold/agents/csharp/dw-dotnet-build-fixer.md +0 -1
- package/scaffold/agents/frontend/dw-qa-runner.md +0 -1
- package/scaffold/agents/python/dw-python-build-fixer.md +0 -1
- package/scaffold/agents/python/dw-python-reviewer.md +0 -1
- package/scaffold/agents/rust/dw-rust-build-fixer.md +0 -1
- package/scaffold/agents/rust/dw-rust-reviewer.md +0 -1
- package/scaffold/agents/security/dw-security-reviewer.md +0 -1
- package/scaffold/agents/security/dw-silent-failure-hunter.md +0 -1
- package/scaffold/agents/typescript/dw-typescript-build-fixer.md +0 -1
- package/scaffold/agents/typescript/dw-typescript-reviewer.md +0 -1
- package/scaffold/config/routing.json +60 -0
- package/scaffold/en/commands/dw-claude-run.md +5 -1
- package/scaffold/en/commands/dw-codex-run.md +5 -1
- package/scaffold/en/commands/dw-dockerize.md +14 -7
- package/scaffold/en/commands/dw-generate-pr.md +13 -0
- package/scaffold/en/commands/dw-new-project.md +34 -30
- package/scaffold/en/commands/dw-run.md +1 -1
- package/scaffold/en/templates/project-onepager.md +16 -14
- package/scaffold/en/templates/task-template.md +1 -1
- package/scaffold/en/templates/tasks-template.md +7 -5
- package/scaffold/pt-br/commands/dw-claude-run.md +5 -1
- package/scaffold/pt-br/commands/dw-codex-run.md +5 -1
- package/scaffold/pt-br/commands/dw-dockerize.md +14 -7
- package/scaffold/pt-br/commands/dw-generate-pr.md +13 -0
- package/scaffold/pt-br/commands/dw-new-project.md +34 -30
- package/scaffold/pt-br/commands/dw-plan.md +1 -1
- package/scaffold/pt-br/commands/dw-run.md +1 -1
- package/scaffold/pt-br/templates/project-onepager.md +16 -14
- package/scaffold/pt-br/templates/task-template.md +1 -1
- package/scaffold/pt-br/templates/tasks-template.md +7 -5
- package/scaffold/skills/docker-compose-recipes/SKILL.md +4 -5
- package/scaffold/skills/docker-compose-recipes/references/compose-composition.md +6 -6
- package/scaffold/skills/docker-compose-recipes/references/env-conventions.md +18 -9
- package/scaffold/skills/docker-compose-recipes/references/healthcheck-patterns.md +4 -5
- package/scaffold/skills/docker-compose-recipes/references/prod-vs-dev.md +7 -2
- package/scaffold/skills/docker-compose-recipes/services/elasticsearch.yml +3 -3
- package/scaffold/skills/docker-compose-recipes/services/mailpit.yml +4 -4
- package/scaffold/skills/docker-compose-recipes/services/meilisearch.yml +2 -2
- package/scaffold/skills/docker-compose-recipes/services/minio.yml +8 -4
- package/scaffold/skills/docker-compose-recipes/services/mysql.yml +4 -4
- package/scaffold/skills/docker-compose-recipes/services/postgres.yml +2 -2
- package/scaffold/skills/docker-compose-recipes/services/rabbitmq.yml +3 -3
- package/scaffold/skills/docker-compose-recipes/services/typesense.yml +3 -3
- package/scaffold/skills/dw-cli-run/SKILL.md +42 -38
- package/scaffold/skills/dw-cli-run/references/dispatch-tuning.md +85 -0
- package/scaffold/skills/dw-execute-phase/SKILL.md +4 -2
- package/scaffold/skills/dw-execute-phase/agents/executor.md +4 -2
- package/scaffold/skills/dw-execute-phase/agents/plan-checker.md +9 -7
- package/scaffold/skills/dw-execute-phase/references/atomic-commits.md +12 -8
- package/scaffold/skills/dw-execute-phase/references/plan-verification.md +6 -4
- package/scaffold/skills/docker-compose-recipes/services/mailhog.yml +0 -23
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dev-workflow",
|
|
3
3
|
"description": "Standalone, à-la-carte skills from the dev-workflow pipeline: minimalism, search-first, simplification, verification, security review, and more.",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "2.0.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Bruno Santos"
|
|
7
7
|
},
|
|
8
|
-
"homepage": "https://github.com/
|
|
8
|
+
"homepage": "https://github.com/brunosps/dev-workflow",
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"keywords": [
|
|
11
11
|
"ai",
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here.
|
|
4
|
+
|
|
5
|
+
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this
|
|
6
|
+
project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
> Entries for 2.0.0 are written from the change set itself. Entries before it were
|
|
9
|
+
> reconstructed from commit history in August 2026 — this file did not exist while
|
|
10
|
+
> those versions were released, so they are summaries of what shipped, not
|
|
11
|
+
> contemporaneous release notes. `git log` remains the authoritative record.
|
|
12
|
+
|
|
13
|
+
## [2.0.0] — 2026-08-02
|
|
14
|
+
|
|
15
|
+
First release after a full security audit of the compose recipes. Two options were
|
|
16
|
+
removed rather than shipped with vulnerabilities the project could not close.
|
|
17
|
+
|
|
18
|
+
Versions 1.8.0, 1.9.0 and 1.10.0 exist as commits but were never published to npm;
|
|
19
|
+
their contents are folded in here. The last published version was 1.7.1.
|
|
20
|
+
|
|
21
|
+
### Removed
|
|
22
|
+
|
|
23
|
+
- **`Postgres + pgvector` is no longer offered by `/dw-new-project`**, and
|
|
24
|
+
`services/postgres-pgvector.yml` is deleted. After repinning to the newest
|
|
25
|
+
available base the image still carried 18 CRITICAL, none of them actionable: 15
|
|
26
|
+
were Go `stdlib` inside a vendored binary (only a maintainer rebuild clears
|
|
27
|
+
those) and the rest have no upstream fix at all (`perl` 5.40, `libxml2`
|
|
28
|
+
`CVE-2026-6653`). Shipping a recipe whose CVEs the project cannot close was not
|
|
29
|
+
a defensible default for an optional capability. **Existing projects are
|
|
30
|
+
unaffected** — `/dw-dockerize` keeps whatever image the project already uses and
|
|
31
|
+
tells the user it needs its own review, rather than substituting one.
|
|
32
|
+
- **MailHog is no longer offered as a dev email-capture option**, and
|
|
33
|
+
`services/mailhog.yml` is deleted. It reported 109 CRITICAL / 1250 HIGH with
|
|
34
|
+
1359 of those carrying a published fix — the profile of an image not rebuilt
|
|
35
|
+
since its upstream went quiet in 2020. Mailpit, already the documented default,
|
|
36
|
+
scans 0 CRITICAL / 0 HIGH for the same job.
|
|
37
|
+
|
|
38
|
+
### Security
|
|
39
|
+
|
|
40
|
+
- **Every credential in every compose recipe now uses `${VAR:?message}`** instead
|
|
41
|
+
of `${VAR:-default}`, so Compose refuses to start rather than falling back to a
|
|
42
|
+
value published in this repository. Applied to `postgres`, `mysql`,
|
|
43
|
+
`elasticsearch`, `meilisearch`, `minio`, `rabbitmq`, and `typesense`.
|
|
44
|
+
- **Every authenticated service publishes on `127.0.0.1` only.** Docker's
|
|
45
|
+
`"HOST:CONTAINER"` short form binds every host interface, which turns a local
|
|
46
|
+
dev credential into a network-reachable one.
|
|
47
|
+
- **`typesense` was pinned to `0.27.1`, a tag that does not exist** — the recipe
|
|
48
|
+
could never have worked (`MANIFEST_UNKNOWN`). Repinned to `30.2`. It also passed
|
|
49
|
+
its API key as a `command:` flag with a working default, which the first version
|
|
50
|
+
of the credential test missed because it only read `environment:` keys.
|
|
51
|
+
- **`minio` moved off `minio/minio:latest`** to `RELEASE.2025-09-07T16-13-09Z`.
|
|
52
|
+
This does not reduce CVEs — MinIO stopped publishing to Docker Hub after that
|
|
53
|
+
release, so `latest` resolves to the same image — but it makes a scan result
|
|
54
|
+
describe what the next user runs rather than what was pulled that day.
|
|
55
|
+
- **No recipe uses an image digest or a floating tag.** A digest freezes the base
|
|
56
|
+
image and accrues CVEs with no upgrade path; the previously pinned pgvector
|
|
57
|
+
digest went from 1 to 22 CRITICAL in three weeks without the image changing at
|
|
58
|
+
all, because only the vulnerability database moved.
|
|
59
|
+
|
|
60
|
+
### Changed
|
|
61
|
+
|
|
62
|
+
- **CLI dispatch is standardized on spawning a CLI with an explicit model and
|
|
63
|
+
effort**, for both Claude and Codex. Codex has no subagent primitive, so spawn
|
|
64
|
+
was already the only option there; standardizing removes the asymmetry. Every
|
|
65
|
+
dispatch now declares **WRITE** or **READ-ONLY** — the hard worktree rule binds
|
|
66
|
+
to WRITE only, since a read-only dispatch cannot edit, which is the entire
|
|
67
|
+
reason the rule exists.
|
|
68
|
+
- **In-session subagents inherit the session model.** Every generated Claude
|
|
69
|
+
subagent previously carried `model: sonnet`, silently overriding an Opus or
|
|
70
|
+
Fable session for planning and review work with no way to see it from the
|
|
71
|
+
harness. Sizing now belongs to the dispatch, not to the agent definition.
|
|
72
|
+
- **Requirement IDs are language-neutral in the shared skills.** `dw-execute-phase`
|
|
73
|
+
is shared by English and Portuguese projects but hard-coded the Portuguese token
|
|
74
|
+
`RF-XX`, so its `plan-checker` searched `tasks.md` for a string English projects
|
|
75
|
+
never generate (`FR-1.1`). Requirement-coverage verification could not match.
|
|
76
|
+
- `tasks.md` gained a `Commit` column, giving `/dw-run` step 6 ("mark Done with
|
|
77
|
+
the commit SHA") somewhere to write. It previously had no destination.
|
|
78
|
+
- `/dw-generate-pr` records the PR URL back into the PRD. Nothing on the `.dw/`
|
|
79
|
+
side previously recorded which PR delivered the work.
|
|
80
|
+
|
|
81
|
+
### Added
|
|
82
|
+
|
|
83
|
+
- `.dw/config/routing.json` — maps a task's Conventional-Commit type to a tier,
|
|
84
|
+
and a tier to a concrete model and effort per brand. Seeded once and never
|
|
85
|
+
reconciled on update, because model availability differs per account.
|
|
86
|
+
- `references/dispatch-tuning.md` in `dw-cli-run`, which declared
|
|
87
|
+
`load_policy: lazy-references` but shipped none. The dual-evaluation protocol,
|
|
88
|
+
escalation ladder, and cold-start tuning moved there.
|
|
89
|
+
- Per-dispatch MCP kill switches: `--strict-mcp-config` (Claude),
|
|
90
|
+
`-c mcp_servers='{}'` (Codex). A spawned CLI boots every configured MCP server
|
|
91
|
+
and shares no prompt cache, which can outweigh a small task.
|
|
92
|
+
- `test/compose-recipe-safety.test.js` and `test/dispatch-routing.test.js`.
|
|
93
|
+
|
|
94
|
+
### Fixed
|
|
95
|
+
|
|
96
|
+
- `.claude-plugin/plugin.json` was stuck at `1.7.0` while `package.json` said
|
|
97
|
+
`1.7.1`, leaving `npm run validate` failing on `main`.
|
|
98
|
+
- Managed-file manifest deduplication and pgvector dev defaults — both committed
|
|
99
|
+
on 2026-07-15 but never merged or published until now.
|
|
100
|
+
|
|
101
|
+
### Notes
|
|
102
|
+
|
|
103
|
+
The regression guards added here deliberately cover **classes**, not files. The
|
|
104
|
+
July 2026 audit raised default credentials against one recipe; that fix was scoped
|
|
105
|
+
to the file in the diff, and the August audit found the same defect in six
|
|
106
|
+
siblings. `compose-recipe-safety.test.js` now fails on any credential default, any
|
|
107
|
+
non-loopback published port on an authenticated service, any digest pin, and any
|
|
108
|
+
floating tag — across every recipe.
|
|
109
|
+
|
|
110
|
+
A full image sweep covered all 16 referenced images, up from 2. Results and the
|
|
111
|
+
residual advisories live in `.dw/secure-audit/` (local, gitignored).
|
|
112
|
+
|
|
113
|
+
## [1.7.1] — 2026-07-24
|
|
114
|
+
|
|
115
|
+
### Fixed
|
|
116
|
+
- `/dw-open-design` command, wrappers, and scripts are synced into the project by
|
|
117
|
+
`install-deps`.
|
|
118
|
+
|
|
119
|
+
## [1.7.0] — 2026-07-15
|
|
120
|
+
|
|
121
|
+
### Added
|
|
122
|
+
- `/dw-open-design` command, with a refactor screenshot mode and a requirement
|
|
123
|
+
that briefs be refined before runs.
|
|
124
|
+
- Docs-first NestJS bootstrap in `/dw-new-project` (Next.js + NestJS, pnpm
|
|
125
|
+
workspaces + Turborepo, pg-boss, Mailpit, dev topology).
|
|
126
|
+
|
|
127
|
+
### Fixed
|
|
128
|
+
- Managed instruction blocks stay idempotent across updates.
|
|
129
|
+
|
|
130
|
+
## [1.6.0] — 2026-07-15
|
|
131
|
+
|
|
132
|
+
Release commit exists; the change set is not cleanly separable from 1.7.0 in the
|
|
133
|
+
history (a source restore commit sits between them). See `git log 28ccc36..af6b157`.
|
|
134
|
+
|
|
135
|
+
## [1.5.0] — 2026-07-02
|
|
136
|
+
|
|
137
|
+
### Added
|
|
138
|
+
- ECC-inspired upgrades: additional skills, runtime cost tracking, a curated rules
|
|
139
|
+
library, and the instincts memory layer.
|
|
140
|
+
|
|
141
|
+
## [1.4.0] — 2026-06-29
|
|
142
|
+
|
|
143
|
+
### Added
|
|
144
|
+
- Skills ecosystem comparison documentation and the README adoptions that followed.
|
|
145
|
+
|
|
146
|
+
## [1.3.0] — 2026-06-23
|
|
147
|
+
|
|
148
|
+
### Added
|
|
149
|
+
- À-la-carte plugin distribution plus a repo `validate` gate.
|
|
150
|
+
- `git-guardrails` and statusline enforcement hooks.
|
|
151
|
+
- Per-skill invocation control via `disable-model-invocation`.
|
|
152
|
+
- `dw-minimalism` (YAGNI decision ladder) and `dw-cli-run` (Claude/Codex/Copilot
|
|
153
|
+
runner protocol) skills.
|
|
154
|
+
|
|
155
|
+
## [1.2.1] — 2026-05-27
|
|
156
|
+
|
|
157
|
+
### Fixed
|
|
158
|
+
- Context-budget wrapper name collision.
|
|
159
|
+
|
|
160
|
+
## [1.2.0] — 2026-05-27
|
|
161
|
+
|
|
162
|
+
### Added
|
|
163
|
+
- Structured return contracts across skills.
|
|
164
|
+
- `/dw-opportunities` and `/dw-refactor` workflows.
|
|
165
|
+
|
|
166
|
+
## [1.1.0] – [1.1.4] — 2026-05-25
|
|
167
|
+
|
|
168
|
+
### Added
|
|
169
|
+
- WSL-resilient browser layer, Security Gate, and the `impeccable` absorption.
|
|
170
|
+
- Portable `/dw-goal` autopilot flow and the subagent handoff workflow.
|
|
171
|
+
- Post-update action guidance.
|
|
172
|
+
|
|
173
|
+
### Fixed
|
|
174
|
+
- Playwright browser selection prefers a real browser with CDP fallback; the
|
|
175
|
+
reverse CDP relay ships prebuilt and runs at user level.
|
|
176
|
+
|
|
177
|
+
## [1.0.0] – [1.0.6] — 2026-05-13
|
|
178
|
+
|
|
179
|
+
Surface consolidation release: 15 obsolete commands deleted and the remainder
|
|
180
|
+
merged into a 20-command surface (later 38 with the tiers added).
|
|
181
|
+
|
|
182
|
+
### Changed
|
|
183
|
+
- `create-prd` + `create-techspec` + `create-tasks` → `/dw-plan`
|
|
184
|
+
- `run-task` + `run-plan` → `/dw-run`
|
|
185
|
+
- `review-implementation` + `code-review` → `/dw-review`
|
|
186
|
+
- `run-qa` + `fix-qa` → `/dw-qa`
|
|
187
|
+
- `security-check` + `deps-audit` → `/dw-secure-audit`
|
|
188
|
+
- `map-codebase` folded into `/dw-intel --build`
|
|
189
|
+
|
|
190
|
+
### Added
|
|
191
|
+
- Removed-commands manifest with old-to-new mapping for migration.
|
|
192
|
+
- Tiered `/dw-help` output with an `--advanced` flag.
|
|
193
|
+
- Opt-in AWS and Azure skill installers with their respective MCP servers.
|
|
194
|
+
|
|
195
|
+
## [0.1.0] – [0.15.0] — 2026-04-06 to 2026-05-13
|
|
196
|
+
|
|
197
|
+
Pre-1.0 development. The CLI, the scaffold layout, the command set, and the
|
|
198
|
+
multi-platform wrapper generation took shape across 35 releases in five weeks.
|
|
199
|
+
See `git log 6cd61cb..d6953f4`.
|
|
200
|
+
|
|
201
|
+
[2.0.0]: https://github.com/brunosps/dev-workflow/releases/tag/v2.0.0
|
package/README.md
CHANGED
|
@@ -42,7 +42,7 @@ Exportable skills (no `.dw/` pipeline required): `dw-minimalism`, `dw-search-fir
|
|
|
42
42
|
|
|
43
43
|
## Commands
|
|
44
44
|
|
|
45
|
-
dev-workflow
|
|
45
|
+
dev-workflow v2.0.0 ships **38 commands** organized into four tiers. Most users only invoke Tier 1 + Tier 2.
|
|
46
46
|
|
|
47
47
|
### Tier 1 — Gateway (3)
|
|
48
48
|
|
|
@@ -81,7 +81,7 @@ Use these when you want step-by-step control instead of `/dw-autopilot`.
|
|
|
81
81
|
| **`/dw-harness-audit`** | Deterministic health scorecard for the dev-workflow install, agents, wrappers, MCPs, and gates. |
|
|
82
82
|
| **`/dw-skill-health`** | Audits installed skills and agents for bloat, duplication, and missing references. |
|
|
83
83
|
| **`/dw-learn`** | Synthesizes durable decisions (confidence-tagged), bugfixes, deviations, and git history into atomic confidence-weighted **instincts** you approve at `.dw/memory/instincts/`; can propose constitution principles. On-demand and human-in-the-loop — **no always-on observer**. |
|
|
84
|
-
| **`/dw-new-project`** | Bootstrap a new project from empty directory. Stack interview, wraps official `create-*` tools
|
|
84
|
+
| **`/dw-new-project`** | Bootstrap a new project from an empty or docs-first directory while preserving existing documentation and prototypes. Stack interview includes Next.js + NestJS, Postgres, pg-boss, Mailpit, dev topology, and wraps official `create-*` tools before composing dev infrastructure, `.env`, scripts, CI, and `.dw/rules/`. |
|
|
85
85
|
| **`/dw-dockerize`** | Reads existing project, detects stack + runtime deps, proposes Dockerfile + docker-compose for dev/prod with explicit trade-offs (Conservative/Balanced/Bold). |
|
|
86
86
|
| **`/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`. |
|
|
87
87
|
| **`/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>]`. |
|
package/lib/agents.js
CHANGED
|
@@ -176,7 +176,12 @@ function renderClaudeAgent(agent, source) {
|
|
|
176
176
|
`name: ${agent.name}`,
|
|
177
177
|
`description: "${yamlString(agent.description)}"`,
|
|
178
178
|
`tools: ${tools.join(', ')}`,
|
|
179
|
-
`
|
|
179
|
+
// `inherit` is Claude Code's documented default: the subagent runs on the
|
|
180
|
+
// session's model. Sizing happens at dispatch (the CLI runners pass an
|
|
181
|
+
// explicit --model/--effort per .dw/config/routing.json), so pinning a tier
|
|
182
|
+
// here would silently override the owner's session choice. A scaffold source
|
|
183
|
+
// agent may still opt out by declaring its own `model:`.
|
|
184
|
+
`model: ${source.metadata.model || 'inherit'}`,
|
|
180
185
|
`permissionMode: ${agent.tool_policy === 'read-only' ? 'plan' : 'default'}`,
|
|
181
186
|
`maxTurns: ${agent.max_turns}`,
|
|
182
187
|
'---',
|
package/lib/init.js
CHANGED
|
@@ -194,6 +194,20 @@ async function run({ force = false, lang = null, mode = 'init', profile = null,
|
|
|
194
194
|
touchedFiles.push(stackMapDest);
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
+
// 3.95. Seed .dw/config/routing.json (dispatch tier/model/effort per brand for
|
|
198
|
+
// the CLI runners). Seeded once and NEVER reconciled: model availability differs
|
|
199
|
+
// per account, so the owner's edits must survive updates.
|
|
200
|
+
const routingSrc = path.join(SCAFFOLD_DIR, 'config', 'routing.json');
|
|
201
|
+
if (require('fs').existsSync(routingSrc)) {
|
|
202
|
+
const cfgDir = path.join(projectRoot, '.dw', 'config');
|
|
203
|
+
ensureDir(cfgDir);
|
|
204
|
+
const routingDest = path.join(cfgDir, 'routing.json');
|
|
205
|
+
const rtStatus = writeFile(routingDest, require('fs').readFileSync(routingSrc, 'utf-8'), false);
|
|
206
|
+
if (rtStatus === 'created') totalCreated++;
|
|
207
|
+
else totalSkipped++;
|
|
208
|
+
touchedFiles.push(routingDest);
|
|
209
|
+
}
|
|
210
|
+
|
|
197
211
|
// 4. Create .dw/rules/ with README
|
|
198
212
|
if (!isUpdate) {
|
|
199
213
|
console.log(' Rules:');
|
package/lib/install-deps.js
CHANGED
|
@@ -90,6 +90,7 @@ function run() {
|
|
|
90
90
|
check: openDesign.check,
|
|
91
91
|
install: openDesign.install,
|
|
92
92
|
instructions: openDesign.instructions(),
|
|
93
|
+
sync: openDesign.syncProjectAssets,
|
|
93
94
|
},
|
|
94
95
|
];
|
|
95
96
|
|
|
@@ -122,6 +123,7 @@ function run() {
|
|
|
122
123
|
try {
|
|
123
124
|
if (typeof dep.check === 'function' && dep.check()) {
|
|
124
125
|
console.log(' \x1b[32m✓ already installed\x1b[0m');
|
|
126
|
+
runDepSync(dep);
|
|
125
127
|
installed++;
|
|
126
128
|
continue;
|
|
127
129
|
}
|
|
@@ -131,6 +133,7 @@ function run() {
|
|
|
131
133
|
execSync(dep.install, { stdio: 'pipe', timeout: 300000 });
|
|
132
134
|
}
|
|
133
135
|
console.log(' \x1b[32m✓\x1b[0m');
|
|
136
|
+
runDepSync(dep);
|
|
134
137
|
installed++;
|
|
135
138
|
} catch (err) {
|
|
136
139
|
console.log(' \x1b[31m✗\x1b[0m');
|
|
@@ -202,3 +205,15 @@ function printBrowserGuidance() {
|
|
|
202
205
|
}
|
|
203
206
|
|
|
204
207
|
module.exports = { run };
|
|
208
|
+
|
|
209
|
+
function runDepSync(dep) {
|
|
210
|
+
if (typeof dep.sync !== 'function') return;
|
|
211
|
+
try {
|
|
212
|
+
const result = dep.sync();
|
|
213
|
+
if (result && result.synced === false && result.reason) {
|
|
214
|
+
console.log(` (project assets not synced: ${result.reason})`);
|
|
215
|
+
}
|
|
216
|
+
} catch (err) {
|
|
217
|
+
console.log(` (project asset sync failed: ${err.message})`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
@@ -2,6 +2,12 @@ const fs = require('fs');
|
|
|
2
2
|
const os = require('os');
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const { execFileSync } = require('child_process');
|
|
5
|
+
const { COMMANDS } = require('./constants');
|
|
6
|
+
const { copyDir, writeFile, log } = require('./utils');
|
|
7
|
+
const { generateWrappers } = require('./wrappers');
|
|
8
|
+
const { readInstallState } = require('./install-state');
|
|
9
|
+
|
|
10
|
+
const SCAFFOLD_DIR = path.join(__dirname, '..', 'scaffold');
|
|
5
11
|
|
|
6
12
|
const OPEN_DESIGN_REPO = 'https://github.com/nexu-io/open-design';
|
|
7
13
|
const OPEN_DESIGN_REF = '1cb7eae';
|
|
@@ -35,6 +41,38 @@ function install() {
|
|
|
35
41
|
}
|
|
36
42
|
}
|
|
37
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Sync the dw-open-design command, scripts and harness wrappers into the
|
|
46
|
+
* current project. install-deps provisions the od CLI, but the skill lives in
|
|
47
|
+
* the project scaffold — without this, users only get the command after a
|
|
48
|
+
* manual `dev-workflow update` (the exact gap reported in the field).
|
|
49
|
+
*/
|
|
50
|
+
function syncProjectAssets(projectRoot = process.cwd()) {
|
|
51
|
+
const state = readInstallState(projectRoot);
|
|
52
|
+
if (!state) {
|
|
53
|
+
return { synced: false, reason: 'no dev-workflow install found in this project (run init/update first)' };
|
|
54
|
+
}
|
|
55
|
+
const lang = state.lang && COMMANDS[state.lang] ? state.lang : 'en';
|
|
56
|
+
const cmd = COMMANDS[lang].find((entry) => entry.name === 'dw-open-design')
|
|
57
|
+
|| COMMANDS.en.find((entry) => entry.name === 'dw-open-design');
|
|
58
|
+
if (!cmd) {
|
|
59
|
+
return { synced: false, reason: 'dw-open-design missing from command registry' };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const commandSrc = path.join(SCAFFOLD_DIR, lang, 'commands', 'dw-open-design.md');
|
|
63
|
+
const commandDest = path.join(projectRoot, '.dw', 'commands', 'dw-open-design.md');
|
|
64
|
+
const status = writeFile(commandDest, fs.readFileSync(commandSrc, 'utf-8'), true);
|
|
65
|
+
log(status, commandDest);
|
|
66
|
+
|
|
67
|
+
const scriptsSrc = path.join(SCAFFOLD_DIR, 'scripts', 'open-design');
|
|
68
|
+
if (fs.existsSync(scriptsSrc)) {
|
|
69
|
+
copyDir(scriptsSrc, path.join(projectRoot, '.dw', 'scripts', 'open-design'), true);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
generateWrappers(projectRoot, [cmd], true);
|
|
73
|
+
return { synced: true };
|
|
74
|
+
}
|
|
75
|
+
|
|
38
76
|
function instructions() {
|
|
39
77
|
return [
|
|
40
78
|
'Open Design CLI is provisioned by dev-workflow into a managed checkout:',
|
|
@@ -80,6 +118,7 @@ function isAtLeast(actual, minimum) {
|
|
|
80
118
|
}
|
|
81
119
|
|
|
82
120
|
module.exports = {
|
|
121
|
+
syncProjectAssets,
|
|
83
122
|
OPEN_DESIGN_REF,
|
|
84
123
|
OPEN_DESIGN_VENDOR_DIR,
|
|
85
124
|
check,
|
package/lib/install-state.js
CHANGED
|
@@ -42,10 +42,14 @@ function writeInstallState(projectRoot, state) {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
function listManagedFiles(projectRoot, relativeFiles) {
|
|
45
|
-
return
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
return [
|
|
46
|
+
...new Set(
|
|
47
|
+
relativeFiles
|
|
48
|
+
.filter(Boolean)
|
|
49
|
+
.map((filePath) => path.relative(projectRoot, filePath))
|
|
50
|
+
.sort()
|
|
51
|
+
),
|
|
52
|
+
];
|
|
49
53
|
}
|
|
50
54
|
|
|
51
55
|
module.exports = {
|
package/lib/utils.js
CHANGED
|
@@ -90,6 +90,20 @@ function writeJson(filePath, value) {
|
|
|
90
90
|
fs.writeFileSync(filePath, JSON.stringify(value, null, 2) + '\n', 'utf-8');
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
function findStandaloneMarkers(content, marker) {
|
|
94
|
+
// Marker names also appear in explanatory prose, so only a full marker line delimits a block.
|
|
95
|
+
const escapedMarker = marker.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
96
|
+
const pattern = new RegExp(`^[\\t ]*${escapedMarker}[\\t ]*\\r?$`, 'gm');
|
|
97
|
+
const markers = [];
|
|
98
|
+
let match;
|
|
99
|
+
|
|
100
|
+
while ((match = pattern.exec(content)) !== null) {
|
|
101
|
+
const start = match.index + match[0].indexOf(marker);
|
|
102
|
+
markers.push({ start, end: start + marker.length });
|
|
103
|
+
}
|
|
104
|
+
return markers;
|
|
105
|
+
}
|
|
106
|
+
|
|
93
107
|
/**
|
|
94
108
|
* Upsert a delimited block inside an existing file.
|
|
95
109
|
*
|
|
@@ -105,8 +119,19 @@ function upsertDelimitedBlock(filePath, blockContent, startMarker, endMarker) {
|
|
|
105
119
|
|
|
106
120
|
// The block content already includes its own start/end markers (so the scaffold
|
|
107
121
|
// file can be read verbatim). Validate that.
|
|
108
|
-
|
|
109
|
-
|
|
122
|
+
const blockStarts = findStandaloneMarkers(blockContent, startMarker);
|
|
123
|
+
const blockEnds = findStandaloneMarkers(blockContent, endMarker);
|
|
124
|
+
if (blockStarts.length === 0 || blockEnds.length === 0) {
|
|
125
|
+
throw new Error(`Block content for ${filePath} is missing standalone markers`);
|
|
126
|
+
}
|
|
127
|
+
if (blockStarts.length > 1 || blockEnds.length > 1) {
|
|
128
|
+
throw new Error(`Block content for ${filePath} has duplicate standalone markers`);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const blockStart = blockStarts[0];
|
|
132
|
+
const blockEnd = blockEnds[0];
|
|
133
|
+
if (blockEnd.start < blockStart.end) {
|
|
134
|
+
throw new Error(`Block content for ${filePath} is missing standalone markers`);
|
|
110
135
|
}
|
|
111
136
|
|
|
112
137
|
if (!exists) {
|
|
@@ -115,17 +140,32 @@ function upsertDelimitedBlock(filePath, blockContent, startMarker, endMarker) {
|
|
|
115
140
|
}
|
|
116
141
|
|
|
117
142
|
const current = fs.readFileSync(filePath, 'utf-8');
|
|
118
|
-
const
|
|
143
|
+
const currentStarts = findStandaloneMarkers(current, startMarker);
|
|
144
|
+
const currentEnds = findStandaloneMarkers(current, endMarker);
|
|
119
145
|
|
|
120
|
-
if (
|
|
146
|
+
if (currentStarts.length === 0 && currentEnds.length === 0) {
|
|
121
147
|
const separator = current.endsWith('\n') ? '\n' : '\n\n';
|
|
122
148
|
const next = current + separator + (blockContent.endsWith('\n') ? blockContent : blockContent + '\n');
|
|
123
149
|
fs.writeFileSync(filePath, next, 'utf-8');
|
|
124
150
|
return 'updated';
|
|
125
151
|
}
|
|
126
152
|
|
|
127
|
-
|
|
128
|
-
|
|
153
|
+
if (currentStarts.length > 1 || currentEnds.length > 1) {
|
|
154
|
+
throw new Error(`Existing file ${filePath} has duplicate standalone markers`);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (currentStarts.length !== 1 || currentEnds.length !== 1) {
|
|
158
|
+
throw new Error(`Existing file ${filePath} has unbalanced standalone markers`);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const currentStart = currentStarts[0];
|
|
162
|
+
const currentEnd = currentEnds[0];
|
|
163
|
+
if (currentEnd.start < currentStart.end) {
|
|
164
|
+
throw new Error(`Existing file ${filePath} has unbalanced standalone markers`);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const before = current.slice(0, currentStart.start);
|
|
168
|
+
const after = current.slice(currentEnd.end);
|
|
129
169
|
const next = before + blockContent.trim() + after;
|
|
130
170
|
if (next === current) return 'unchanged';
|
|
131
171
|
fs.writeFileSync(filePath, next, 'utf-8');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brunosps00/dev-workflow",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.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"
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"scaffold/",
|
|
18
18
|
".claude-plugin/",
|
|
19
19
|
"README.md",
|
|
20
|
+
"CHANGELOG.md",
|
|
20
21
|
"LICENSE"
|
|
21
22
|
],
|
|
22
23
|
"keywords": [
|
|
@@ -42,7 +43,7 @@
|
|
|
42
43
|
},
|
|
43
44
|
"repository": {
|
|
44
45
|
"type": "git",
|
|
45
|
-
"url": "https://github.com/
|
|
46
|
+
"url": "https://github.com/brunosps/dev-workflow"
|
|
46
47
|
},
|
|
47
48
|
"author": "Bruno Santos"
|
|
48
49
|
}
|