@brunosps00/dev-workflow 1.0.6 → 1.1.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 +2 -2
- package/bin/dev-workflow.js +5 -0
- package/lib/constants.js +2 -2
- package/lib/install-deps.js +88 -3
- package/lib/setup-wsl-browser.js +149 -0
- package/package.json +1 -1
- package/scaffold/en/commands/dw-analyze-project.md +22 -0
- package/scaffold/en/commands/dw-autopilot.md +3 -1
- package/scaffold/en/commands/dw-functional-doc.md +11 -3
- package/scaffold/en/commands/dw-generate-pr.md +2 -2
- package/scaffold/en/commands/dw-qa.md +1 -1
- package/scaffold/en/commands/dw-redesign-ui.md +2 -2
- package/scaffold/en/commands/dw-review.md +7 -5
- package/scaffold/en/commands/dw-secure-audit.md +72 -15
- package/scaffold/en/templates/constitution-template.md +8 -3
- package/scaffold/en/templates/functional-doc/playwright.flow.mjs.tpl +17 -0
- package/scaffold/pt-br/commands/dw-analyze-project.md +22 -0
- package/scaffold/pt-br/commands/dw-autopilot.md +3 -1
- package/scaffold/pt-br/commands/dw-functional-doc.md +11 -3
- package/scaffold/pt-br/commands/dw-generate-pr.md +2 -2
- package/scaffold/pt-br/commands/dw-qa.md +1 -1
- package/scaffold/pt-br/commands/dw-redesign-ui.md +2 -2
- package/scaffold/pt-br/commands/dw-review.md +7 -5
- package/scaffold/pt-br/commands/dw-secure-audit.md +72 -15
- package/scaffold/pt-br/templates/constitution-template.md +8 -3
- package/scaffold/pt-br/templates/functional-doc/playwright.flow.mjs.tpl +17 -0
- package/scaffold/scripts/cdp-relay/Cargo.toml +16 -0
- package/scaffold/scripts/cdp-relay/src/main.rs +49 -0
- package/scaffold/scripts/functional-doc/generate-dossier.mjs +7 -9
- package/scaffold/scripts/functional-doc/run-playwright-flow.mjs +192 -183
- package/scaffold/scripts/lib/capture-screenshots.mjs +133 -0
- package/scaffold/scripts/lib/resolve-browser.mjs +405 -0
- package/scaffold/scripts/lib/ui-slop-detect.mjs +102 -0
- package/scaffold/skills/dw-testing-discipline/references/playwright-recipes.md +50 -0
- package/scaffold/skills/dw-ui-discipline/SKILL.md +5 -0
- package/scaffold/skills/dw-ui-discipline/references/color-oklch.md +60 -0
- package/scaffold/skills/dw-ui-discipline/references/motion.md +52 -0
- package/scaffold/skills/dw-ui-discipline/references/responsive.md +52 -0
- package/scaffold/skills/dw-ui-discipline/references/type-scale.md +48 -0
- package/scaffold/skills/dw-ui-discipline/references/ux-writing.md +52 -0
- package/scaffold/skills/security-review/SKILL.md +19 -0
- package/scaffold/skills/security-review/references/sast.md +67 -0
- package/scaffold/skills/security-review/references/secrets.md +46 -0
- package/scaffold/en/templates/functional-doc/playwright.spec.ts.tpl +0 -19
- package/scaffold/pt-br/templates/functional-doc/playwright.spec.ts.tpl +0 -19
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ This will:
|
|
|
19
19
|
|
|
20
20
|
> **Compozy-inspired disciplines.** Since 0.5.0, dev-workflow bundles three primitives — `dw-verify`, `dw-memory`, `dw-review-rigor` — adapted from the [Compozy](https://github.com/compozy/compozy) project and invoked internally by existing commands. See [docs/compozy-integration.md](docs/compozy-integration.md) for what was ported and what was not.
|
|
21
21
|
|
|
22
|
-
Optional dependencies (Playwright browsers, react-doctor, Trivy, Docker):
|
|
22
|
+
Optional dependencies (Playwright browsers, react-doctor, Trivy, Semgrep, gitleaks, Docker):
|
|
23
23
|
```bash
|
|
24
24
|
npx @brunosps00/dev-workflow install-deps
|
|
25
25
|
```
|
|
@@ -75,7 +75,7 @@ These are auto-invoked by Tier 1-3 commands. Available standalone via `/dw-help
|
|
|
75
75
|
|---------|------|------------|
|
|
76
76
|
| **`/dw-adr "decision"`** | Records an Architecture Decision Record at `.dw/spec/<prd>/adrs/`. | `/dw-plan techspec --council`; deviations from constitution |
|
|
77
77
|
| **`/dw-intel "question"`** | Query codebase intelligence (`.dw/intel/`). `--build` (re)creates the index. | `/dw-plan`, `/dw-review`, `/dw-bugfix` |
|
|
78
|
-
| **`/dw-secure-audit`** |
|
|
78
|
+
| **`/dw-secure-audit`** | **Security Gate** (phase after review/QA, before commit/PR): OWASP + Semgrep SAST (diff/generated code) + gitleaks secrets + Trivy SCA/IaC + lockfile + supply-chain + outdated. Rigoroso: secrets/CRITICAL/HIGH block (secrets have no ADR escape). Flags: `--scan-only`, `--plan`, `--execute`. See [docs/security-gate.md](docs/security-gate.md). | `/dw-autopilot` (explicit step), enforced by `/dw-generate-pr` |
|
|
79
79
|
| **`/dw-goal "<objective>"`** | Durable objective contract. Uses Codex native `/goal` when available and `.dw/goals/` everywhere for Codex, Copilot, Claude Code, and OpenCode. | `/dw-autopilot` after planning |
|
|
80
80
|
| **`/dw-find-skills "query"`** | Searches `npx skills` ecosystem, vets, installs. | manual when extending the bundle |
|
|
81
81
|
| **`/dw-update`** | Updates dev-workflow to latest npm release with rollback snapshot. | manual maintenance |
|
package/bin/dev-workflow.js
CHANGED
|
@@ -5,6 +5,7 @@ const installDeps = require('../lib/install-deps');
|
|
|
5
5
|
const installAzureSkills = require('../lib/install-azure-skills');
|
|
6
6
|
const installAwsSkills = require('../lib/install-aws-skills');
|
|
7
7
|
const uninstall = require('../lib/uninstall');
|
|
8
|
+
const setupWslBrowser = require('../lib/setup-wsl-browser');
|
|
8
9
|
|
|
9
10
|
const args = process.argv.slice(2);
|
|
10
11
|
const command = args[0];
|
|
@@ -45,6 +46,7 @@ const HELP_TEXT = `
|
|
|
45
46
|
repair Reconcile managed files using the recorded install state
|
|
46
47
|
subtask Create, complete, consume, and list local subagent handoffs
|
|
47
48
|
install-deps Install system dependencies (Playwright browsers, MCP servers)
|
|
49
|
+
setup-wsl-browser (WSL) Build the CDP relay on Windows + add the Hyper-V firewall rule so flows can drive the real Windows browser
|
|
48
50
|
install-azure-skills Opt-in: clone curated Azure skills from MicrosoftDocs/Agent-Skills
|
|
49
51
|
into .agents/skills/azure/ and register the Microsoft Learn MCP
|
|
50
52
|
server (HTTP, no-auth). Interactive category selection.
|
|
@@ -95,6 +97,9 @@ async function main() {
|
|
|
95
97
|
case 'install-deps':
|
|
96
98
|
installDeps.run();
|
|
97
99
|
break;
|
|
100
|
+
case 'setup-wsl-browser':
|
|
101
|
+
setupWslBrowser.run();
|
|
102
|
+
break;
|
|
98
103
|
case 'install-azure-skills':
|
|
99
104
|
await installAzureSkills.run();
|
|
100
105
|
break;
|
package/lib/constants.js
CHANGED
|
@@ -25,7 +25,7 @@ const COMMANDS = {
|
|
|
25
25
|
{ name: 'dw-resume', description: 'Trigger when user says "resume work", "where did we stop?", or starts a session in a project with an existing .dw/STATE.md. Reads STATE.md, presents a TLDR, and suggests the next dw-* command.' },
|
|
26
26
|
{ name: 'dw-review', description: 'Trigger when user asks to review code, check quality, or verify PR readiness. Default runs L2 (PRD coverage) + L3 (code quality). Flags --coverage-only / --code-only / --bugfix <slug>.' },
|
|
27
27
|
{ name: 'dw-run', description: 'Trigger when user wants to execute tasks. Default runs all pending in dependency order; \'run <task-id>\' runs one; \'run --resume\' continues an interrupted plan.' },
|
|
28
|
-
{ name: 'dw-secure-audit', description: '
|
|
28
|
+
{ name: 'dw-secure-audit', description: 'Security Gate: OWASP + Semgrep SAST (diff) + gitleaks secrets + Trivy SCA/IaC + lockfile + supply-chain + outdated. Rigoroso: secrets/CRITICAL/HIGH block. Auto-invoked by /dw-review and /dw-generate-pr, explicit phase in /dw-autopilot, and runnable standalone.' },
|
|
29
29
|
{ name: 'dw-skill-health', description: 'Audits installed skills and agents for bloat, duplication, missing references, and stale or unused modules.' },
|
|
30
30
|
{ name: 'dw-subtask-start', description: 'Creates a minimal input packet for a subagent without injecting the parent transcript.' },
|
|
31
31
|
{ name: 'dw-subtask-complete', description: 'Records a structured subagent handoff with result, files, decisions, risks, verification, and blockers.' },
|
|
@@ -58,7 +58,7 @@ const COMMANDS = {
|
|
|
58
58
|
{ name: 'dw-resume', description: 'Trigger quando usuario diz "retoma", "onde paramos?" ou comeca sessao num projeto com .dw/STATE.md existente. Le STATE.md, apresenta TLDR e sugere proximo comando dw-*.' },
|
|
59
59
|
{ name: 'dw-review', description: 'Trigger quando usuario pede pra revisar codigo, checar qualidade ou validar prontidao pra PR. Default roda L2 (cobertura PRD) + L3 (qualidade). Flags --coverage-only / --code-only / --bugfix <slug>.' },
|
|
60
60
|
{ name: 'dw-run', description: 'Trigger quando usuario quer executar tasks. Default roda todas pendentes em ordem de dependencia; \'run <task-id>\' roda uma; \'run --resume\' continua plan interrompido.' },
|
|
61
|
-
{ name: 'dw-secure-audit', description: '
|
|
61
|
+
{ name: 'dw-secure-audit', description: 'Security Gate: OWASP + Semgrep SAST (diff) + gitleaks secrets + Trivy SCA/IaC + lockfile + supply-chain + outdated. Rigoroso: secrets/CRITICAL/HIGH bloqueiam. Auto-invocado por /dw-review e /dw-generate-pr, fase explicita no /dw-autopilot, e executavel standalone.' },
|
|
62
62
|
{ name: 'dw-skill-health', description: 'Audita skills e agentes instalados por bloat, duplicacao, referencias quebradas e modulos sem uso.' },
|
|
63
63
|
{ name: 'dw-subtask-start', description: 'Cria um input packet minimo para subagente sem injetar transcript bruto do parent.' },
|
|
64
64
|
{ name: 'dw-subtask-complete', description: 'Registra handoff estruturado do subagente com resultado, arquivos, decisoes, riscos, verificacao e bloqueios.' },
|
package/lib/install-deps.js
CHANGED
|
@@ -6,9 +6,9 @@ function run() {
|
|
|
6
6
|
|
|
7
7
|
const deps = [
|
|
8
8
|
{
|
|
9
|
-
name: 'Playwright browsers',
|
|
9
|
+
name: 'Playwright browsers (Chromium + deps)',
|
|
10
10
|
check: 'npx playwright --version',
|
|
11
|
-
install: 'npx playwright install --with-deps',
|
|
11
|
+
install: 'npx playwright install --with-deps chromium',
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
14
|
name: 'Context7 MCP',
|
|
@@ -31,7 +31,44 @@ function run() {
|
|
|
31
31
|
' Windows: choco install trivy (or: scoop install trivy)',
|
|
32
32
|
' Docker: docker pull aquasec/trivy:latest (use via alias or wrapper)',
|
|
33
33
|
'',
|
|
34
|
-
'Once installed, /dw-
|
|
34
|
+
'Once installed, /dw-secure-audit will use it for CVE, secret, and IaC scanning.',
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: 'Semgrep (SAST)',
|
|
39
|
+
check: 'semgrep --version',
|
|
40
|
+
install: null,
|
|
41
|
+
instructions: [
|
|
42
|
+
'Semgrep powers the SAST layer of /dw-secure-audit (semantic analysis of generated code).',
|
|
43
|
+
' pipx: pipx install semgrep (recommended — isolated)',
|
|
44
|
+
' pip: python3 -m pip install --user semgrep',
|
|
45
|
+
' macOS: brew install semgrep',
|
|
46
|
+
' Docker: docker pull semgrep/semgrep:latest (use via alias or wrapper)',
|
|
47
|
+
'',
|
|
48
|
+
'The gate runs pinned rulesets (p/security-audit, p/owasp-top-ten, p/secrets) on the diff.',
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: 'gitleaks (secret scanner)',
|
|
53
|
+
check: 'gitleaks version',
|
|
54
|
+
install: null,
|
|
55
|
+
instructions: [
|
|
56
|
+
'gitleaks is the dedicated secret scanner for /dw-secure-audit (any hit blocks the gate).',
|
|
57
|
+
' macOS: brew install gitleaks',
|
|
58
|
+
' Linux: download from https://github.com/gitleaks/gitleaks/releases (or: go install github.com/gitleaks/gitleaks/v8@latest)',
|
|
59
|
+
' Windows: scoop install gitleaks (or: choco install gitleaks)',
|
|
60
|
+
' Docker: docker pull zricethezav/gitleaks:latest',
|
|
61
|
+
],
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: 'syft (SBOM, optional)',
|
|
65
|
+
check: 'syft version',
|
|
66
|
+
install: null,
|
|
67
|
+
instructions: [
|
|
68
|
+
'syft generates the SBOM for the advisory SBOM/license layer of /dw-secure-audit (optional, non-blocking).',
|
|
69
|
+
' macOS: brew install syft',
|
|
70
|
+
' Linux: curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin',
|
|
71
|
+
' Windows: scoop install syft',
|
|
35
72
|
],
|
|
36
73
|
},
|
|
37
74
|
{
|
|
@@ -93,6 +130,54 @@ function run() {
|
|
|
93
130
|
if (failed) parts.push(`${failed} failed`);
|
|
94
131
|
console.log(` Done! ${parts.join(', ')}`);
|
|
95
132
|
console.log();
|
|
133
|
+
|
|
134
|
+
checkPlaywrightVersion();
|
|
135
|
+
printBrowserGuidance();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// page.screencast (used by /dw-functional-doc to record video, including over CDP) needs
|
|
139
|
+
// Playwright >= 1.60. Warn if the installed version is older.
|
|
140
|
+
function checkPlaywrightVersion() {
|
|
141
|
+
try {
|
|
142
|
+
const raw = execSync('npx playwright --version', { stdio: 'pipe', timeout: 15000 }).toString();
|
|
143
|
+
const match = raw.match(/(\d+)\.(\d+)\.(\d+)/);
|
|
144
|
+
if (!match) return;
|
|
145
|
+
const [, major, minor] = match.map(Number);
|
|
146
|
+
if (major < 1 || (major === 1 && minor < 60)) {
|
|
147
|
+
console.log(` \x1b[33m⚠ Playwright ${match[0]} detected.\x1b[0m /dw-functional-doc video needs >= 1.60 (page.screencast).`);
|
|
148
|
+
console.log(' Upgrade in your project: npm i -D @playwright/test@latest');
|
|
149
|
+
console.log();
|
|
150
|
+
}
|
|
151
|
+
} catch {
|
|
152
|
+
// playwright not resolvable here; the flow runner reports it at runtime
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function isWsl() {
|
|
157
|
+
if (process.env.WSL_DISTRO_NAME) return true;
|
|
158
|
+
try {
|
|
159
|
+
return /microsoft/i.test(require('fs').readFileSync('/proc/version', 'utf8'));
|
|
160
|
+
} catch {
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function printBrowserGuidance() {
|
|
166
|
+
if (!isWsl()) return;
|
|
167
|
+
const mirrored = require('fs').existsSync('/sys/class/net/loopback0');
|
|
168
|
+
console.log(' Browser automation on WSL (dw-qa / dw-functional-doc / dw-redesign-ui):');
|
|
169
|
+
console.log(' Default: full headless Chromium (desktop-faithful, no WSLg) — works out of the box.');
|
|
170
|
+
console.log(' To drive the real Windows browser, set BROWSER_TEST to its exe path, e.g.');
|
|
171
|
+
console.log(' BROWSER_TEST="/mnt/c/Program Files (x86)/Microsoft/Edge/Application/msedge.exe".');
|
|
172
|
+
if (mirrored) {
|
|
173
|
+
console.log(' Mirrored networking detected — connects to the Windows browser on 127.0.0.1 directly.');
|
|
174
|
+
} else {
|
|
175
|
+
console.log(' NAT networking — run `npx @brunosps00/dev-workflow setup-wsl-browser` once to build the');
|
|
176
|
+
console.log(' cdp-relay.exe (needs Rust on Windows) and add the Hyper-V firewall rule. Otherwise flows');
|
|
177
|
+
console.log(' fall back to the local headless Chromium (faithful video, no Windows browser).');
|
|
178
|
+
}
|
|
179
|
+
console.log(' Details: .dw/skills/dw-testing-discipline/references/playwright-recipes.md ("Browser on WSL").');
|
|
180
|
+
console.log();
|
|
96
181
|
}
|
|
97
182
|
|
|
98
183
|
module.exports = { run };
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
const { execSync, spawnSync } = require('child_process');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
// Builds the Rust CDP relay (cdp-relay.exe) on Windows and adds the one-time Hyper-V firewall
|
|
6
|
+
// rule so WSL (NAT networking) can drive the real Windows browser over CDP. Idempotent.
|
|
7
|
+
//
|
|
8
|
+
// Why: Chromium binds its debug port to Windows loopback only, and the WSL Hyper-V firewall
|
|
9
|
+
// defaults inbound to Block. A fixed-port relay + one Hyper-V allow rule bridges WSL -> browser.
|
|
10
|
+
// The relay is a tiny static .exe — no Node/Python/PowerShell runtime dependency at run time.
|
|
11
|
+
|
|
12
|
+
const RELAY_PORT = 39222;
|
|
13
|
+
const WSL_VM_CREATOR_ID = '{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}'; // standard WSL VM creator id
|
|
14
|
+
const RULE_NAME = 'dw-cdp-relay';
|
|
15
|
+
|
|
16
|
+
function isWsl() {
|
|
17
|
+
if (process.env.WSL_DISTRO_NAME) return true;
|
|
18
|
+
try {
|
|
19
|
+
return /microsoft/i.test(fs.readFileSync('/proc/version', 'utf8'));
|
|
20
|
+
} catch {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function winEnv(name) {
|
|
26
|
+
try {
|
|
27
|
+
const out = execSync(`cmd.exe /c "echo %${name}%"`, { stdio: 'pipe' }).toString().split(/\r?\n/)[0].trim();
|
|
28
|
+
return /^[A-Za-z]:\\/.test(out) ? out : null;
|
|
29
|
+
} catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function findWindowsCargo() {
|
|
35
|
+
try {
|
|
36
|
+
const line = execSync('cmd.exe /c where cargo', { stdio: 'pipe' })
|
|
37
|
+
.toString()
|
|
38
|
+
.split(/\r?\n/)
|
|
39
|
+
.map((s) => s.trim())
|
|
40
|
+
.find((s) => /cargo\.exe$/i.test(s));
|
|
41
|
+
if (!line) return null;
|
|
42
|
+
const wsl = execSync(`wslpath -u "${line}"`, { stdio: 'pipe' }).toString().trim();
|
|
43
|
+
return fs.existsSync(wsl) ? { winPath: line, wslPath: wsl } : null;
|
|
44
|
+
} catch {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function copyCrate(srcDir, destWslDir) {
|
|
50
|
+
fs.mkdirSync(path.join(destWslDir, 'src'), { recursive: true });
|
|
51
|
+
fs.copyFileSync(path.join(srcDir, 'Cargo.toml'), path.join(destWslDir, 'Cargo.toml'));
|
|
52
|
+
fs.copyFileSync(path.join(srcDir, 'src', 'main.rs'), path.join(destWslDir, 'src', 'main.rs'));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function run() {
|
|
56
|
+
console.log('\n dev-workflow setup-wsl-browser');
|
|
57
|
+
console.log(` ${'='.repeat(40)}\n`);
|
|
58
|
+
|
|
59
|
+
if (!isWsl()) {
|
|
60
|
+
console.log(' This command is only needed on WSL. On native Windows/macOS/Linux, flows use the local browser directly.');
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const localAppData = winEnv('LOCALAPPDATA');
|
|
65
|
+
if (!localAppData) {
|
|
66
|
+
console.log(' \x1b[31m✗\x1b[0m Could not resolve %LOCALAPPDATA% on Windows. Is Windows interop enabled?');
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const destWin = `${localAppData}\\dev-workflow`;
|
|
70
|
+
const destWsl = execSync(`wslpath -u "${destWin}"`, { stdio: 'pipe' }).toString().trim();
|
|
71
|
+
const srcWslDir = `${destWsl}/cdp-relay-src`;
|
|
72
|
+
const srcWinDir = `${destWin}\\cdp-relay-src`;
|
|
73
|
+
|
|
74
|
+
// 1) Build the relay with the Windows Rust toolchain.
|
|
75
|
+
const cargo = findWindowsCargo();
|
|
76
|
+
if (!cargo) {
|
|
77
|
+
console.log(' \x1b[33m—\x1b[0m No Windows `cargo` found (where cargo). Install Rust on Windows: https://rustup.rs');
|
|
78
|
+
console.log(' Without the relay, WSL flows fall back to the local headless Chromium (faithful, no Windows browser).');
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const crateSrc = path.join(__dirname, '..', 'scaffold', 'scripts', 'cdp-relay');
|
|
83
|
+
if (!fs.existsSync(path.join(crateSrc, 'Cargo.toml'))) {
|
|
84
|
+
console.log(` \x1b[31m✗\x1b[0m Relay crate source not found at ${crateSrc}`);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
process.stdout.write(' Building cdp-relay.exe (Windows cargo, release)...');
|
|
89
|
+
try {
|
|
90
|
+
fs.mkdirSync(destWsl, { recursive: true });
|
|
91
|
+
copyCrate(crateSrc, srcWslDir);
|
|
92
|
+
execSync(`"${cargo.wslPath}" build --release --manifest-path "${srcWinDir}\\Cargo.toml"`, {
|
|
93
|
+
stdio: 'pipe',
|
|
94
|
+
timeout: 180000,
|
|
95
|
+
});
|
|
96
|
+
fs.copyFileSync(path.join(srcWslDir, 'target', 'release', 'cdp-relay.exe'), path.join(destWsl, 'cdp-relay.exe'));
|
|
97
|
+
console.log(' \x1b[32m✓\x1b[0m');
|
|
98
|
+
console.log(` ${destWin}\\cdp-relay.exe`);
|
|
99
|
+
} catch (err) {
|
|
100
|
+
console.log(' \x1b[31m✗\x1b[0m');
|
|
101
|
+
console.log(` ${String(err.message).split('\n')[0]}`);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// 2) Add the Hyper-V firewall inbound rule (one-time, elevated -> UAC prompt).
|
|
106
|
+
console.log(`\n Adding Hyper-V firewall rule for TCP ${RELAY_PORT} (a UAC prompt will appear — accept it)...`);
|
|
107
|
+
const inner = [
|
|
108
|
+
`Remove-NetFirewallHyperVRule -Name '${RULE_NAME}' -ErrorAction SilentlyContinue;`,
|
|
109
|
+
`New-NetFirewallHyperVRule -Name '${RULE_NAME}' -DisplayName 'dev-workflow cdp-relay'`,
|
|
110
|
+
`-Direction Inbound -Action Allow -VMCreatorId '${WSL_VM_CREATOR_ID}' -Protocol TCP -LocalPorts ${RELAY_PORT}`,
|
|
111
|
+
].join(' ');
|
|
112
|
+
try {
|
|
113
|
+
execSync(
|
|
114
|
+
`powershell.exe -NoProfile -Command "Start-Process powershell -Verb RunAs -WindowStyle Hidden -ArgumentList '-NoProfile','-Command',\\"${inner}\\""`,
|
|
115
|
+
{ stdio: 'pipe', timeout: 60000 },
|
|
116
|
+
);
|
|
117
|
+
} catch {
|
|
118
|
+
// Start-Process returns before the elevated process finishes; verify below regardless.
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// 3) Verify.
|
|
122
|
+
let ok = false;
|
|
123
|
+
for (let i = 0; i < 10 && !ok; i += 1) {
|
|
124
|
+
try {
|
|
125
|
+
const out = execSync(
|
|
126
|
+
`powershell.exe -NoProfile -c "Get-NetFirewallHyperVRule -Name '${RULE_NAME}' -ErrorAction SilentlyContinue | Select-Object -Expand Action"`,
|
|
127
|
+
{ stdio: 'pipe', timeout: 15000 },
|
|
128
|
+
).toString();
|
|
129
|
+
ok = /Allow/i.test(out);
|
|
130
|
+
} catch {
|
|
131
|
+
ok = false;
|
|
132
|
+
}
|
|
133
|
+
if (!ok) execSync('sleep 1');
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
console.log(` ${'='.repeat(40)}`);
|
|
137
|
+
if (ok) {
|
|
138
|
+
console.log(' \x1b[32m✓ Done.\x1b[0m The Windows browser is reachable from WSL over CDP.');
|
|
139
|
+
console.log(` Set BROWSER_TEST to a Windows browser exe to use it, e.g.`);
|
|
140
|
+
console.log(' BROWSER_TEST="/mnt/c/Program Files (x86)/Microsoft/Edge/Application/msedge.exe"');
|
|
141
|
+
} else {
|
|
142
|
+
console.log(' \x1b[33m⚠ Hyper-V firewall rule not confirmed.\x1b[0m UAC may have been declined, or this Windows lacks');
|
|
143
|
+
console.log(' Hyper-V firewall cmdlets. Flows will fall back to the local headless Chromium (faithful video, no');
|
|
144
|
+
console.log(' Windows browser). You can also enable mirrored networking instead. Re-run to retry.');
|
|
145
|
+
}
|
|
146
|
+
console.log();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
module.exports = { run, RELAY_PORT };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brunosps00/dev-workflow",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.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"
|
|
@@ -827,6 +827,27 @@ If after the heuristics nothing crosses the bar (small codebase, low churn, no i
|
|
|
827
827
|
|
|
828
828
|
**Refresh cadence:** users re-run `/dw-analyze-project` whenever rules drift. Step 9 refreshes auto sections while keeping preserved entries. There is no separate refresh-only command.
|
|
829
829
|
|
|
830
|
+
### Step 10: Design authority (DESIGN.md) — frontend projects only
|
|
831
|
+
|
|
832
|
+
Run this when a frontend was detected (React/Vue/Angular/Svelte/Tailwind/CSS) so `dw-ui-discipline`'s
|
|
833
|
+
grounding question 1 ("where do design decisions come from?") has a project authority to defer to. This
|
|
834
|
+
closes the loop the grounding only *reads* today.
|
|
835
|
+
|
|
836
|
+
1. **Check for an existing authority first.** If `DESIGN.md`, `BRAND.md`, or `STYLE_GUIDE.md` already
|
|
837
|
+
exists at the project (or a frontend module) root, do NOT overwrite — note its location and stop.
|
|
838
|
+
2. **Detect design tokens** in priority order: Tailwind `theme`/`@theme` (colors, fontFamily, spacing,
|
|
839
|
+
radius), CSS custom properties in `globals.css`/`theme.css`/`tokens.css`, MUI/Chakra theme exports,
|
|
840
|
+
shadcn `components.json`, Storybook theme. Read the real values — do not invent.
|
|
841
|
+
3. **If tokens exist:** synthesize `DESIGN.md` at the frontend root capturing what the project ALREADY
|
|
842
|
+
uses — palette (with the actual hex/oklch values and token names), typography (families, scale,
|
|
843
|
+
weights), spacing/radius scale, and any component conventions observed. Head it with:
|
|
844
|
+
`> Generated by /dw-analyze-project from existing tokens on <date>. Curate before treating as canon.`
|
|
845
|
+
4. **If no tokens exist:** do NOT fabricate a palette. Recommend bootstrapping from
|
|
846
|
+
`dw-ui-discipline/references/curated-defaults.md` and record that recommendation in the rules index.
|
|
847
|
+
5. Reference the new `DESIGN.md` from `.dw/rules/<frontend-module>.md` so downstream commands find it.
|
|
848
|
+
|
|
849
|
+
This step is additive and reversible; it never edits component code, only documents what is there.
|
|
850
|
+
|
|
830
851
|
## Quality Checklist
|
|
831
852
|
|
|
832
853
|
Before declaring the analysis complete, verify:
|
|
@@ -850,6 +871,7 @@ Before declaring the analysis complete, verify:
|
|
|
850
871
|
- [ ] All file paths in rules reference real, existing files
|
|
851
872
|
- [ ] Step 8 (constitution) offered and resolved (A/B/C)
|
|
852
873
|
- [ ] Step 9 (concerns map) presented candidates, awaited approval, wrote `.dw/rules/concerns.md` (or noted no signals)
|
|
874
|
+
- [ ] Step 10 (design authority) ran for frontend projects: existing authority respected, or `DESIGN.md` generated from real tokens, or curated-defaults bootstrap recommended
|
|
853
875
|
- [ ] Preserved-marker blocks in concerns.md kept verbatim on refresh
|
|
854
876
|
- [ ] Topology analysis completed (god nodes, coupling metrics, dependency graph)
|
|
855
877
|
- [ ] Critical nodes table generated with Ca, Ce, instability
|
|
@@ -152,10 +152,11 @@ When `autopilot-state.json status=plan_complete`, formally invoke:
|
|
|
152
152
|
The goal owns this sequence:
|
|
153
153
|
|
|
154
154
|
1. `/dw-run <prd-path>`
|
|
155
|
-
2. `/dw-review <prd-path>` (full review: coverage, quality, conventions,
|
|
155
|
+
2. `/dw-review <prd-path>` (full review: coverage, quality, conventions, constitution, verify)
|
|
156
156
|
3. `/dw-qa <prd-path>`
|
|
157
157
|
4. `/dw-qa --fix <prd-path>` if QA found Open bugs
|
|
158
158
|
5. `/dw-review <prd-path>` again after QA/fixes
|
|
159
|
+
6. **Security Gate** — the post-QA `/dw-review` (step 5) triggers `/dw-secure-audit`, producing a fresh `.dw/secure-audit/audit-summary.md`. This step **ensures** that verdict is APPROVED: if it is missing/stale/REJECTED, run `/dw-secure-audit <prd-path>` standalone, then loop back to `/dw-bugfix` per finding and re-check. SECRET findings always block (no ADR escape). Do not force a second full scan when a fresh APPROVED summary already exists.
|
|
159
160
|
|
|
160
161
|
<critical>Do not substitute `/dw-review --coverage-only` for the goal reviews. The autopilot quality goal requires full `/dw-review` before QA and after QA fixes.</critical>
|
|
161
162
|
|
|
@@ -175,6 +176,7 @@ Before `/dw-commit`, verify:
|
|
|
175
176
|
- `.dw/goals/autopilot-<prd-slug>/status.json` is complete.
|
|
176
177
|
- `<prd-path>/QA/review-consolidated.md` exists from the final post-QA review.
|
|
177
178
|
- `<prd-path>/QA/qa-report.md` and `<prd-path>/QA/bugs.md` exist.
|
|
179
|
+
- **Security Gate passed:** `.dw/secure-audit/audit-summary.md` exists, is fresh (post-last-edit), and status is APPROVED. If missing/stale/REJECTED → STOP (do not commit).
|
|
178
180
|
- `autopilot-state.json` records planning artifacts and the completed goal.
|
|
179
181
|
|
|
180
182
|
If anything is missing, STOP and re-run the missing formal command. Do not commit partial work.
|
|
@@ -114,7 +114,7 @@ Minimum files:
|
|
|
114
114
|
- `case-matrix.md`
|
|
115
115
|
- `e2e-runbook.md`
|
|
116
116
|
- `manifest.json`
|
|
117
|
-
- `scripts/*.
|
|
117
|
+
- `scripts/*.flow.mjs`
|
|
118
118
|
- `captions/*.srt`
|
|
119
119
|
|
|
120
120
|
If there is execution:
|
|
@@ -291,8 +291,16 @@ If a previous flow in the workspace already has a working shell script (e.g., `r
|
|
|
291
291
|
## Utility Scripts
|
|
292
292
|
|
|
293
293
|
Use the workspace utilities when appropriate:
|
|
294
|
-
- `node .dw/scripts/
|
|
295
|
-
- `node .dw/scripts/
|
|
294
|
+
- `node .dw/scripts/functional-doc/generate-dossier.mjs --target <URL> [--lang en|pt-br] [--project <name>] [--base-url <url>]`
|
|
295
|
+
- `node .dw/scripts/functional-doc/run-playwright-flow.mjs --flow-dir <path> [--video-resolution fullhd|1920x1080] [--list-only]`
|
|
296
|
+
|
|
297
|
+
The runner drives Playwright via the Node API and records video with `page.screencast` (the only
|
|
298
|
+
mechanism that works over CDP). It generates `scripts/<slug>.flow.mjs` — a plain ESM module exporting
|
|
299
|
+
`async function flow({ page, context, expect, baseURL, step, shot })` — not a `@playwright/test` spec,
|
|
300
|
+
so it needs no project `playwright.config.*`. The browser is chosen by `.dw/scripts/lib/resolve-browser.mjs`
|
|
301
|
+
(WSL-resilient: full headless Chromium by default; set `BROWSER_TEST` to a Windows browser exe to drive it over CDP — in NAT run `npx @brunosps00/dev-workflow setup-wsl-browser` once for the cdp-relay.exe + Hyper-V rule, mirrored networking works directly);
|
|
302
|
+
see the "Browser on WSL" section of `dw-testing-discipline/references/playwright-recipes.md`. Chromium
|
|
303
|
+
only — `screencast`/CDP do not support Firefox/WebKit.
|
|
296
304
|
|
|
297
305
|
## Completion Criteria
|
|
298
306
|
|
|
@@ -15,11 +15,11 @@ You are an assistant specialized in creating well-documented Pull Requests. Your
|
|
|
15
15
|
|-------|---------|
|
|
16
16
|
| `dw-verify` | **ALWAYS** — invoked before `git push`. Without a VERIFICATION REPORT PASS in the current session AFTER the last code edit, the PR **CANNOT** be created. |
|
|
17
17
|
| `dw-git-discipline` | **ALWAYS** — validates branch naming (`<type>/<scope>` kebab-case), atomic-commit history (each commit single-intent, conventional message), branch lifetime (flag if >7 days old), and PR scope (suggest split if diff > ~400 lines). PR description follows summary + test plan structure, not a `git log` dump. |
|
|
18
|
-
| `/dw-secure-audit` | **ALWAYS for TS/Python/C#/Rust projects** —
|
|
18
|
+
| `/dw-secure-audit` | **ALWAYS for TS/Python/C#/Rust projects** — a fresh `.dw/secure-audit/audit-summary.md` with status ≠ REJECTED is required for supported-language projects. |
|
|
19
19
|
|
|
20
20
|
<critical>Hard gate 1 (verify): if the current session has no VERIFICATION REPORT PASS from `dw-verify` produced AFTER the last edit/commit, STOP and invoke `dw-verify` before proceeding. A PR is a permanent artifact — it demands the highest verification standard.</critical>
|
|
21
21
|
|
|
22
|
-
<critical>Hard gate 2 (security): for TS/Python/C#/Rust projects, if
|
|
22
|
+
<critical>Hard gate 2 (security): for TS/Python/C#/Rust projects, if `.dw/secure-audit/audit-summary.md` is missing, stale (predates the last edit), OR has REJECTED status, STOP and invoke `/dw-secure-audit` before proceeding. SECRET findings and HIGH/CRITICAL vulnerabilities CANNOT reach the PR. For other languages (Go, Java, etc.), this gate is skipped with a note.</critical>
|
|
23
23
|
|
|
24
24
|
## Usage
|
|
25
25
|
|
|
@@ -83,7 +83,7 @@ When available under `./.agents/skills/`, these are invoked operationally:
|
|
|
83
83
|
|
|
84
84
|
1. **Pre-flight**: confirm the project dev server can run. Confirm `.dw/spec/<prd>/` has the PRD + TechSpec + tasks.
|
|
85
85
|
2. **Map FRs to test plan**: for each FR, identify the user-facing flow that exercises it.
|
|
86
|
-
3. **Drive Playwright MCP** (or
|
|
86
|
+
3. **Drive Playwright MCP** (if unavailable or blocked — common on WSL — fall back to the WSL-resilient local capture `node .dw/scripts/lib/capture-screenshots.mjs`, which picks the browser via `.dw/scripts/lib/resolve-browser.mjs`; see the "Browser on WSL" section of `dw-testing-discipline/references/playwright-recipes.md`):
|
|
87
87
|
- Happy paths for each FR.
|
|
88
88
|
- Edge cases (boundary inputs, network failure, validation errors).
|
|
89
89
|
- Negative flows (unauthorized actions, malformed input).
|
|
@@ -56,12 +56,12 @@ Use diagnostic tools based on the project's framework:
|
|
|
56
56
|
## Required Behavior
|
|
57
57
|
|
|
58
58
|
1. Identify the target: page, component, or route to be redesigned.
|
|
59
|
-
2. **AUDIT**: read the current implementation, identify the CSS stack (Tailwind, CSS Modules, styled-components, etc.), capture screenshot
|
|
59
|
+
2. **AUDIT**: read the current implementation, identify the CSS stack (Tailwind, CSS Modules, styled-components, etc.), capture the before-state screenshot (Playwright MCP, or `node .dw/scripts/lib/capture-screenshots.mjs` as the WSL-resilient fallback), run react-doctor if React project.
|
|
60
60
|
3. Ask 3 to 5 questions about redesign goals: style direction, brand constraints, inspirations, target audience, priority devices.
|
|
61
61
|
4. **PROPOSE**: present 2 to 3 design directions after passing the `dw-ui-discipline` hard-gate (brand authorities or curated defaults selected; surface job sentence written; state matrix enumerated; scene sentence written). Each direction lists color palette, typography pairing, layout style, and rationale. Self-check each direction against the 14 anti-slop patterns. For EACH direction, explicitly describe the mobile layout (<=768px) and desktop layout (>=1024px), including how elements reorganize, stack, or hide between breakpoints.
|
|
62
62
|
5. Wait for explicit user approval before implementing.
|
|
63
63
|
6. **IMPLEMENT**: apply the chosen design with a mobile-first approach — implement the mobile layout first, then add media queries/breakpoints for tablet and desktop. Respect the existing stack. Use `vercel-react-best-practices` for React/Next.js. Maintain the project's CSS methodology.
|
|
64
|
-
7. **VALIDATE**: capture after-state in BOTH resolutions (mobile and desktop), compare before/after, verify accessibility against `dw-ui-discipline/references/accessibility-floor.md` (WCAG 2.2 AA — non-negotiable: contrast, focus-visible, keyboard nav, ARIA, no traps), run react-doctor `--diff` if React.
|
|
64
|
+
7. **VALIDATE**: capture after-state in BOTH resolutions (mobile and desktop), compare before/after, verify accessibility against `dw-ui-discipline/references/accessibility-floor.md` (WCAG 2.2 AA — non-negotiable: contrast, focus-visible, keyboard nav, ARIA, no traps), run react-doctor `--diff` if React. Capture screenshots at 375px (mobile) and 1440px (desktop) — `node .dw/scripts/lib/capture-screenshots.mjs --url <url> --widths 375,1440` is the WSL-resilient path; see the "Browser on WSL" section of `dw-testing-discipline/references/playwright-recipes.md`.
|
|
65
65
|
8. **PERSIST CONTRACT**: if the user approved a direction, generate `design-contract.md` in the PRD directory (`.dw/spec/prd-[name]/design-contract.md`) with: approved direction, color palette, typography pairing, layout rules, accessibility rules, and component rules. This contract will be read by `dw-run-task` and `dw-run-plan` to ensure visual consistency.
|
|
66
66
|
|
|
67
67
|
## Codebase Intelligence
|
|
@@ -44,9 +44,10 @@ When available under `./.agents/skills/`, these are invoked as analytical suppor
|
|
|
44
44
|
|
|
45
45
|
- `dw-review-rigor`: **ALWAYS** — applies de-duplication (same pattern in N files = 1 finding), severity ordering (critical → high → medium → low), verify-before-flag, skip-what-linter-catches, and signal-over-volume. The "Issues Found" table follows this discipline.
|
|
46
46
|
- `dw-verify`: **ALWAYS** — invoked before emitting `APPROVED` or `APPROVED WITH CAVEATS`. Without a VERIFICATION REPORT PASS (test + lint + build), verdict cannot be APPROVED.
|
|
47
|
-
- `dw-secure-audit
|
|
47
|
+
- `dw-secure-audit` (**Security Gate**): **ALWAYS for TS/Python/C#/Rust projects** — triggered here and the verdict is enforced. If the project's language is supported and a fresh `.dw/secure-audit/audit-summary.md` is missing OR has REJECTED status, the review verdict is **REJECTED** — no exception. The same gate is also a standalone command (`/dw-secure-audit`) and an explicit phase in `/dw-autopilot`. It now adds Semgrep SAST (diff) + gitleaks secrets on top of OWASP/Trivy/SCA.
|
|
48
|
+
- `security-review`: the OWASP diff-level skill the gate uses (injection, authz, secrets, SSRF, crypto — HIGH CONFIDENCE only).
|
|
48
49
|
- `dw-simplification`: use when the diff touches dense or twisty code — applies Chesterton's Fence, behavior-preserving refactor protocol, complexity metrics.
|
|
49
|
-
- `dw-ui-discipline`: use when the diff touches UI — runs the 14 visual-slop patterns + accessibility floor checks.
|
|
50
|
+
- `dw-ui-discipline`: use when the diff touches UI — runs the 14 visual-slop patterns + accessibility floor checks. For a deterministic gate, also run `node .dw/scripts/lib/ui-slop-detect.mjs <changed-ui-paths> --fail-on error` (a wrapper over the impeccable detector); treat blocking findings as **REJECTED** and surface warnings in the report.
|
|
50
51
|
- `dw-testing-discipline`: use when the diff touches tests — applies the 25 anti-patterns catalog + 6 agent guardrails (when tests were agent-authored).
|
|
51
52
|
- `dw-llm-eval`: **REQUIRED when the diff touches AI/LLM feature code paths**. Reference dataset + ≥2 oracle rungs + judge calibration (if rung 4 used) + eval run results MUST be in the PR. Missing → REJECTED.
|
|
52
53
|
- `security-review`: use when the diff touches auth, authorization, external input, upload, SQL, secrets, SSRF, XSS, or sensitive surfaces.
|
|
@@ -161,9 +162,10 @@ If MISSING > 0, the verdict suggests revisiting `/dw-plan tasks` to scope or `/d
|
|
|
161
162
|
- Run dw-verify to produce a VERIFICATION REPORT (test + lint + build all GREEN).
|
|
162
163
|
- Without PASS, verdict cannot be APPROVED.
|
|
163
164
|
|
|
164
|
-
8. **Security
|
|
165
|
-
-
|
|
166
|
-
- If language is supported and audit is missing OR REJECTED → verdict **REJECTED**.
|
|
165
|
+
8. **Security Gate (`dw-secure-audit` for TS/Python/C#/Rust):**
|
|
166
|
+
- Trigger `/dw-secure-audit` against the diff (OWASP + Semgrep SAST + gitleaks + Trivy/SCA + supply-chain). It produces/refreshes `.dw/secure-audit/audit-summary.md`.
|
|
167
|
+
- Latest scan must be present, fresh (post-last-edit), and not REJECTED. If language is supported and the audit is missing OR REJECTED → review verdict **REJECTED**. SECRET findings always block (no ADR escape).
|
|
168
|
+
- The same gate is also runnable standalone (`/dw-secure-audit`) and is an explicit phase in `/dw-autopilot`; `/dw-generate-pr` re-enforces the verdict before the PR.
|
|
167
169
|
|
|
168
170
|
### Output
|
|
169
171
|
|