@brunosps00/dev-workflow 1.4.0 → 1.6.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 +1 -1
- package/README.md +6 -5
- package/lib/constants.js +6 -4
- package/lib/hooks.js +53 -11
- package/lib/init.js +49 -1
- package/package.json +4 -2
- package/scaffold/config/stack-mappings.json +40 -0
- package/scaffold/en/commands/dw-adr.md +49 -11
- package/scaffold/en/commands/dw-analyze-project.md +10 -1
- package/scaffold/en/commands/dw-brainstorm.md +103 -32
- package/scaffold/en/commands/dw-claude-run.md +8 -5
- package/scaffold/en/commands/dw-context-budget.md +9 -0
- package/scaffold/en/commands/dw-harness-audit.md +3 -0
- package/scaffold/en/commands/dw-learn.md +41 -0
- package/scaffold/en/commands/dw-plan.md +36 -5
- package/scaffold/en/commands/dw-review.md +1 -0
- package/scaffold/en/commands/dw-run.md +1 -0
- package/scaffold/en/templates/adr-template.md +8 -4
- package/scaffold/en/templates/idea-onepager.md +44 -2
- package/scaffold/pt-br/commands/dw-adr.md +49 -11
- package/scaffold/pt-br/commands/dw-analyze-project.md +10 -1
- package/scaffold/pt-br/commands/dw-brainstorm.md +105 -32
- package/scaffold/pt-br/commands/dw-claude-run.md +8 -5
- package/scaffold/pt-br/commands/dw-context-budget.md +9 -0
- package/scaffold/pt-br/commands/dw-harness-audit.md +3 -0
- package/scaffold/pt-br/commands/dw-learn.md +41 -0
- package/scaffold/pt-br/commands/dw-plan.md +36 -5
- package/scaffold/pt-br/commands/dw-review.md +1 -0
- package/scaffold/pt-br/commands/dw-run.md +1 -0
- package/scaffold/pt-br/templates/adr-template.md +8 -4
- package/scaffold/pt-br/templates/idea-onepager.md +44 -2
- package/scaffold/rules/README.md +22 -0
- package/scaffold/rules/common.md +29 -0
- package/scaffold/rules/csharp.md +18 -0
- package/scaffold/rules/python.md +18 -0
- package/scaffold/rules/react.md +18 -0
- package/scaffold/rules/rust.md +18 -0
- package/scaffold/rules/typescript.md +23 -0
- package/scaffold/rules-readme.md +8 -0
- package/scaffold/scripts/hooks/session-cost.mjs +126 -0
- package/scaffold/scripts/hooks/statusline.mjs +31 -0
- package/scaffold/scripts/lib/model-prices.json +12 -0
- package/scaffold/skill-registry.json +25 -1
- package/scaffold/skills/dw-cli-run/SKILL.md +13 -9
- package/scaffold/skills/dw-codebase-intel/SKILL.md +3 -1
- package/scaffold/skills/dw-debug-protocol/SKILL.md +4 -0
- package/scaffold/skills/dw-debug-protocol/references/agent-degradation.md +30 -0
- package/scaffold/skills/dw-domain-modeling/SKILL.md +84 -0
- package/scaffold/skills/dw-domain-modeling/references/adr-policy.md +48 -0
- package/scaffold/skills/dw-domain-modeling/references/glossary-format.md +66 -0
- package/scaffold/skills/dw-execute-phase/SKILL.md +13 -0
- package/scaffold/skills/dw-git-discipline/SKILL.md +1 -0
- package/scaffold/skills/dw-grilling/SKILL.md +98 -0
- package/scaffold/skills/dw-grilling/references/decision-tree.md +56 -0
- package/scaffold/skills/dw-grilling/references/interview-loop.md +52 -0
- package/scaffold/skills/dw-llm-eval/SKILL.md +12 -0
- package/scaffold/skills/dw-memory/SKILL.md +12 -1
- package/scaffold/skills/dw-memory/references/instincts.md +45 -0
- package/scaffold/skills/dw-review-rigor/SKILL.md +12 -0
- package/scaffold/skills/dw-review-rigor/references/false-positives.md +21 -0
- package/scaffold/skills/dw-review-rigor/references/self-eval-rubric.md +38 -0
- package/scaffold/skills/dw-silent-failure/SKILL.md +4 -2
- package/scaffold/skills/dw-simplification/SKILL.md +13 -0
- package/scaffold/skills/dw-simplification/references/dead-code-tools.md +23 -0
- package/scaffold/skills/dw-testing-discipline/SKILL.md +17 -0
- package/scaffold/skills/dw-ui-discipline/SKILL.md +1 -1
- package/scaffold/skills/dw-verify/SKILL.md +1 -1
- package/scaffold/skills/dw-verify/references/pre-check-and-status.md +28 -0
|
@@ -1,7 +1,7 @@
|
|
|
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": "1.
|
|
4
|
+
"version": "1.6.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Bruno Santos"
|
|
7
7
|
},
|
package/README.md
CHANGED
|
@@ -12,11 +12,11 @@ This will:
|
|
|
12
12
|
1. Ask you to select a language (English or Portuguese)
|
|
13
13
|
2. Create `.dw/commands/` with workflow commands
|
|
14
14
|
3. Create `.dw/templates/` with document templates (PRD, TechSpec, Tasks, ADR, etc.)
|
|
15
|
-
4. Create `.dw/rules/` (populated by `/dw-analyze-project`)
|
|
15
|
+
4. Create `.dw/rules/` (populated by `/dw-analyze-project`) + a curated `.dw/rules-library/` declarative baseline per stack (loaded lazily via `.dw/config/stack-mappings.json`)
|
|
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
17
|
6. Generate skill wrappers and project agents for Claude Code, Codex, Copilot, and OpenCode
|
|
18
18
|
7. Configure MCP servers (Context7 + Playwright)
|
|
19
|
-
8. Install enforcement hooks (git guardrails) + a statusline into `.claude/settings.json` (merge-aware — your own hooks/statusline are never overwritten)
|
|
19
|
+
8. Install enforcement hooks (git guardrails + a `SessionEnd` token-cost tracker → `.dw/metrics/costs.jsonl`) + a statusline (branch · active spec · minimalism mode · today's estimated spend) into `.claude/settings.json` (merge-aware — your own hooks/statusline are never overwritten)
|
|
20
20
|
|
|
21
21
|
> **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.
|
|
22
22
|
|
|
@@ -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 v1.
|
|
45
|
+
dev-workflow v1.6.0 ships **37 commands** organized into four tiers. Most users only invoke Tier 1 + Tier 2.
|
|
46
46
|
|
|
47
47
|
### Tier 1 — Gateway (3)
|
|
48
48
|
|
|
@@ -69,7 +69,7 @@ Use these when you want step-by-step control instead of `/dw-autopilot`.
|
|
|
69
69
|
| **`/dw-commit`** | Atomic Conventional Commits for pending changes. Applies `dw-git-discipline` (one intent per commit, lint+tests+build green before). |
|
|
70
70
|
| **`/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. |
|
|
71
71
|
|
|
72
|
-
### Tier 3 — Specialty (
|
|
72
|
+
### Tier 3 — Specialty (12)
|
|
73
73
|
|
|
74
74
|
| Command | What |
|
|
75
75
|
|---------|------|
|
|
@@ -80,6 +80,7 @@ Use these when you want step-by-step control instead of `/dw-autopilot`.
|
|
|
80
80
|
| **`/dw-context-budget`** | Audits context overhead from commands, skills, agents, instruction files, and MCPs. |
|
|
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
|
+
| **`/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**. |
|
|
83
84
|
| **`/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/`. |
|
|
84
85
|
| **`/dw-dockerize`** | Reads existing project, detects stack + runtime deps, proposes Dockerfile + docker-compose for dev/prod with explicit trade-offs (Conservative/Balanced/Bold). |
|
|
85
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`. |
|
|
@@ -376,7 +377,7 @@ Optional Azure integration (v1.0.3). The `/dw-install-azure-skills` command and
|
|
|
376
377
|
|
|
377
378
|
Session continuity and adaptive routing patterns adapted from [`tech-leads-club/agent-skills/tlc-spec-driven`](https://github.com/tech-leads-club/agent-skills/tree/main/packages/skills-catalog/skills/(development)/tlc-spec-driven) by Felipe Rodrigues (CC-BY-4.0, v1.0.2). Eight patterns were absorbed selectively after a comparative analysis confirmed that the majority of the skill duplicates existing dev-workflow capabilities (PRD/TechSpec/Tasks pipeline, constitution discipline, source-grounding, two-tier memory, verify-before-complete, brownfield mapping, sub-agent delegation, atomic commits). Patterns adopted: (1) `STATE.md` cross-session working memory at `.dw/STATE.md` + new `/dw-pause` and `/dw-resume` commands; (2) Auto-Sizing Matrix (Small/Medium/Large/Complex) formalized in `CLAUDE.md`/`AGENTS.md` above the Trigger Map; (3) Concerns Map (`.dw/rules/concerns.md`) generated by a new Step 9 in `/dw-analyze-project` and consumed on-demand by `/dw-plan`, `/dw-run`, and `/dw-bugfix`; (4) Context Budget discipline as a new section in `dw-memory` with reference `dw-memory/references/context-budget.md`; (5) Interactive UAT walkthrough as `/dw-qa --uat`; (6) Quick-mode persistence — bugfixes now land in `.dw/bugfixes/NNN-<slug>/{TASK.md, SUMMARY.md, fix-report.md}` and remain queryable via `/dw-intel`; (7) Safety valve in `/dw-bugfix` Step 5.0 that forces escalation to `/dw-plan` when scope exceeds 5 tasks or has cross-dependencies; (8) Cross-skill awareness — `/dw-intel --build` now indexes `.dw/bugfixes/*/SUMMARY.md` into `bugfixes.json`, and `dw-codebase-intel` documents the new `bugfix-history` and `risk-area` query shapes. Patterns explicitly REJECTED: `.specs/` directory structure (dev-workflow uses `.dw/`), Knowledge Verification Chain (already covered by `dw-source-grounding`), Specify/Design/Tasks/Execute naming (dev-workflow keeps PRD/TechSpec/Tasks/Run), Skill Integrations pattern with mermaid-studio/codenavi delegation, and literal text copying (everything is clean-room reimplementation from the conceptual patterns; CC-BY-4.0 attribution is for derivative ideas, not borrowed prose).
|
|
378
379
|
|
|
379
|
-
|
|
380
|
+
Patterns from [`mattpocock/skills`](https://github.com/mattpocock/skills) by Matt Pocock (MIT) were integrated **without adding any new public command** (the public command count is unchanged): (1) **grill** — a native, stateful alignment session reimplemented (clean-room, no upstream prose copied) from [`skills/engineering/grill-with-docs`](https://github.com/mattpocock/skills/blob/main/skills/engineering/grill-with-docs/SKILL.md), [`skills/productivity/grilling`](https://github.com/mattpocock/skills/blob/main/skills/productivity/grilling/SKILL.md), and [`skills/engineering/domain-modeling`](https://github.com/mattpocock/skills/blob/main/skills/engineering/domain-modeling/SKILL.md). It is the `/dw-brainstorm` `grill` mode, backed by two **internal, non-exported** bundled skills — `dw-grilling` (dependency-ordered decision-tree interview, one decision per turn with a recommended answer, facts looked up rather than asked, shared-understanding gate) and `dw-domain-modeling` (canonical glossary, fuzzy/overloaded-term challenge, rare ADRs). Intentional `.dw/` differences: the curated glossary lives in **`.dw/domain/**`** (not upstream's root `CONTEXT.md`, and not our auto-generated `.dw/rules/`); Grill requires **one explicit authorization** before it writes and is mutually exclusive with the option matrix; alignment emits an idea one-pager at **schema `1.1`** consumed by `/dw-plan` without re-asking; and ADR creation is gated on the 3-criteria test and routed via `/dw-adr --scope=repo|prd`. (2) **prototype** → `/dw-brainstorm` `prototype` mode (LOGIC terminal app or UI variant dispatch); (3) **improve-codebase-architecture** → `dw-simplification/references/deep-modules.md` (deletion test, locality, leverage, seam, adapter diagnostic invoked by the `refactor-audit` mode); (4) **zoom-out** → one-paragraph guidance in `agent-instructions.md`. The same line of work also collapses `/dw-brainstorm`'s six legacy flags into a single full-flow entry point that auto-dispatches modes based on project signals.
|
|
380
381
|
|
|
381
382
|
Opportunity discovery and the explicit `/dw-refactor` surface were inspired by patterns observed in [`pedronauck/skills`](https://github.com/pedronauck/skills), especially `game-changing-features` (10x opportunity framing) and `refactoring-analysis` (Fowler-smell prioritization). dev-workflow does not install or depend on that repository at runtime, and the command text here is a clean-room adaptation of the workflow shape rather than copied skill content.
|
|
382
383
|
|
package/lib/constants.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
const COMMANDS = {
|
|
2
2
|
en: [
|
|
3
|
-
{ name: 'dw-adr', description: 'Records an architectural decision and the trade-offs accepted, before they get lost.' },
|
|
3
|
+
{ name: 'dw-adr', description: 'Records an architectural decision and the trade-offs accepted, before they get lost. --scope=repo writes .dw/adrs/ (works before any PRD); --scope=prd writes under the active PRD. Gated on hard-to-reverse + surprising + genuine trade-off.' },
|
|
4
4
|
{ name: 'dw-analyze-project', description: 'Scans the repo to learn its stack and conventions, then writes the rules other commands rely on.' },
|
|
5
5
|
{ name: 'dw-autopilot', description: 'Trigger when user asks to implement, build, create, or add a feature non-trivially. First invocation plans and stops; second invocation resumes via dw-goal, then commit and PR.' },
|
|
6
|
-
{ name: 'dw-brainstorm', description: 'Refine a concrete idea against the product\'s existing features.
|
|
6
|
+
{ name: 'dw-brainstorm', description: 'Refine a concrete idea against the product\'s existing features. Auto-dispatches internal modes via --mode= (option-matrix / grill / prototype / council / research / refactor-audit / onepager). Grill is a native stateful alignment session (a direct grill-me phrase or --mode=grill) that writes canonical vocabulary to .dw/domain/. Use dw-opportunities before you have an idea and dw-refactor for code-health audits.' },
|
|
7
7
|
{ name: 'dw-bugfix', description: 'Trigger when user reports a bug, pastes an error, or describes broken behavior. Triages with three questions, then fixes or routes to PRD.' },
|
|
8
8
|
{ name: 'dw-claude-run', userInvoked: true, description: 'Trigger when user asks to run/fire Claude (claude -p headless) in a dedicated worktree to implement a prepared prompt/spec. Claude adapter over the dw-cli-run protocol: durable audit log, resumable session via --session-id, 0-10 dual evaluation, STOP for the gate. Never the main checkout; never merges.' },
|
|
9
9
|
{ name: 'dw-codex-run', userInvoked: true, description: 'Trigger when user asks to run/fire Codex (codex exec) in a dedicated worktree to implement a prepared prompt/spec. Codex adapter over the dw-cli-run protocol: durable audit log, resumable per-task session, 0-10 dual evaluation, STOP for the gate. Never the main checkout; never merges.' },
|
|
@@ -20,6 +20,7 @@ const COMMANDS = {
|
|
|
20
20
|
{ name: 'dw-install-aws-skills', description: 'Trigger when user asks to install AWS expertise, setup AWS MCP server, or add AWS agent skills. Opt-in: clones curated skills from aws/agent-toolkit-for-aws into .agents/skills/aws/ and registers the unified AWS MCP Server (stdio via mcp-proxy-for-aws). Requires uv, aws cli, and AWS credentials.' },
|
|
21
21
|
{ name: 'dw-install-azure-skills', description: 'Trigger when user asks to install Azure expertise, setup Microsoft docs MCP, or add Azure agent skills. Opt-in: clones curated skills from MicrosoftDocs/Agent-Skills into .agents/skills/azure/ and registers the Microsoft Learn MCP server.' },
|
|
22
22
|
{ name: 'dw-intel', description: 'Codebase intelligence: query mode (default) answers questions citing .dw/intel/ + .dw/rules/; --build mode (re)builds the index.' },
|
|
23
|
+
{ name: 'dw-learn', description: 'Synthesizes durable decisions, bugfixes, deviations, and git history into atomic confidence-weighted instincts you approve; can propose constitution principles. On-demand and human-in-the-loop — no always-on observer.' },
|
|
23
24
|
{ name: 'dw-new-project', description: 'Interviews you about stack and infra, then scaffolds a working monorepo with docker-compose for dev, .env, scripts, CI, and seeded rules.' },
|
|
24
25
|
{ name: 'dw-opportunities', description: 'Scans the installed project for product, UX, automation, refactor, and security opportunities, then routes each idea to the right next dw-* command.' },
|
|
25
26
|
{ name: 'dw-pause', description: 'Trigger when user says "pause work", "end session", or "save where we are". Consolidates open loops, decisions, blockers, and todos into .dw/STATE.md so the next session can resume.' },
|
|
@@ -38,10 +39,10 @@ const COMMANDS = {
|
|
|
38
39
|
{ name: 'dw-update', description: 'Updates dev-workflow to the latest npm release in-place, with a snapshot you can roll back to.' },
|
|
39
40
|
],
|
|
40
41
|
'pt-br': [
|
|
41
|
-
{ name: 'dw-adr', description: 'Registra uma decisao arquitetural e os trade-offs aceitos, antes que se percam.' },
|
|
42
|
+
{ name: 'dw-adr', description: 'Registra uma decisao arquitetural e os trade-offs aceitos, antes que se percam. --scope=repo escreve em .dw/adrs/ (funciona antes de qualquer PRD); --scope=prd escreve sob o PRD ativo. Gated em dificil-de-reverter + surpreendente + trade-off real.' },
|
|
42
43
|
{ name: 'dw-analyze-project', description: 'Escaneia o repo para aprender stack e convencoes, e escreve as regras que os outros commands usam.' },
|
|
43
44
|
{ name: 'dw-autopilot', description: 'Trigger quando usuario pede pra implementar, criar ou adicionar uma feature nao-trivial. Primeira invocacao planeja e para; segunda retoma via dw-goal, depois commit e PR.' },
|
|
44
|
-
{ name: 'dw-brainstorm', description: 'Refina uma ideia concreta contra features existentes do produto.
|
|
45
|
+
{ name: 'dw-brainstorm', description: 'Refina uma ideia concreta contra features existentes do produto. Auto-dispatch de modos internos via --mode= (option-matrix / grill / prototype / council / research / refactor-audit / onepager). Grill e uma sessao nativa de alinhamento com estado (frase direta tipo me-questione ou --mode=grill) que escreve vocabulario canonico em .dw/domain/. Use dw-opportunities antes de ter uma ideia e dw-refactor para auditoria de code health.' },
|
|
45
46
|
{ name: 'dw-bugfix', description: 'Trigger quando usuario reporta bug, cola erro ou descreve comportamento quebrado. Tria com tres perguntas, depois corrige ou roteia pra PRD.' },
|
|
46
47
|
{ name: 'dw-claude-run', userInvoked: true, description: 'Trigger quando usuario pede pra rodar/disparar o Claude (claude -p headless) numa worktree dedicada pra implementar um prompt/spec preparado. Adapter Claude sobre o protocolo dw-cli-run: log de auditoria duravel, sessao resumivel via --session-id, dupla avaliacao 0-10, PARA pro gate. Nunca no checkout principal; nunca mergeia.' },
|
|
47
48
|
{ name: 'dw-codex-run', userInvoked: true, description: 'Trigger quando usuario pede pra rodar/disparar o Codex (codex exec) numa worktree dedicada pra implementar um prompt/spec preparado. Adapter Codex sobre o protocolo dw-cli-run: log de auditoria duravel, sessao resumivel por tarefa, dupla avaliacao 0-10, PARA pro gate. Nunca no checkout principal; nunca mergeia.' },
|
|
@@ -58,6 +59,7 @@ const COMMANDS = {
|
|
|
58
59
|
{ name: 'dw-install-aws-skills', description: 'Trigger quando usuario pede pra instalar expertise AWS, configurar MCP da AWS, ou adicionar agent skills AWS. Opt-in: clona skills curadas de aws/agent-toolkit-for-aws para .agents/skills/aws/ e registra o AWS MCP Server unificado (stdio via mcp-proxy-for-aws). Requer uv, aws cli e credenciais AWS.' },
|
|
59
60
|
{ name: 'dw-install-azure-skills', description: 'Trigger quando usuario pede pra instalar expertise Azure, configurar MCP do Microsoft docs, ou adicionar agent skills Azure. Opt-in: clona skills curadas de MicrosoftDocs/Agent-Skills para .agents/skills/azure/ e registra o Microsoft Learn MCP server.' },
|
|
60
61
|
{ name: 'dw-intel', description: 'Inteligencia do codebase: modo query (default) responde citando .dw/intel/ + .dw/rules/; modo --build (re)constroi indice.' },
|
|
62
|
+
{ name: 'dw-learn', description: 'Sintetiza decisoes duraveis, bugfixes, deviations e historico git em instincts atomicos ponderados por confianca que voce aprova; pode propor principios de constitution. On-demand e human-in-the-loop — sem observador sempre-ligado.' },
|
|
61
63
|
{ name: 'dw-new-project', description: 'Entrevista voce sobre stack e infra, depois faz scaffold de um monorepo com docker-compose para dev, .env, scripts, CI e rules seed.' },
|
|
62
64
|
{ name: 'dw-opportunities', description: 'Escaneia o projeto instalado por oportunidades de produto, UX, automacao, refactor e seguranca, e roteia cada ideia para o proximo comando dw-* correto.' },
|
|
63
65
|
{ name: 'dw-pause', description: 'Trigger quando usuario diz "pausa o trabalho", "encerra a sessao" ou "salva onde paramos". Consolida pontas soltas, decisoes, bloqueios e todos em .dw/STATE.md para a proxima sessao retomar.' },
|
package/lib/hooks.js
CHANGED
|
@@ -7,6 +7,8 @@ const HOOKS_DIR_MARKER = '.dw/scripts/hooks/';
|
|
|
7
7
|
const GIT_GUARDRAILS_CMD = 'node .dw/scripts/hooks/git-guardrails.mjs';
|
|
8
8
|
const STATUSLINE_CMD = 'node .dw/scripts/hooks/statusline.mjs';
|
|
9
9
|
const GIT_GUARDRAILS_SCRIPT = 'git-guardrails.mjs';
|
|
10
|
+
const SESSION_COST_CMD = 'node .dw/scripts/hooks/session-cost.mjs';
|
|
11
|
+
const SESSION_COST_SCRIPT = 'session-cost.mjs';
|
|
10
12
|
|
|
11
13
|
function isOurs(command) {
|
|
12
14
|
return typeof command === 'string' && command.includes(HOOKS_DIR_MARKER);
|
|
@@ -31,13 +33,48 @@ function installHooks(projectRoot) {
|
|
|
31
33
|
const before = JSON.stringify(settings);
|
|
32
34
|
|
|
33
35
|
const hooksResult = reconcilePreToolUseGitGuardrails(settings);
|
|
36
|
+
const sessionCostResult = reconcileSessionEndCost(settings);
|
|
34
37
|
const statusLineResult = reconcileStatusLine(settings);
|
|
35
38
|
|
|
36
39
|
if (JSON.stringify(settings) !== before) {
|
|
37
40
|
writeSettings(projectRoot, settings);
|
|
38
41
|
}
|
|
39
42
|
|
|
40
|
-
return { hooks: hooksResult, statusLine: statusLineResult };
|
|
43
|
+
return { hooks: hooksResult, sessionCost: sessionCostResult, statusLine: statusLineResult };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Reconcile the SessionEnd cost-tracking hook (marker-based, merge-aware — same
|
|
48
|
+
* contract as the git guardrail). No matcher: fires on every session end.
|
|
49
|
+
* Returns 'added' | 'updated' | 'unchanged'.
|
|
50
|
+
*/
|
|
51
|
+
function reconcileSessionEndCost(settings) {
|
|
52
|
+
if (!settings.hooks || typeof settings.hooks !== 'object') settings.hooks = {};
|
|
53
|
+
if (!Array.isArray(settings.hooks.SessionEnd)) settings.hooks.SessionEnd = [];
|
|
54
|
+
|
|
55
|
+
const groups = settings.hooks.SessionEnd;
|
|
56
|
+
|
|
57
|
+
const existed = groups.some(
|
|
58
|
+
(g) => g && Array.isArray(g.hooks) && g.hooks.some((h) => h && typeof h.command === 'string' && h.command.includes(SESSION_COST_SCRIPT)),
|
|
59
|
+
);
|
|
60
|
+
const exactPresent = groups.some(
|
|
61
|
+
(g) => g && Array.isArray(g.hooks) && g.hooks.some((h) => h && h.command === SESSION_COST_CMD),
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
if (exactPresent) return 'unchanged';
|
|
65
|
+
|
|
66
|
+
// Drop any stale/relocated copies of OUR hook, preserving user hooks.
|
|
67
|
+
for (const group of groups) {
|
|
68
|
+
if (!group || !Array.isArray(group.hooks)) continue;
|
|
69
|
+
group.hooks = group.hooks.filter(
|
|
70
|
+
(h) => !(h && typeof h.command === 'string' && h.command.includes(SESSION_COST_SCRIPT)),
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
settings.hooks.SessionEnd = groups.filter((g) => g && Array.isArray(g.hooks) && g.hooks.length > 0);
|
|
74
|
+
|
|
75
|
+
settings.hooks.SessionEnd.push({ hooks: [{ type: 'command', command: SESSION_COST_CMD }] });
|
|
76
|
+
|
|
77
|
+
return existed ? 'updated' : 'added';
|
|
41
78
|
}
|
|
42
79
|
|
|
43
80
|
function reconcilePreToolUseGitGuardrails(settings) {
|
|
@@ -105,17 +142,21 @@ function removeHooks(projectRoot) {
|
|
|
105
142
|
const settings = readSettings(projectRoot);
|
|
106
143
|
let removed = 0;
|
|
107
144
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
145
|
+
// Remove OUR hook entries from every event (PreToolUse, SessionEnd, PostToolUse, …),
|
|
146
|
+
// identified by the .dw/scripts/hooks/ marker; never touch user-added hooks.
|
|
147
|
+
if (settings.hooks && typeof settings.hooks === 'object') {
|
|
148
|
+
for (const event of Object.keys(settings.hooks)) {
|
|
149
|
+
const groups = settings.hooks[event];
|
|
150
|
+
if (!Array.isArray(groups)) continue;
|
|
151
|
+
for (const group of groups) {
|
|
152
|
+
if (!group || !Array.isArray(group.hooks)) continue;
|
|
153
|
+
const kept = group.hooks.filter((h) => !(h && isOurs(h.command)));
|
|
154
|
+
removed += group.hooks.length - kept.length;
|
|
155
|
+
group.hooks = kept;
|
|
156
|
+
}
|
|
157
|
+
settings.hooks[event] = groups.filter((g) => g && Array.isArray(g.hooks) && g.hooks.length > 0);
|
|
158
|
+
if (settings.hooks[event].length === 0) delete settings.hooks[event];
|
|
114
159
|
}
|
|
115
|
-
settings.hooks.PreToolUse = settings.hooks.PreToolUse.filter(
|
|
116
|
-
(g) => g && Array.isArray(g.hooks) && g.hooks.length > 0,
|
|
117
|
-
);
|
|
118
|
-
if (settings.hooks.PreToolUse.length === 0) delete settings.hooks.PreToolUse;
|
|
119
160
|
if (Object.keys(settings.hooks).length === 0) delete settings.hooks;
|
|
120
161
|
}
|
|
121
162
|
|
|
@@ -134,4 +175,5 @@ module.exports = {
|
|
|
134
175
|
HOOKS_DIR_MARKER,
|
|
135
176
|
GIT_GUARDRAILS_CMD,
|
|
136
177
|
STATUSLINE_CMD,
|
|
178
|
+
SESSION_COST_CMD,
|
|
137
179
|
};
|
package/lib/init.js
CHANGED
|
@@ -170,6 +170,30 @@ async function run({ force = false, lang = null, mode = 'init', profile = null,
|
|
|
170
170
|
console.log();
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
+
// 3.9. Copy curated rules library + stack mappings (declarative baseline per stack,
|
|
174
|
+
// loaded lazily by the detected stack). Managed: reconciled on update/repair.
|
|
175
|
+
const rulesLibSrc = path.join(SCAFFOLD_DIR, 'rules');
|
|
176
|
+
if (require('fs').existsSync(rulesLibSrc)) {
|
|
177
|
+
console.log(' Rules library:');
|
|
178
|
+
const rlResults = copyDir(rulesLibSrc, path.join(projectRoot, '.dw', 'rules-library'), managedForce);
|
|
179
|
+
totalCreated += rlResults.created;
|
|
180
|
+
totalSkipped += rlResults.skipped;
|
|
181
|
+
totalOverwritten += rlResults.overwritten;
|
|
182
|
+
touchedFiles.push(...listFilesRecursive(path.join(projectRoot, '.dw', 'rules-library')));
|
|
183
|
+
console.log(` ${rlResults.created} created, ${rlResults.skipped} skipped, ${rlResults.overwritten} overwritten\n`);
|
|
184
|
+
}
|
|
185
|
+
const stackMapSrc = path.join(SCAFFOLD_DIR, 'config', 'stack-mappings.json');
|
|
186
|
+
if (require('fs').existsSync(stackMapSrc)) {
|
|
187
|
+
const cfgDir = path.join(projectRoot, '.dw', 'config');
|
|
188
|
+
ensureDir(cfgDir);
|
|
189
|
+
const stackMapDest = path.join(cfgDir, 'stack-mappings.json');
|
|
190
|
+
const smStatus = writeFile(stackMapDest, require('fs').readFileSync(stackMapSrc, 'utf-8'), managedForce);
|
|
191
|
+
if (smStatus === 'created') totalCreated++;
|
|
192
|
+
else if (smStatus === 'overwritten') totalOverwritten++;
|
|
193
|
+
else totalSkipped++;
|
|
194
|
+
touchedFiles.push(stackMapDest);
|
|
195
|
+
}
|
|
196
|
+
|
|
173
197
|
// 4. Create .dw/rules/ with README
|
|
174
198
|
if (!isUpdate) {
|
|
175
199
|
console.log(' Rules:');
|
|
@@ -233,6 +257,30 @@ async function run({ force = false, lang = null, mode = 'init', profile = null,
|
|
|
233
257
|
touchedFiles.push(gitkeepPath);
|
|
234
258
|
}
|
|
235
259
|
|
|
260
|
+
// 5.25. Ensure .dw/metrics/ + .gitignore (runtime cost tracking; costs.jsonl is
|
|
261
|
+
// machine-local so it is gitignored). Created if missing on both init and update.
|
|
262
|
+
{
|
|
263
|
+
const metricsDir = path.join(projectRoot, '.dw', 'metrics');
|
|
264
|
+
ensureDir(metricsDir);
|
|
265
|
+
const metricsGitignore = path.join(metricsDir, '.gitignore');
|
|
266
|
+
const mStatus = writeFile(metricsGitignore, 'costs.jsonl\n', false);
|
|
267
|
+
if (mStatus === 'created') totalCreated++;
|
|
268
|
+
else totalSkipped++;
|
|
269
|
+
touchedFiles.push(metricsGitignore);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// 5.26. Ensure .dw/memory/instincts/ (durable learnings promoted by /dw-learn;
|
|
273
|
+
// format in the dw-memory skill's references/instincts.md). Init only; preserved on update.
|
|
274
|
+
if (!isUpdate) {
|
|
275
|
+
const instinctsDir = path.join(projectRoot, '.dw', 'memory', 'instincts');
|
|
276
|
+
ensureDir(instinctsDir);
|
|
277
|
+
const instinctsKeep = path.join(instinctsDir, '.gitkeep');
|
|
278
|
+
const ikStatus = writeFile(instinctsKeep, '', false);
|
|
279
|
+
if (ikStatus === 'created') totalCreated++;
|
|
280
|
+
else totalSkipped++;
|
|
281
|
+
touchedFiles.push(instinctsKeep);
|
|
282
|
+
}
|
|
283
|
+
|
|
236
284
|
// 5.3. Create local ephemeral subtask handoff directories.
|
|
237
285
|
ensureSubtaskLayout(projectRoot);
|
|
238
286
|
touchedFiles.push(path.join(projectRoot, '.dw', 'subtasks', '.gitignore'));
|
|
@@ -317,7 +365,7 @@ async function run({ force = false, lang = null, mode = 'init', profile = null,
|
|
|
317
365
|
// refreshes our entries, never touches user-defined hooks/statusLine).
|
|
318
366
|
console.log(' Hooks & statusline:');
|
|
319
367
|
const hookResults = installHooks(projectRoot);
|
|
320
|
-
console.log(` git-guardrails: ${hookResults.hooks}, statusline: ${hookResults.statusLine}\n`);
|
|
368
|
+
console.log(` git-guardrails: ${hookResults.hooks}, session-cost: ${hookResults.sessionCost}, statusline: ${hookResults.statusLine}\n`);
|
|
321
369
|
if (hookResults.statusLine === 'skipped-user') {
|
|
322
370
|
console.log(' Note: a custom statusLine is set; to show dev-workflow state add `node .dw/scripts/hooks/statusline.mjs`.\n');
|
|
323
371
|
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brunosps00/dev-workflow",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.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"
|
|
7
7
|
},
|
|
8
8
|
"scripts": {
|
|
9
|
+
"test": "node --test test/*.test.js",
|
|
9
10
|
"validate": "node lib/validate.js",
|
|
10
|
-
"build:plugin": "node lib/build-plugin.js"
|
|
11
|
+
"build:plugin": "node lib/build-plugin.js",
|
|
12
|
+
"pack:check": "npm pack --dry-run"
|
|
11
13
|
},
|
|
12
14
|
"files": [
|
|
13
15
|
"bin/",
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_note": "Maps a detected stack to its curated baseline rule files (in .dw/rules-library/), relevant bundled skills, and safe default permissions. Consumed by /dw-analyze-project (detect + seed constitution) and /dw-review (declarative bar). Load ONLY the active stack's rules — never the whole library. Indicators: a bare filename means 'file exists'; 'file:substring' means the file contains the substring.",
|
|
3
|
+
"stacks": [
|
|
4
|
+
{
|
|
5
|
+
"id": "typescript",
|
|
6
|
+
"indicators": ["tsconfig.json", "package.json:typescript"],
|
|
7
|
+
"rules": ["common", "typescript"],
|
|
8
|
+
"skills": ["dw-testing-discipline", "dw-simplification"],
|
|
9
|
+
"permissions": { "allow": ["npx tsc", "npx eslint", "npm test", "pnpm test"], "deny": ["npm publish"] }
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"id": "react",
|
|
13
|
+
"indicators": ["package.json:react"],
|
|
14
|
+
"rules": ["common", "typescript", "react"],
|
|
15
|
+
"skills": ["dw-ui-discipline", "vercel-react-best-practices", "dw-testing-discipline"],
|
|
16
|
+
"permissions": { "allow": ["npm test", "pnpm test", "npx vitest"], "deny": [] }
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": "python",
|
|
20
|
+
"indicators": ["pyproject.toml", "requirements.txt", "setup.py"],
|
|
21
|
+
"rules": ["common", "python"],
|
|
22
|
+
"skills": ["dw-testing-discipline", "dw-silent-failure"],
|
|
23
|
+
"permissions": { "allow": ["pytest", "ruff", "mypy"], "deny": [] }
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"id": "rust",
|
|
27
|
+
"indicators": ["Cargo.toml"],
|
|
28
|
+
"rules": ["common", "rust"],
|
|
29
|
+
"skills": ["dw-testing-discipline"],
|
|
30
|
+
"permissions": { "allow": ["cargo test", "cargo clippy", "cargo check"], "deny": [] }
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"id": "csharp",
|
|
34
|
+
"indicators": [".csproj", ".sln"],
|
|
35
|
+
"rules": ["common", "csharp"],
|
|
36
|
+
"skills": ["dw-testing-discipline"],
|
|
37
|
+
"permissions": { "allow": ["dotnet test", "dotnet build"], "deny": [] }
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|
|
@@ -1,36 +1,71 @@
|
|
|
1
1
|
<system_instructions>
|
|
2
|
-
You are an architectural-decision recorder. Your job is to create an **Architecture Decision Record (ADR)** documenting an important technical decision
|
|
2
|
+
You are an architectural-decision recorder. Your job is to create an **Architecture Decision Record (ADR)** documenting an important technical decision — either repo-wide (`--scope=repo`, valid even before any PRD exists) or bound to an active PRD (`--scope=prd`).
|
|
3
3
|
|
|
4
4
|
## When to Use
|
|
5
5
|
- Use when an architectural or design decision has been made and needs to be recorded for future reference (library choice, communication pattern, performance tradeoff, compliance-imposed constraint, etc.)
|
|
6
6
|
- Use during `/dw-plan techspec` or `/dw-run` when the rationale for the decision does not fit in the techspec or the task file
|
|
7
|
+
- Use **before any PRD exists** to record a repo-wide decision — pass `--scope=repo` (writes to `.dw/adrs/`).
|
|
7
8
|
- Do NOT use for trivial or cheaply-reversible decisions (variable names, import order)
|
|
8
9
|
- Do NOT use to record bugs or incidents (use `/dw-bugfix` or operational notes)
|
|
9
10
|
|
|
11
|
+
<critical>Offer or create an ADR ONLY when all three criteria hold: (1) **hard to reverse**, (2) **surprising without context**, and (3) a **genuine trade-off** (a real alternative was considered and chosen against). If any one is missing, skip the ADR — do not turn the ADR log into noise. Creation ALWAYS needs explicit user approval, even when all three hold.</critical>
|
|
12
|
+
|
|
10
13
|
## Pipeline Position
|
|
11
|
-
**Predecessor:** any point
|
|
14
|
+
**Predecessor:** any point (repo-scoped ADRs work even before `/dw-plan prd`) | **Successor:** continue the previous flow (techspec, task, review)
|
|
12
15
|
|
|
13
16
|
The ADR is **additive**: it does not replace any pipeline stage. Any existing command can invoke `/dw-adr` when a non-trivial decision needs a permanent record.
|
|
14
17
|
|
|
18
|
+
## Scope (`--scope=repo|prd`)
|
|
19
|
+
|
|
20
|
+
| Scope | Directory | When |
|
|
21
|
+
|-------|-----------|------|
|
|
22
|
+
| `repo` | `.dw/adrs/adr-NNN.md` | Repo-wide decision, and any decision made **before a PRD exists**. |
|
|
23
|
+
| `prd` | `{{PRD_PATH}}/adrs/adr-NNN.md` | Decision bound to a specific active PRD. |
|
|
24
|
+
|
|
25
|
+
**Default resolution** when `--scope` is not given (`--scope=` is always authoritative and overrides this):
|
|
26
|
+
|
|
27
|
+
1. Determine the **candidate active PRDs** (see "Active PRD" below) — PRD directories in `.dw/spec/prd-*/` that are NOT terminal/historical.
|
|
28
|
+
2. Exactly one candidate → default to `prd` (that PRD).
|
|
29
|
+
3. Zero candidates (no PRD exists, or every PRD is terminal) → default to `repo`.
|
|
30
|
+
4. Two or more candidates with no disambiguating signal → **ask** which PRD (or `repo`); never guess.
|
|
31
|
+
|
|
32
|
+
### Active PRD (operational definition)
|
|
33
|
+
|
|
34
|
+
Distinguish an **active** PRD from a **historical/terminal** one deterministically and conservatively, using evidence already in the repo — in this precedence:
|
|
35
|
+
|
|
36
|
+
1. **Explicit target** — a PRD named in the request or passed as `{{PRD_PATH}}`. Wins outright.
|
|
37
|
+
2. **Active session** — the PRD referenced by `.dw/STATE.md` (the current working spec), when present.
|
|
38
|
+
3. **Current branch** — a `feat/prd-<slug>` checkout points at `prd-<slug>`.
|
|
39
|
+
|
|
40
|
+
A PRD directory is **terminal/historical** (excluded from candidates) when its `prd.md` frontmatter/status marks it shipped, merged, delivered, done, archived, superseded, or cancelled. When none of signals 1–3 disambiguate and more than one non-terminal PRD remains, **ask** — do not guess. This reads only what the repo already records; it never invents state, a status field, or a migration.
|
|
41
|
+
|
|
42
|
+
Numbering (`NNN`) is sequential **within the chosen scope's** ADR directory — repo ADRs and per-PRD ADRs have independent counters.
|
|
43
|
+
|
|
15
44
|
## Input Variables
|
|
16
45
|
|
|
17
46
|
| Variable | Description | Example |
|
|
18
47
|
|----------|-------------|---------|
|
|
19
|
-
| `{{
|
|
48
|
+
| `{{SCOPE}}` | `repo` or `prd` (optional; resolved by default rules above) | `repo` |
|
|
49
|
+
| `{{PRD_PATH}}` | Path to the active PRD folder (only for `scope=prd`) | `.dw/spec/prd-my-feature` |
|
|
20
50
|
| `{{TITLE}}` | Short imperative title of the decision | "Use PostgreSQL instead of MongoDB" |
|
|
21
51
|
|
|
22
|
-
If `{{PRD_PATH}}` is not provided, ask the user which PRD is active (read `.dw/spec/` and list). If `{{TITLE}}` is not provided, ask.
|
|
52
|
+
If `{{SCOPE}}` is not provided, resolve it per the Scope section (unique PRD → `prd`; no PRD → `repo`; multiple PRDs → ask). For `scope=prd`, if `{{PRD_PATH}}` is not provided, ask the user which PRD is active (read `.dw/spec/` and list). If `{{TITLE}}` is not provided, ask.
|
|
23
53
|
|
|
24
54
|
## File Locations
|
|
25
55
|
|
|
26
|
-
-
|
|
27
|
-
-
|
|
56
|
+
- **`scope=repo`** → directory `.dw/adrs/`, new file `.dw/adrs/adr-NNN.md`.
|
|
57
|
+
- **`scope=prd`** → directory `{{PRD_PATH}}/adrs/`, new file `{{PRD_PATH}}/adrs/adr-NNN.md`.
|
|
58
|
+
- NNN zero-padded to 3 digits, sequential within the chosen scope's directory.
|
|
28
59
|
- Template: `.dw/templates/adr-template.md`
|
|
29
60
|
|
|
30
61
|
## Workflow
|
|
31
62
|
|
|
63
|
+
### 0. Resolve scope
|
|
64
|
+
- Determine `scope` from `--scope=` or the default resolution (unique active PRD → `prd`; no PRD → `repo`; ambiguous multiple PRDs → ask). Set the target ADR directory accordingly (`.dw/adrs/` for repo, `{{PRD_PATH}}/adrs/` for prd).
|
|
65
|
+
- Confirm the three-criterion gate holds (hard to reverse + surprising + genuine trade-off) and get explicit user approval before writing.
|
|
66
|
+
|
|
32
67
|
### 1. Discover the next number
|
|
33
|
-
- List files in
|
|
68
|
+
- List files in the target ADR directory (create it if missing)
|
|
34
69
|
- Next number is `max(existing) + 1`, or `1` if empty
|
|
35
70
|
|
|
36
71
|
### 2. Gather context (minimum questions)
|
|
@@ -52,8 +87,9 @@ id: NNN
|
|
|
52
87
|
status: Proposed | Accepted | Deprecated | Superseded
|
|
53
88
|
title: [ADR title]
|
|
54
89
|
date: YYYY-MM-DD
|
|
55
|
-
|
|
56
|
-
|
|
90
|
+
scope: repo | prd
|
|
91
|
+
prd: [PRD slug for scope=prd, or "n/a" for scope=repo]
|
|
92
|
+
schema_version: "1.1"
|
|
57
93
|
---
|
|
58
94
|
|
|
59
95
|
# ADR-NNN: [Title]
|
|
@@ -86,11 +122,13 @@ schema_version: "1.0"
|
|
|
86
122
|
|
|
87
123
|
### 4. Update cross-references
|
|
88
124
|
|
|
89
|
-
If the ADR is created
|
|
125
|
+
If the ADR is created with **`scope=prd`** (during a PRD execution), add a line to the "Related ADRs" section of related artifacts:
|
|
90
126
|
- `prd.md`, `techspec.md`, or `[N]_task.md`, matching the decision's scope
|
|
91
127
|
|
|
92
128
|
If the "Related ADRs" section does not exist in the file, add it at the end.
|
|
93
129
|
|
|
130
|
+
For **`scope=repo`** ADRs there is no owning PRD — set `prd: n/a` in the frontmatter and link related artifacts only when they genuinely apply (e.g. `.dw/constitution.md`, `.dw/rules/`). Repo ADRs are the natural home for decisions taken during a greenfield Grill session before any PRD exists.
|
|
131
|
+
|
|
94
132
|
### 5. Report
|
|
95
133
|
|
|
96
134
|
Present to the user:
|
|
@@ -110,7 +148,7 @@ This command is inspired by the ADR pattern in `/tmp/compozy/.agents/skills/cy-c
|
|
|
110
148
|
|
|
111
149
|
- Paths are `.dw/spec/<prd>/adrs/` instead of `.compozy/tasks/<name>/adrs/`
|
|
112
150
|
- 4 minimum questions instead of Compozy's longer interactive flow (aligned with the concise style of other dw-* commands)
|
|
113
|
-
- Explicit integration with `schema_version`
|
|
151
|
+
- Explicit integration with `schema_version` v1.1 templates (adds `scope`; the PRD link is conditional so repo-scoped ADRs are coherent)
|
|
114
152
|
|
|
115
153
|
Credit: Compozy project.
|
|
116
154
|
|
|
@@ -32,6 +32,7 @@ The rules generated by this command are consumed by:
|
|
|
32
32
|
<critical>This command ONLY generates documentation. Do NOT modify any project source code.</critical>
|
|
33
33
|
<critical>Read actual source files to verify patterns — do not guess from file names alone.</critical>
|
|
34
34
|
<critical>Include real code examples from the project in the generated rules.</critical>
|
|
35
|
+
<critical>PRESERVE the Grill flow's domain artifacts. `.dw/domain/**` (glossary / context-map / per-context files) is human-curated canonical vocabulary owned by `/dw-brainstorm` grill — this command must NEVER regenerate, merge, or overwrite it. When `.dw/domain/**` exists, READ it and LINK it from `.dw/rules/index.md`; do not copy its terms into the auto-generated `.dw/rules/` files. This command owns `.dw/rules/**`; the Grill flow owns `.dw/domain/**`.</critical>
|
|
35
36
|
|
|
36
37
|
## Objective
|
|
37
38
|
|
|
@@ -225,6 +226,10 @@ For each module/project detected, identify:
|
|
|
225
226
|
| **Auth** | NextAuth, Passport, Keycloak, Auth0, etc. | Dependencies + auth-related files |
|
|
226
227
|
| **API Style** | REST, GraphQL, tRPC, gRPC | Route definitions, schema files |
|
|
227
228
|
|
|
229
|
+
#### Curated baseline (rules-library)
|
|
230
|
+
|
|
231
|
+
After detecting the stack(s), consult `.dw/config/stack-mappings.json`: each matched stack points to its curated baseline in `.dw/rules-library/` (`common.md` + `<stack>.md`) — the declarative "what good code looks like here" default. **Reference** these files (do NOT copy them into `.dw/rules/`): the analytical rules you write describe what the code IS; the library describes what it SHOULD be. Load only the matched stacks' files to protect the context budget.
|
|
232
|
+
|
|
228
233
|
#### Frontend Health Baseline
|
|
229
234
|
|
|
230
235
|
When React is detected, run `npx react-doctor@latest --verbose` and include the health score in the generated rules as a baseline metric.
|
|
@@ -494,8 +499,11 @@ workspace-root/
|
|
|
494
499
|
|
|
495
500
|
- See [{module}]({module}.md) for detailed rules per module
|
|
496
501
|
- See [integrations.md](integrations.md) for inter-project communication (if monorepo)
|
|
502
|
+
- See [domain glossary](../domain/glossary.md) — or [context map](../domain/context-map.md) — for canonical vocabulary (only when `.dw/domain/` exists; owned by Grill, read-only here, never regenerated)
|
|
497
503
|
```
|
|
498
504
|
|
|
505
|
+
> When `.dw/domain/**` exists, add the Domain Vocabulary link(s) above to the generated `index.md` and leave the domain files untouched. When it does not exist, omit the link — this command never creates `.dw/domain/**` (only `/dw-brainstorm` grill does, after explicit authorization).
|
|
506
|
+
|
|
499
507
|
#### 7.2 `.dw/rules/{module}.md` (per module)
|
|
500
508
|
|
|
501
509
|
```markdown
|
|
@@ -740,7 +748,7 @@ Three options:
|
|
|
740
748
|
|
|
741
749
|
**Option A — Synthesize:**
|
|
742
750
|
|
|
743
|
-
1. Read `.dw/rules/index.md` + each `.dw/rules/{module}.md`.
|
|
751
|
+
1. Read `.dw/rules/index.md` + each `.dw/rules/{module}.md`, plus the curated baseline for the detected stack(s) in `.dw/rules-library/` (`common.md` + `<stack>.md`). A baseline principle the project already follows is a well-grounded proposal — cite the rules-library file as its evidence.
|
|
744
752
|
2. Propose 5–8 principles. Each must:
|
|
745
753
|
- Have a unique `P-NNN` ID.
|
|
746
754
|
- Map to an observation in `.dw/rules/` (cite the rule file + section).
|
|
@@ -873,6 +881,7 @@ Before declaring the analysis complete, verify:
|
|
|
873
881
|
- [ ] Step 9 (concerns map) presented candidates, awaited approval, wrote `.dw/rules/concerns.md` (or noted no signals)
|
|
874
882
|
- [ ] Step 10 (design authority) ran for frontend projects: existing authority respected, or `DESIGN.md` generated from real tokens, or curated-defaults bootstrap recommended
|
|
875
883
|
- [ ] Preserved-marker blocks in concerns.md kept verbatim on refresh
|
|
884
|
+
- [ ] `.dw/domain/**` (glossary / context-map) preserved verbatim and linked from index.md when present — never regenerated or overwritten
|
|
876
885
|
- [ ] Topology analysis completed (god nodes, coupling metrics, dependency graph)
|
|
877
886
|
- [ ] Critical nodes table generated with Ca, Ce, instability
|
|
878
887
|
- [ ] Circular dependencies identified and documented
|