@brunosps00/dev-workflow 2.2.0 → 2.4.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.
Files changed (154) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/CHANGELOG.md +121 -0
  3. package/README.md +25 -15
  4. package/lib/constants.js +39 -36
  5. package/lib/doctor.js +1 -1
  6. package/lib/init.js +8 -0
  7. package/lib/instruction-health.js +38 -0
  8. package/lib/post-update.js +2 -1
  9. package/lib/validate.js +3 -1
  10. package/package.json +1 -1
  11. package/scaffold/agent-registry.json +17 -1
  12. package/scaffold/agents/core/dw-finding-refuter.md +55 -0
  13. package/scaffold/config/routing.json +61 -23
  14. package/scaffold/en/agent-instructions.md +32 -137
  15. package/scaffold/en/commands/dw-analyze-project.md +2 -0
  16. package/scaffold/en/commands/dw-autopilot.md +36 -241
  17. package/scaffold/en/commands/dw-brainstorm.md +1 -1
  18. package/scaffold/en/commands/dw-bugfix.md +10 -35
  19. package/scaffold/en/commands/dw-claude-run.md +47 -45
  20. package/scaffold/en/commands/dw-codex-run.md +48 -45
  21. package/scaffold/en/commands/dw-context-budget.md +6 -14
  22. package/scaffold/en/commands/dw-copilot-run.md +47 -41
  23. package/scaffold/en/commands/dw-find-skills.md +3 -1
  24. package/scaffold/en/commands/dw-generate-pr.md +2 -2
  25. package/scaffold/en/commands/dw-goal.md +25 -5
  26. package/scaffold/en/commands/dw-help.md +3 -3
  27. package/scaffold/en/commands/dw-install-aws-skills.md +2 -0
  28. package/scaffold/en/commands/dw-install-azure-skills.md +2 -0
  29. package/scaffold/en/commands/dw-plan.md +15 -8
  30. package/scaffold/en/commands/dw-qa.md +3 -0
  31. package/scaffold/en/commands/dw-resume.md +5 -11
  32. package/scaffold/en/commands/dw-review.md +154 -10
  33. package/scaffold/en/commands/dw-run.md +47 -177
  34. package/scaffold/en/commands/dw-secure-audit.md +4 -0
  35. package/scaffold/en/commands/dw-skill-health.md +39 -0
  36. package/scaffold/en/commands/dw-triage.md +8 -0
  37. package/scaffold/en/commands/dw-update.md +18 -4
  38. package/scaffold/en/references/automode.md +71 -0
  39. package/scaffold/en/references/command-routing.md +54 -0
  40. package/scaffold/en/references/execution-contract.md +55 -0
  41. package/scaffold/en/references/invariants.md +88 -0
  42. package/scaffold/en/references/untrusted-input.md +69 -0
  43. package/scaffold/en/templates/constitution-template.md +1 -0
  44. package/scaffold/en/templates/frontend-quality-template.md +43 -0
  45. package/scaffold/en/templates/task-template.md +20 -40
  46. package/scaffold/en/templates/tasks-template.md +9 -6
  47. package/scaffold/en/templates/techspec-template.md +4 -0
  48. package/scaffold/en/templates/triage-record-template.md +5 -0
  49. package/scaffold/pt-br/agent-instructions.md +32 -137
  50. package/scaffold/pt-br/commands/dw-analyze-project.md +3 -1
  51. package/scaffold/pt-br/commands/dw-autopilot.md +36 -241
  52. package/scaffold/pt-br/commands/dw-brainstorm.md +1 -1
  53. package/scaffold/pt-br/commands/dw-bugfix.md +10 -35
  54. package/scaffold/pt-br/commands/dw-claude-run.md +47 -46
  55. package/scaffold/pt-br/commands/dw-codex-run.md +48 -45
  56. package/scaffold/pt-br/commands/dw-context-budget.md +6 -14
  57. package/scaffold/pt-br/commands/dw-copilot-run.md +47 -43
  58. package/scaffold/pt-br/commands/dw-find-skills.md +3 -1
  59. package/scaffold/pt-br/commands/dw-generate-pr.md +2 -2
  60. package/scaffold/pt-br/commands/dw-goal.md +25 -5
  61. package/scaffold/pt-br/commands/dw-help.md +3 -3
  62. package/scaffold/pt-br/commands/dw-install-aws-skills.md +2 -0
  63. package/scaffold/pt-br/commands/dw-install-azure-skills.md +2 -0
  64. package/scaffold/pt-br/commands/dw-plan.md +15 -8
  65. package/scaffold/pt-br/commands/dw-qa.md +3 -0
  66. package/scaffold/pt-br/commands/dw-resume.md +7 -11
  67. package/scaffold/pt-br/commands/dw-review.md +154 -10
  68. package/scaffold/pt-br/commands/dw-run.md +47 -177
  69. package/scaffold/pt-br/commands/dw-secure-audit.md +5 -1
  70. package/scaffold/pt-br/commands/dw-skill-health.md +39 -0
  71. package/scaffold/pt-br/commands/dw-triage.md +8 -0
  72. package/scaffold/pt-br/commands/dw-update.md +18 -4
  73. package/scaffold/pt-br/references/automode.md +72 -0
  74. package/scaffold/pt-br/references/command-routing.md +54 -0
  75. package/scaffold/pt-br/references/execution-contract.md +55 -0
  76. package/scaffold/pt-br/references/invariants.md +88 -0
  77. package/scaffold/pt-br/references/untrusted-input.md +70 -0
  78. package/scaffold/pt-br/templates/constitution-template.md +1 -0
  79. package/scaffold/pt-br/templates/frontend-quality-template.md +43 -0
  80. package/scaffold/pt-br/templates/task-template.md +20 -40
  81. package/scaffold/pt-br/templates/tasks-template.md +9 -6
  82. package/scaffold/pt-br/templates/techspec-template.md +4 -0
  83. package/scaffold/pt-br/templates/triage-record-template.md +5 -0
  84. package/scaffold/scripts/hooks/git-guardrails.mjs +12 -0
  85. package/scaffold/scripts/hooks/session-cost.mjs +122 -7
  86. package/scaffold/scripts/lib/workflow-contract.mjs +101 -0
  87. package/scaffold/skill-registry.json +35 -23
  88. package/scaffold/skills/dw-chaos-engineering/SKILL.md +126 -0
  89. package/scaffold/skills/dw-chaos-engineering/references/vector-catalog.md +43 -0
  90. package/scaffold/skills/dw-cli-run/SKILL.md +39 -215
  91. package/scaffold/skills/dw-cli-run/references/dispatch-tuning.md +14 -72
  92. package/scaffold/skills/dw-codebase-intel/SKILL.md +5 -39
  93. package/scaffold/skills/dw-codebase-intel/agents/intel-updater.md +1 -1
  94. package/scaffold/skills/dw-codebase-intel/references/agents-detail.md +7 -0
  95. package/scaffold/skills/dw-codebase-intel/references/files-in-dw-intel-detail.md +16 -0
  96. package/scaffold/skills/dw-codebase-intel/references/how-dw-intel-reads-this-detail.md +12 -0
  97. package/scaffold/skills/dw-codebase-intel/references/how-to-compose-the-typical-flow-detail.md +11 -0
  98. package/scaffold/skills/dw-council/SKILL.md +2 -17
  99. package/scaffold/skills/dw-council/references/integration-with-other-dw-commands-detail.md +7 -0
  100. package/scaffold/skills/dw-council/references/phase-2-tensions-and-rebuttals-detail.md +15 -0
  101. package/scaffold/skills/dw-debug-protocol/references/six-step-triage.md +1 -0
  102. package/scaffold/skills/dw-domain-modeling/SKILL.md +1 -1
  103. package/scaffold/skills/dw-execute-phase/SKILL.md +12 -32
  104. package/scaffold/skills/dw-execute-phase/agents/executor.md +15 -252
  105. package/scaffold/skills/dw-execute-phase/agents/plan-checker.md +4 -207
  106. package/scaffold/skills/dw-execute-phase/references/atomic-commits.md +8 -18
  107. package/scaffold/skills/dw-execute-phase/references/de-sloppify-pass-optional-cleanup-task-detail.md +12 -0
  108. package/scaffold/skills/dw-execute-phase/references/deviation-rules-during-execution-detail.md +8 -0
  109. package/scaffold/skills/dw-execute-phase/references/how-the-two-agents-compose-detail.md +7 -0
  110. package/scaffold/skills/dw-execute-phase/references/plan-verification.md +9 -155
  111. package/scaffold/skills/dw-execute-phase/references/wave-coordination.md +6 -97
  112. package/scaffold/skills/dw-git-discipline/SKILL.md +2 -2
  113. package/scaffold/skills/dw-grilling/SKILL.md +1 -1
  114. package/scaffold/skills/dw-incident-response/SKILL.md +1 -64
  115. package/scaffold/skills/dw-incident-response/references/the-five-phases-detail.md +66 -0
  116. package/scaffold/skills/dw-llm-eval/SKILL.md +6 -53
  117. package/scaffold/skills/dw-llm-eval/references/agent-tool-use-evaluation-detail.md +23 -0
  118. package/scaffold/skills/dw-llm-eval/references/anti-patterns-will-block-in-dw-review-code-only-detail.md +9 -0
  119. package/scaffold/skills/dw-llm-eval/references/bounded-decisions.md +76 -0
  120. package/scaffold/skills/dw-llm-eval/references/consistency-run-to-run-stability-detail.md +10 -0
  121. package/scaffold/skills/dw-llm-eval/references/integration-with-dev-workflow-commands-detail.md +6 -0
  122. package/scaffold/skills/dw-llm-eval/references/judge-calibration.md +5 -0
  123. package/scaffold/skills/dw-llm-eval/references/the-oracle-ladder-detail.md +15 -0
  124. package/scaffold/skills/dw-memory/SKILL.md +4 -50
  125. package/scaffold/skills/dw-memory/references/context-budget.md +8 -56
  126. package/scaffold/skills/dw-memory/references/promotion-decision-test-detail.md +30 -0
  127. package/scaffold/skills/dw-minimalism/SKILL.md +4 -5
  128. package/scaffold/skills/dw-review-rigor/SKILL.md +31 -88
  129. package/scaffold/skills/dw-review-rigor/references/composition-audit.md +160 -0
  130. package/scaffold/skills/dw-review-rigor/references/refutation-pass.md +124 -0
  131. package/scaffold/skills/dw-review-rigor/references/the-five-rules-detail.md +56 -0
  132. package/scaffold/skills/dw-simplification/SKILL.md +2 -55
  133. package/scaffold/skills/dw-simplification/references/pattern-recognition-detail.md +11 -0
  134. package/scaffold/skills/dw-simplification/references/the-five-rules-detail.md +48 -0
  135. package/scaffold/skills/dw-source-grounding/SKILL.md +21 -56
  136. package/scaffold/skills/dw-source-grounding/references/the-protocol-detect-fetch-implement-cite-detail.md +58 -0
  137. package/scaffold/skills/dw-testing-discipline/SKILL.md +25 -177
  138. package/scaffold/skills/dw-testing-discipline/references/agent-guardrails.md +9 -167
  139. package/scaffold/skills/dw-testing-discipline/references/core-rules.md +3 -3
  140. package/scaffold/skills/dw-testing-discipline/references/mutation-testing.md +19 -0
  141. package/scaffold/skills/dw-testing-discipline/references/patterns.md +3 -12
  142. package/scaffold/skills/dw-ui-discipline/SKILL.md +2 -59
  143. package/scaffold/skills/dw-ui-discipline/references/frontend-engineering.md +46 -0
  144. package/scaffold/skills/dw-ui-discipline/references/the-four-grounding-questions-detail.md +61 -0
  145. package/scaffold/skills/dw-verify/SKILL.md +26 -148
  146. package/scaffold/skills/dw-verify/references/verification-discovery-and-attribution.md +2 -2
  147. package/scaffold/skills/humanizer/SKILL.md +2 -1
  148. package/scaffold/skills/security-review/SKILL.md +6 -184
  149. package/scaffold/skills/security-review/references/do-not-flag-detail.md +49 -0
  150. package/scaffold/skills/security-review/references/modern-threats.md +5 -0
  151. package/scaffold/skills/security-review/references/quick-patterns-reference-detail.md +56 -0
  152. package/scaffold/skills/security-review/references/review-process-detail.md +112 -0
  153. package/scaffold/skills/vercel-react-best-practices/SKILL.md +1 -90
  154. package/scaffold/skills/vercel-react-best-practices/references/quick-reference-detail.md +92 -0
@@ -0,0 +1,101 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { fileURLToPath } from 'node:url';
3
+ import { resolve } from 'node:path';
4
+
5
+ const tools = new Set(['local', 'codex', 'claude', 'copilot']);
6
+ const tiers = new Set(['light', 'standard', 'heavy']);
7
+
8
+ // A small executable contract for the agent-authored execution-plan.json.
9
+ // This validates assignments, not account access or authorization on its own.
10
+ export function validatePlan(plan) {
11
+ const issues = [];
12
+ if (!plan || !['1.0', '1.1'].includes(plan.schema_version)) return ['Unsupported execution plan schema'];
13
+ if (!Array.isArray(plan.tasks) || !plan.tasks.length) return ['tasks must be a nonempty array'];
14
+ if (typeof plan.approved !== 'boolean') issues.push('approved must be a boolean');
15
+ const ids = new Set();
16
+ for (const task of plan.tasks) {
17
+ if (!task || typeof task.id !== 'string' || !task.id.trim()) {
18
+ issues.push('Every task needs a nonempty string id');
19
+ continue;
20
+ }
21
+ if (ids.has(task.id)) issues.push(`Duplicate task ${task.id}`);
22
+ ids.add(task.id);
23
+ if (!Array.isArray(task.depends_on) || task.depends_on.some(id => typeof id !== 'string')) issues.push(`${task.id}: depends_on must be a string array`);
24
+ if (plan.schema_version === '1.1' && !task.execution) issues.push(`${task.id}: missing execution assignment`);
25
+ if (task.execution) {
26
+ const e = task.execution;
27
+ if (typeof e !== 'object' || Array.isArray(e)) { issues.push(`${task.id}: execution must be an object`); continue; }
28
+ if (!tiers.has(e.complexity)) issues.push(`${task.id}: invalid complexity`);
29
+ if (typeof e.rationale !== 'string' || !e.rationale.trim()) issues.push(`${task.id}: missing rationale`);
30
+ if (!Array.isArray(e.agents) || e.agents.some(a => typeof a !== 'string')) issues.push(`${task.id}: agents must be a string array`);
31
+ for (const assignment of [e, ...(Array.isArray(e.fallbacks) ? e.fallbacks : [])]) {
32
+ if (!assignment || typeof assignment !== 'object' || Array.isArray(assignment)) { issues.push(`${task.id}: invalid fallback assignment`); continue; }
33
+ if (!tools.has(assignment.tool)) issues.push(`${task.id}: invalid tool`);
34
+ if (typeof assignment.model !== 'string' || !assignment.model.trim()) issues.push(`${task.id}: missing model`);
35
+ if (typeof assignment.effort !== 'string' || !assignment.effort.trim()) issues.push(`${task.id}: missing effort`);
36
+ if (assignment.tool !== 'local' && [assignment.model, assignment.effort].includes('inherit')) issues.push(`${task.id}: external assignments must resolve model and effort`);
37
+ }
38
+ if (e.fallbacks !== undefined && !Array.isArray(e.fallbacks)) issues.push(`${task.id}: fallbacks must be an array`);
39
+ }
40
+ }
41
+ const tasks = new Map(plan.tasks.filter(t => t?.id).map(t => [t.id, t]));
42
+ const visiting = new Set(), visited = new Set();
43
+ function visit(id) {
44
+ if (visiting.has(id)) { issues.push(`Dependency cycle at ${id}`); return; }
45
+ if (visited.has(id)) return;
46
+ visiting.add(id);
47
+ for (const dep of tasks.get(id)?.depends_on || []) {
48
+ if (!ids.has(dep)) issues.push(`${id}: unknown dependency ${dep}`);
49
+ else visit(dep);
50
+ }
51
+ visiting.delete(id); visited.add(id);
52
+ }
53
+ if (!issues.length) for (const id of ids) visit(id);
54
+ return issues;
55
+ }
56
+
57
+ export function resolveAssignment(plan, taskId, availableTools) {
58
+ const issues = validatePlan(plan);
59
+ if (issues.length) throw new Error(issues.join('; '));
60
+ if (plan.approved !== true) throw new Error('Execution plan is not approved');
61
+ const task = plan.tasks.find(t => t.id === taskId);
62
+ if (!task) throw new Error(`Unknown task ${taskId}`);
63
+ // Legacy plans never imply permission to start another CLI.
64
+ const assignment = task.execution || { tool: 'local', model: 'inherit', effort: 'inherit', agents: [] };
65
+ const candidates = [assignment, ...(assignment.fallbacks || [])];
66
+ const chosen = candidates.find(c => availableTools.includes(c.tool));
67
+ if (!chosen) throw new Error(`No approved executor available for ${taskId}`);
68
+ return { ...chosen, agents: assignment.agents || [], fallback: chosen !== assignment };
69
+ }
70
+
71
+ export function readyTasks(plan, completedIds) {
72
+ const issues = validatePlan(plan);
73
+ if (issues.length) throw new Error(issues.join('; '));
74
+ const done = new Set(completedIds);
75
+ return plan.tasks.filter(t => !done.has(t.id) && t.depends_on.every(id => done.has(id))).map(t => t.id);
76
+ }
77
+
78
+ // Callers fingerprint actual inputs (including relevant untracked files) and
79
+ // environment. Unknown values fail closed. Time/message boundaries are irrelevant.
80
+ export function reusableEvidence(evidence, current) {
81
+ if (!evidence || evidence.exit_code !== 0 || !current) return false;
82
+ for (const key of ['command', 'input_fingerprint', 'environment_fingerprint']) {
83
+ if (typeof current[key] !== 'string' || !current[key] || evidence[key] !== current[key]) return false;
84
+ }
85
+ return Array.isArray(current.scope) && current.scope.length > 0 && Array.isArray(evidence.scope)
86
+ && current.scope.every(item => evidence.scope.includes(item));
87
+ }
88
+
89
+ if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
90
+ try {
91
+ const [mode, file, taskId, available = 'local'] = process.argv.slice(2);
92
+ if (!['validate', 'resolve', 'ready'].includes(mode) || !file) throw new Error('Usage: workflow-contract.mjs validate|resolve|ready <plan.json> [task-id|completed-csv] [available-tools-csv]');
93
+ const plan = JSON.parse(readFileSync(file, 'utf8'));
94
+ if (mode === 'validate') {
95
+ const issues = validatePlan(plan);
96
+ console.log(JSON.stringify({ status: issues.length ? 'BLOCKED' : 'PASS', issues }));
97
+ if (issues.length) process.exitCode = 1;
98
+ } else if (mode === 'resolve') console.log(JSON.stringify(resolveAssignment(plan, taskId, available.split(','))));
99
+ else console.log(JSON.stringify(readyTasks(plan, taskId ? taskId.split(',') : [])));
100
+ } catch (error) { console.error(error.message); process.exitCode = 1; }
101
+ }
@@ -9,7 +9,7 @@
9
9
  "trigger": "API QA, endpoint testing, HTTP recipe generation",
10
10
  "expected_output": "A selected API testing recipe and evidence path for the active stack.",
11
11
  "load_policy": "lazy-references",
12
- "context_limit": 12000,
12
+ "context_limit": 8000,
13
13
  "invocation": "explicit",
14
14
  "exportable": true,
15
15
  "bundled": true
@@ -22,20 +22,32 @@
22
22
  "trigger": "Docker Compose service selection or local infrastructure setup",
23
23
  "expected_output": "A selected service recipe and composition guidance.",
24
24
  "load_policy": "lazy-references",
25
- "context_limit": 12000,
25
+ "context_limit": 8000,
26
26
  "invocation": "explicit",
27
27
  "exportable": true,
28
28
  "bundled": true
29
29
  },
30
+ {
31
+ "name": "dw-chaos-engineering",
32
+ "kind": "protocol",
33
+ "tier": "specialty",
34
+ "owner": "manual,dw-qa,dw-review",
35
+ "trigger": "Explicit request to adversarially test or stress an implemented change",
36
+ "expected_output": "Chaos report with per-attack classification, minimal repros, and the routing of each finding.",
37
+ "load_policy": "lazy-references",
38
+ "context_limit": 8000,
39
+ "invocation": "explicit",
40
+ "bundled": true
41
+ },
30
42
  {
31
43
  "name": "dw-cli-run",
32
44
  "kind": "protocol",
33
45
  "tier": "core",
34
46
  "owner": "dw-codex-run,dw-claude-run,dw-copilot-run",
35
- "trigger": "Fire an AI CLI (Codex/Claude/Copilot) in a dedicated git worktree to implement a prepared prompt; resumable per-task session; STOP for the gate",
36
- "expected_output": "Audit-logged run with a 0-10 dual evaluation, a resumable session-id sidecar, and a STOP-for-gate Structured Return.",
47
+ "trigger": "Execute an approved task through a supported external CLI adapter",
48
+ "expected_output": "Reviewed task handoff with durable session, acceptance evidence and next task or blocker.",
37
49
  "load_policy": "lazy-references",
38
- "context_limit": 20500,
50
+ "context_limit": 8000,
39
51
  "bundled": true
40
52
  },
41
53
  {
@@ -46,7 +58,7 @@
46
58
  "trigger": "Codebase indexing or codebase intelligence query",
47
59
  "expected_output": ".dw/intel index files or a cited answer from the index.",
48
60
  "load_policy": "lazy-references",
49
- "context_limit": 12000,
61
+ "context_limit": 8000,
50
62
  "bundled": true
51
63
  },
52
64
  {
@@ -57,7 +69,7 @@
57
69
  "trigger": "Council mode or high-impact architectural debate",
58
70
  "expected_output": "Advisor positions, tension synthesis, and decision recommendation.",
59
71
  "load_policy": "lazy-references",
60
- "context_limit": 12000,
72
+ "context_limit": 8000,
61
73
  "bundled": true
62
74
  },
63
75
  {
@@ -68,7 +80,7 @@
68
80
  "trigger": "Native Grill domain vocabulary: challenge fuzzy/overloaded terms, cross-check against code, persist a canonical glossary to .dw/domain",
69
81
  "expected_output": "Canonical terms with discouraged synonyms persisted lazily to .dw/domain (single or multi-context), or fuzzy-term findings.",
70
82
  "load_policy": "lazy-references",
71
- "context_limit": 12000,
83
+ "context_limit": 8000,
72
84
  "exportable": false,
73
85
  "bundled": true
74
86
  },
@@ -80,7 +92,7 @@
80
92
  "trigger": "Native Grill decision-tree interview: sharpen a plan/PRD to shared understanding, exactly one decision per turn with a recommended answer",
81
93
  "expected_output": "A dependency-ordered decision tree, resolved decisions with recommendations, and an explicit shared-understanding gate.",
82
94
  "load_policy": "lazy-references",
83
- "context_limit": 12000,
95
+ "context_limit": 8000,
84
96
  "exportable": false,
85
97
  "bundled": true
86
98
  },
@@ -92,7 +104,7 @@
92
104
  "trigger": "Bugfix, QA fix loop, or non-reproducible failure",
93
105
  "expected_output": "Six-step triage, root cause, guard, and verification path.",
94
106
  "load_policy": "lazy-references",
95
- "context_limit": 12000,
107
+ "context_limit": 8000,
96
108
  "bundled": true
97
109
  },
98
110
  {
@@ -103,7 +115,7 @@
103
115
  "trigger": "Task execution, plan-checking, waves, checkpoint recovery",
104
116
  "expected_output": "Plan-check verdict, wave execution report, or checkpoint summary.",
105
117
  "load_policy": "lazy-references",
106
- "context_limit": 12000,
118
+ "context_limit": 8000,
107
119
  "bundled": true
108
120
  },
109
121
  {
@@ -114,7 +126,7 @@
114
126
  "trigger": "Commit creation, branch hygiene, PR generation",
115
127
  "expected_output": "Atomic commit plan and git hygiene checks.",
116
128
  "load_policy": "lazy-references",
117
- "context_limit": 12000,
129
+ "context_limit": 8000,
118
130
  "bundled": true
119
131
  },
120
132
  {
@@ -125,7 +137,7 @@
125
137
  "trigger": "Production critical bug, outage, incident, SEV workflow",
126
138
  "expected_output": "Incident triage, communication, resolution, and postmortem artifacts.",
127
139
  "load_policy": "lazy-references",
128
- "context_limit": 12000,
140
+ "context_limit": 8000,
129
141
  "bundled": true
130
142
  },
131
143
  {
@@ -136,7 +148,7 @@
136
148
  "trigger": "AI, LLM, RAG, classifier, agent, or tool-use feature",
137
149
  "expected_output": "Eval strategy, oracle choice, dataset requirements, and result checks.",
138
150
  "load_policy": "lazy-references",
139
- "context_limit": 12000,
151
+ "context_limit": 8000,
140
152
  "bundled": true
141
153
  },
142
154
  {
@@ -147,7 +159,7 @@
147
159
  "trigger": "Task execution memory, checkpointing, compaction",
148
160
  "expected_output": "Updated workflow memory and task-local memory guidance.",
149
161
  "load_policy": "lazy-references",
150
- "context_limit": 12000,
162
+ "context_limit": 8000,
151
163
  "bundled": true
152
164
  },
153
165
  {
@@ -171,7 +183,7 @@
171
183
  "trigger": "Code review, implementation review, or review consolidation",
172
184
  "expected_output": "Deduplicated findings ordered by defensible severity.",
173
185
  "load_policy": "always-small",
174
- "context_limit": 12000,
186
+ "context_limit": 8000,
175
187
  "bundled": true
176
188
  },
177
189
  {
@@ -205,7 +217,7 @@
205
217
  "trigger": "Refactor analysis, code smells, complexity, or behavior-preserving simplification",
206
218
  "expected_output": "Simplification target, risk, behavior-preserving checks, and recommendation.",
207
219
  "load_policy": "lazy-references",
208
- "context_limit": 12000,
220
+ "context_limit": 8000,
209
221
  "exportable": true,
210
222
  "bundled": true
211
223
  },
@@ -217,7 +229,7 @@
217
229
  "trigger": "Library/framework/API decision, technical research, dependency audit",
218
230
  "expected_output": "Cited source-grounded decision with version and retrieval date.",
219
231
  "load_policy": "lazy-references",
220
- "context_limit": 12000,
232
+ "context_limit": 8000,
221
233
  "bundled": true
222
234
  },
223
235
  {
@@ -228,7 +240,7 @@
228
240
  "trigger": "Writing, reviewing, or debugging tests",
229
241
  "expected_output": "Test placement, invariant, anti-pattern checks, and verification guidance.",
230
242
  "load_policy": "lazy-references",
231
- "context_limit": 12000,
243
+ "context_limit": 8000,
232
244
  "bundled": true
233
245
  },
234
246
  {
@@ -239,7 +251,7 @@
239
251
  "trigger": "UI design, redesign, visual QA, accessibility, or frontend polish",
240
252
  "expected_output": "Grounding answers, state matrix, accessibility checks, and visual risks.",
241
253
  "load_policy": "lazy-references",
242
- "context_limit": 12000,
254
+ "context_limit": 8000,
243
255
  "bundled": true
244
256
  },
245
257
  {
@@ -250,7 +262,7 @@
250
262
  "trigger": "Completion claim, commit, PR generation, or fixed bug status",
251
263
  "expected_output": "Fresh verification report with cited command evidence.",
252
264
  "load_policy": "always-small",
253
- "context_limit": 12000,
265
+ "context_limit": 8000,
254
266
  "exportable": true,
255
267
  "bundled": true
256
268
  },
@@ -288,7 +300,7 @@
288
300
  "trigger": "Security review, sensitive code, OWASP checks, auth/payment/input surfaces",
289
301
  "expected_output": "High-confidence security findings or explicit pass.",
290
302
  "load_policy": "lazy-references",
291
- "context_limit": 14000,
303
+ "context_limit": 8000,
292
304
  "exportable": true,
293
305
  "bundled": true
294
306
  },
@@ -300,7 +312,7 @@
300
312
  "trigger": "React/Next.js performance, hydration, data fetching, bundle or render issues",
301
313
  "expected_output": "Selected performance rule references and metric-driven recommendations.",
302
314
  "load_policy": "lazy-references",
303
- "context_limit": 12000,
315
+ "context_limit": 8000,
304
316
  "invocation": "explicit",
305
317
  "exportable": true,
306
318
  "bundled": true
@@ -0,0 +1,126 @@
1
+ ---
2
+ name: dw-chaos-engineering
3
+ description: Use to adversarially test a change you just implemented. Maps the attack surface, writes tests that try to break it, classifies each KILLED/SURVIVED/INCONCLUSIVE. Local only, writes tests only, 3 rounds max. Ask for it by name.
4
+ allowed-tools:
5
+ - Read
6
+ - Write
7
+ - Bash
8
+ - Grep
9
+ - Glob
10
+ ---
11
+
12
+ # Chaos Engineering
13
+
14
+ > Adapted from the chaos-engineering skill in [`samsantosb/ship-it`](https://github.com/samsantosb/ship-it)
15
+ > (MIT © Samuel Santos). The vector catalogue and the KILLED/SURVIVED/INCONCLUSIVE vocabulary come from
16
+ > there; target resolution, criticality anchoring and finding routing are rewritten for `.dw/`.
17
+
18
+ Where the rest of the pipeline builds, this tries to break. It takes a change that is already implemented
19
+ and writes tests whose only purpose is to prove it fails.
20
+
21
+ **An attack that SURVIVED is also a result.** The goal is not bugs at any cost — it is mapping where the
22
+ code holds and where it gives, and leaving the tests that matter as regression inheritance.
23
+
24
+ ## When to use
25
+
26
+ Invoked by name, never automatically — it writes files, runs the suite and costs real time. Ask for it
27
+ after an implementation is complete and its normal tests pass: post-`/dw-run`, post-`/dw-bugfix`, or on an
28
+ open PR before merge.
29
+
30
+ Do not use it to find a known bug (that is `/dw-bugfix`), to review code (`/dw-review`), or on a change
31
+ that has no tests yet — chaos measures resilience, it does not substitute for coverage.
32
+
33
+ ## Step 0 — Baseline gate
34
+
35
+ **The target's existing tests must pass before any attack.** Run the project's configured suite scoped to
36
+ the touched files.
37
+
38
+ A red baseline stops the run. With a broken environment you cannot tell a finding from noise, and every
39
+ subsequent classification is worthless. Report the failing baseline and stop — that is a `BLOCKED` outcome
40
+ under `.dw/references/automode.md`, not a failed run.
41
+
42
+ ## Step 1 — Resolve the target
43
+
44
+ First that exists: the PR diff · the local diff against the base branch · the files named in
45
+ `.dw/spec/<prd>/tasks/` or `.dw/bugfixes/<slug>/TASK.md`. Only what changed is in scope — the rest of the
46
+ repository is not the target.
47
+
48
+ Read the acceptance criteria if the target has them. Every promise is attackable by negation.
49
+
50
+ ## Step 2 — Attack plan
51
+
52
+ Cross the diff with `references/vector-catalog.md` and select the vectors that actually apply. Not every
53
+ vector fits every diff; prioritize by impact × probability.
54
+
55
+ **Criticality is anchored, not assumed.** `.dw/rules/concerns.md` (the Concerns Map) and
56
+ `.dw/constitution.md` define what is critical *in this project*. Without them severity is opinion; with
57
+ them, a finding against the thing the project protects is critical by definition.
58
+
59
+ Show the plan before building: target, surface, selected vectors as hypotheses, and the vectors left out
60
+ with one line each on why.
61
+
62
+ ## Step 3 — Build the arsenal
63
+
64
+ Follow the project's test conventions and the `dw-testing-discipline` skill — it owns *how* a test is
65
+ written (the anti-pattern catalogue, the agent guardrails, flaky discipline). This skill owns only the
66
+ attack protocol.
67
+
68
+ - One group per vector, one case per attack, named for the hypothesis rather than the implementation.
69
+ - **Simulate hostility with mocks and fixtures.** The test describes a hostile world; it never depends on
70
+ a real one.
71
+ - **Each attack asserts the CORRECT behaviour** — what the system should do under chaos — never the bug.
72
+ So a failing attack is a real finding, and the same test becomes a free regression once it is fixed.
73
+
74
+ ## Step 4 — Run and classify
75
+
76
+ - **KILLED** — the attack broke it. Produce the minimal reproduction: the smallest hostile input that
77
+ still kills.
78
+ - **SURVIVED** — the code held. A result, not a wasted test.
79
+ - **INCONCLUSIVE** — the *test* is wrong (bad mock, flake, environment limit). Fix and rerun, at most
80
+ twice; still inconclusive after that, record it as such and drop it. Never inflate the report.
81
+
82
+ **Round cap: 3.** The initial plan plus at most two deepening rounds on what killed or nearly did. The
83
+ INCONCLUSIVE retry cap is independent — never burn a round chasing a verdict on a broken test.
84
+
85
+ ## Step 5 — Triage
86
+
87
+ Severity comes from the criticality anchor, not from how alarming the input looked.
88
+
89
+ Before sealing each finding, apply the **defense-lawyer test**: is there a reading where this behaviour is
90
+ intentional — an ADR, a project rule, an adjacent comment? If yes, mark it `contestable` and record the
91
+ doubt. The report separates fact from interpretation, the same way `dw-review-rigor` separates a finding
92
+ from an unresolved lead.
93
+
94
+ ## Step 6 — Report and routing
95
+
96
+ Report to `<target>/QA/chaos-report.md`, following the target convention `/dw-qa` already uses.
97
+
98
+ Where each result goes:
99
+
100
+ | Result | Destination |
101
+ |---|---|
102
+ | SURVIVED covering a real gap no existing test covered | Promote as a permanent regression |
103
+ | KILLED on an open PR | Test ships **unskipped** — it blocks the merge on purpose, and `/dw-review` rejects |
104
+ | KILLED on already-merged code | Open `.dw/bugfixes/NNN-slug/` via `/dw-bugfix`; never reopen the landed work |
105
+ | SURVIVED but redundant, or INCONCLUSIVE | Discard. The arsenal is not an accumulation |
106
+
107
+ ## Hard limits
108
+
109
+ - **Local only.** Never fire a request at staging, production or a partner API. A hostile world is
110
+ simulated, without exception.
111
+ - **Tests only.** Production code is read-only here. Finding and fixing are separate roles by design.
112
+ - **Three rounds.** Infinite chaos is procrastination with extra steps.
113
+ - **No theatrical chaos**: no scenarios impossible by construction to pad the report, no asserting the
114
+ current buggy behaviour, and no calling KILLED when what broke was the mock or the clock.
115
+ - Never leave a red test ownerless. A KILLED on an open PR blocks merge on purpose — that is the signal
116
+ working. A red suite with no report and no owner is sabotage.
117
+
118
+ ## Structured Return
119
+
120
+ - **Status:** `PASS` when the run completed with no unfixed KILLED, `FINDINGS` when attacks killed, `BLOCKED` when the baseline is red or the target cannot be resolved, `NOT_APPLICABLE` when no implemented change is in scope.
121
+ - **Scope:** target resolved, files attacked, vectors selected and vectors deliberately skipped.
122
+ - **Evidence:** per-attack classification with the minimal reproduction for each kill, and the baseline result.
123
+ - **Artifacts:** chaos report path, test files written, and where each shipped.
124
+ - **Decisions:** vector selection, severity anchoring, and every `contestable` downgrade with its reading.
125
+ - **Risks:** inconclusive attacks, vectors out of scope, and coverage the rounds did not reach.
126
+ - **Next Step:** the fix route for each kill (`/dw-bugfix` or the PR's own branch), or merge-clean.
@@ -0,0 +1,43 @@
1
+ # Vector catalogue
2
+
3
+ Cross the diff with this list and pick what applies. Selecting every vector for every diff is how a chaos
4
+ run turns into theatre — the skipped vectors, each with one line on why, are part of the plan.
5
+
6
+ ## Boundaries
7
+ Zero · negative · `MAX_SAFE_INTEGER` and the language's numeric ceiling · empty, one, and N+1 · the
8
+ off-by-one at a page or batch edge · leap day · a timezone that is not the author's · DST transition.
9
+
10
+ ## Nulls and absence
11
+ An optional field omitted entirely (not sent as null) · `null` versus `undefined` where the code treats
12
+ them alike · empty object versus missing object · a field the external API stopped returning.
13
+
14
+ ## Broken money
15
+ Rounding at the cent · installments that do not sum to the total · negative amounts · a discount above
16
+ 100% · float arithmetic where decimal is required · currency mismatch · a refund larger than the payment.
17
+
18
+ ## Hostile dependencies
19
+ The external API returns 500 · 429 with and without `Retry-After` · a timeout with no response at all ·
20
+ truncated JSON · valid JSON with the wrong shape · the cache is down · a database deadlock · a job dies
21
+ mid-flight leaving its work half-applied.
22
+
23
+ ## Concurrency and idempotency
24
+ The same request submitted twice · a duplicated webhook · a job reprocessed after a retry · a cron racing
25
+ a live request · two writers on the same row · a read between a check and its use.
26
+
27
+ ## Hostile payloads
28
+ Emoji and combining characters · mixed encodings · a 10k-character string in a field sized for 50 ·
29
+ injection strings that must remain inert · HTML inside free text · a number arriving as a string · deeply
30
+ nested structures.
31
+
32
+ ## Impossible state
33
+ An enum value outside the domain · an orphaned foreign key · an expired session presented as valid · a
34
+ status transition the state machine does not define · a record referencing a deleted parent.
35
+
36
+ ## Contract violation
37
+ An external type that flipped between deploys · an unknown enum member · an extra unexpected field · page
38
+ 2 of a paginated response arriving empty · a schema version the code does not know.
39
+
40
+ ---
41
+
42
+ Each attack asserts what the system **should** do under that condition. An attack written to assert the
43
+ current broken behaviour is not an attack — it is a regression test for the bug.