@houseofwolvesllc/claude-scrum-skill 1.8.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,61 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/houseofwolvesllc/claudescrumskill/schemas/ReviewVerdictSchema.json",
4
+ "title": "ReviewVerdictSchema",
5
+ "description": "Output of a single review pass (per-lens verdict in review_panel.js, or single-pass review in older skills).",
6
+ "type": "object",
7
+ "required": ["recommendation", "findings", "summary"],
8
+ "properties": {
9
+ "recommendation": {
10
+ "type": "string",
11
+ "enum": ["accept", "accept-with-followups", "block"]
12
+ },
13
+ "findings": {
14
+ "type": "object",
15
+ "required": ["critical", "warning", "info"],
16
+ "properties": {
17
+ "critical": {
18
+ "type": "array",
19
+ "items": { "$ref": "#/$defs/Finding" }
20
+ },
21
+ "warning": {
22
+ "type": "array",
23
+ "items": { "$ref": "#/$defs/Finding" }
24
+ },
25
+ "info": {
26
+ "type": "array",
27
+ "items": { "$ref": "#/$defs/Finding" }
28
+ }
29
+ }
30
+ },
31
+ "summary": {
32
+ "type": "string",
33
+ "description": "Reviewer's one-paragraph summary of the pass."
34
+ },
35
+ "lens": {
36
+ "type": "string",
37
+ "enum": ["correctness", "security", "style", "tests"],
38
+ "description": "Set by review_panel.js when running multi-lens; absent in single-pass review."
39
+ }
40
+ },
41
+ "additionalProperties": false,
42
+ "$defs": {
43
+ "Finding": {
44
+ "type": "object",
45
+ "required": ["title", "severity", "body"],
46
+ "properties": {
47
+ "title": { "type": "string" },
48
+ "location": {
49
+ "type": "string",
50
+ "description": "file:line or section reference; optional but recommended."
51
+ },
52
+ "severity": {
53
+ "type": "string",
54
+ "enum": ["critical", "warning", "info"]
55
+ },
56
+ "body": { "type": "string" }
57
+ },
58
+ "additionalProperties": false
59
+ }
60
+ }
61
+ }
@@ -0,0 +1,34 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/houseofwolvesllc/claudescrumskill/schemas/ScaffoldOutputSchema.json",
4
+ "title": "ScaffoldOutputSchema",
5
+ "description": "Output of /project-scaffold; consumed by /project-orchestrate Step 1 to scope the run.",
6
+ "type": "object",
7
+ "required": ["scope", "scopedEpics", "scopedStories"],
8
+ "properties": {
9
+ "scope": {
10
+ "type": "string",
11
+ "enum": ["prd", "all"],
12
+ "description": "Whether the run is PRD-scoped or covers all open epics."
13
+ },
14
+ "scopedEpics": {
15
+ "type": "array",
16
+ "items": { "type": "string" },
17
+ "description": "Epic slugs (local mode) or milestone numbers (remote mode) created/touched by this scaffold."
18
+ },
19
+ "scopedStories": {
20
+ "type": "array",
21
+ "items": { "type": "string" },
22
+ "description": "Story slugs or issue numbers created/touched by this scaffold."
23
+ },
24
+ "designSpikeEpic": {
25
+ "type": "string",
26
+ "description": "Slug of the auto-injected design-spike epic, if any."
27
+ },
28
+ "queueStateFilePath": {
29
+ "type": "string",
30
+ "description": "Path to orchestration-queue-state.md when multi-path mode is in effect."
31
+ }
32
+ },
33
+ "additionalProperties": false
34
+ }
@@ -0,0 +1,77 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/houseofwolvesllc/claudescrumskill/schemas/SpecSchema.json",
4
+ "title": "SpecSchema",
5
+ "description": "Output shape of /project-spec, consumed by /project-scaffold. Inlined to avoid cross-file $ref resolution ambiguity.",
6
+ "type": "object",
7
+ "required": ["title", "overview", "objectives", "epics"],
8
+ "properties": {
9
+ "title": { "type": "string" },
10
+ "overview": { "type": "string" },
11
+ "objectives": {
12
+ "type": "object",
13
+ "required": ["primary"],
14
+ "properties": {
15
+ "primary": { "type": "array", "items": { "type": "string" } },
16
+ "secondary": { "type": "array", "items": { "type": "string" } }
17
+ }
18
+ },
19
+ "epics": {
20
+ "type": "array",
21
+ "items": { "$ref": "#/$defs/Epic" }
22
+ },
23
+ "dependencies": {
24
+ "type": "array",
25
+ "items": { "type": "string" }
26
+ },
27
+ "design_concerns": {
28
+ "type": "array",
29
+ "items": { "type": "string" }
30
+ },
31
+ "scaffold_mode": {
32
+ "type": "string",
33
+ "enum": ["single-pass", "two-pass"]
34
+ },
35
+ "design_spike": { "type": "boolean" }
36
+ },
37
+ "additionalProperties": false,
38
+ "$defs": {
39
+ "Epic": {
40
+ "type": "object",
41
+ "required": ["name", "slug", "description"],
42
+ "properties": {
43
+ "name": { "type": "string" },
44
+ "slug": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$" },
45
+ "description": { "type": "string" },
46
+ "depends_on": { "type": "array", "items": { "type": "string" } },
47
+ "shared_design_concerns": { "type": "array", "items": { "type": "string" } },
48
+ "slice": {
49
+ "type": "object",
50
+ "properties": {
51
+ "start_line": { "type": "integer", "minimum": 1 },
52
+ "end_line": { "type": "integer", "minimum": 1 }
53
+ }
54
+ },
55
+ "epic_type": { "type": "string", "enum": ["design-spike"] },
56
+ "stories": { "type": "array", "items": { "$ref": "#/$defs/Story" } }
57
+ }
58
+ },
59
+ "Story": {
60
+ "type": "object",
61
+ "required": ["title", "slug", "acceptance_criteria", "points", "executor"],
62
+ "properties": {
63
+ "title": { "type": "string" },
64
+ "slug": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$" },
65
+ "acceptance_criteria": { "type": "array", "items": { "type": "string" }, "minItems": 1 },
66
+ "technical_context": { "type": "string" },
67
+ "points": { "type": "integer", "enum": [1, 2, 3, 5, 8, 13] },
68
+ "executor": { "type": "string", "enum": ["claude", "human", "cowork"] },
69
+ "priority": { "type": "string", "enum": ["P0-critical", "P1-high", "P2-medium", "P3-low"] },
70
+ "persona": { "type": "string", "enum": ["impl", "ops", "research"] },
71
+ "blocked_by": { "type": "array", "items": { "type": "string" } },
72
+ "blocks": { "type": "array", "items": { "type": "string" } },
73
+ "labels": { "type": "array", "items": { "type": "string" } }
74
+ }
75
+ }
76
+ }
77
+ }
@@ -0,0 +1,42 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/houseofwolvesllc/claudescrumskill/schemas/SprintStoryReturnSchema.json",
4
+ "title": "SprintStoryReturnSchema",
5
+ "description": "Per-story return value from sprint_pipeline.js. The calling skill persists results to state file and story frontmatter.",
6
+ "type": "object",
7
+ "required": ["storySlug", "status"],
8
+ "properties": {
9
+ "storySlug": {
10
+ "type": "string",
11
+ "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$"
12
+ },
13
+ "status": {
14
+ "type": "string",
15
+ "enum": ["done", "blocked", "failed"]
16
+ },
17
+ "branch": {
18
+ "type": "string",
19
+ "description": "Story branch name created during implementation (e.g., story/12-auth-endpoint)."
20
+ },
21
+ "prUrl": {
22
+ "type": "string",
23
+ "format": "uri",
24
+ "description": "GitHub mode only. PR URL opened by the story branch."
25
+ },
26
+ "commits": {
27
+ "type": "array",
28
+ "items": { "type": "string" },
29
+ "description": "Commit SHAs produced by the story."
30
+ },
31
+ "blockers": {
32
+ "type": "array",
33
+ "items": { "type": "string" },
34
+ "description": "Free-text descriptions of why the story is blocked. Populated when status = blocked."
35
+ },
36
+ "reason": {
37
+ "type": "string",
38
+ "description": "Free-text explanation when status = failed or blocked."
39
+ }
40
+ },
41
+ "additionalProperties": false
42
+ }
@@ -0,0 +1,56 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/houseofwolvesllc/claudescrumskill/schemas/StorySchema.json",
4
+ "title": "StorySchema",
5
+ "description": "Single story shape produced by Pass 2 elaboration; consumed by sprint planning and execution.",
6
+ "type": "object",
7
+ "required": ["title", "slug", "acceptance_criteria", "points", "executor"],
8
+ "properties": {
9
+ "title": { "type": "string" },
10
+ "slug": {
11
+ "type": "string",
12
+ "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$"
13
+ },
14
+ "acceptance_criteria": {
15
+ "type": "array",
16
+ "items": { "type": "string" },
17
+ "minItems": 1
18
+ },
19
+ "technical_context": {
20
+ "type": "string",
21
+ "description": "Architecture notes, relevant files, approach guidance. May be empty if the story body is self-explanatory."
22
+ },
23
+ "points": {
24
+ "type": "integer",
25
+ "enum": [1, 2, 3, 5, 8, 13],
26
+ "description": "Fibonacci estimate per CONVENTIONS.md story point guidelines."
27
+ },
28
+ "executor": {
29
+ "type": "string",
30
+ "enum": ["claude", "human", "cowork"]
31
+ },
32
+ "priority": {
33
+ "type": "string",
34
+ "enum": ["P0-critical", "P1-high", "P2-medium", "P3-low"]
35
+ },
36
+ "persona": {
37
+ "type": "string",
38
+ "enum": ["impl", "ops", "research"],
39
+ "description": "Subagent posture preamble selection. Default is impl."
40
+ },
41
+ "blocked_by": {
42
+ "type": "array",
43
+ "items": { "type": "string" },
44
+ "description": "Slugs (or epic/slug references) of stories that must complete first."
45
+ },
46
+ "blocks": {
47
+ "type": "array",
48
+ "items": { "type": "string" }
49
+ },
50
+ "labels": {
51
+ "type": "array",
52
+ "items": { "type": "string" }
53
+ }
54
+ },
55
+ "additionalProperties": false
56
+ }
@@ -0,0 +1,252 @@
1
+ // sprint_pipeline.js — per-story sprint execution as a pipeline.
2
+ //
3
+ // Invoked by /project-orchestrate Phase 1 Step 3. Replaces the v1.x
4
+ // Task-spawning prose with per-stage barrier removal and concurrency up
5
+ // to min(16, cpu_cores - 2) per the Workflow tool's cap.
6
+ //
7
+ // args: {
8
+ // stories: Story[], // StorySchema-shaped
9
+ // epicSlug: string,
10
+ // releaseBranch: string, // "release/<epic-slug>"
11
+ // contextMdPath?: string, // <paths.context>/<epicSlug>/CONTEXT.md
12
+ // claudeMdPath?: string, // project CLAUDE.md
13
+ // backendMode: "local" | "github" | "jira" | "trello",
14
+ // repoIdentifier?: string, // "owner/repo" — github mode only
15
+ // personaPreambles: Record<string, string> // persona name → preamble text
16
+ // }
17
+ //
18
+ // returns: SprintStoryReturn[] (one per story; failed items filtered to null upstream)
19
+
20
+ export const meta = {
21
+ name: 'sprint-pipeline',
22
+ description: 'Per-story sprint execution: implement → review → verify → open PR',
23
+ phases: [
24
+ { title: 'Implement' },
25
+ { title: 'Review' },
26
+ { title: 'Verify' },
27
+ { title: 'Open PR' },
28
+ ],
29
+ }
30
+
31
+ const REVIEW_VERDICT_SCHEMA = {
32
+ type: 'object',
33
+ required: ['recommendation', 'findings', 'summary'],
34
+ properties: {
35
+ recommendation: { type: 'string', enum: ['accept', 'accept-with-followups', 'block'] },
36
+ findings: {
37
+ type: 'object',
38
+ required: ['critical', 'warning', 'info'],
39
+ properties: {
40
+ critical: { type: 'array' },
41
+ warning: { type: 'array' },
42
+ info: { type: 'array' },
43
+ },
44
+ },
45
+ summary: { type: 'string' },
46
+ },
47
+ }
48
+
49
+ const IMPL_RETURN_SCHEMA = {
50
+ type: 'object',
51
+ required: ['storySlug', 'branch', 'commits'],
52
+ properties: {
53
+ storySlug: { type: 'string' },
54
+ branch: { type: 'string' },
55
+ commits: { type: 'array', items: { type: 'string' } },
56
+ notes: { type: 'string' },
57
+ },
58
+ }
59
+
60
+ const VERIFY_RETURN_SCHEMA = {
61
+ type: 'object',
62
+ required: ['storySlug', 'verifyStatus'],
63
+ properties: {
64
+ storySlug: { type: 'string' },
65
+ verifyStatus: { type: 'string', enum: ['pass', 'warn', 'fail'] },
66
+ notes: { type: 'string' },
67
+ },
68
+ }
69
+
70
+ const SPRINT_STORY_RETURN_SCHEMA = {
71
+ type: 'object',
72
+ required: ['storySlug', 'status'],
73
+ properties: {
74
+ storySlug: { type: 'string' },
75
+ status: { type: 'string', enum: ['done', 'blocked', 'failed'] },
76
+ branch: { type: 'string' },
77
+ prUrl: { type: 'string' },
78
+ commits: { type: 'array', items: { type: 'string' } },
79
+ blockers: { type: 'array', items: { type: 'string' } },
80
+ reason: { type: 'string' },
81
+ },
82
+ }
83
+
84
+ /**
85
+ * Build a SprintStoryReturn-shaped object for short-circuit paths
86
+ * (review-block, verify-fail). The shape conforms to
87
+ * SPRINT_STORY_RETURN_SCHEMA above; keeping the helper alongside ensures
88
+ * any future schema change requires updating both at once.
89
+ */
90
+ function makeSprintStoryReturn({ storySlug, status, branch, commits, prUrl, blockers, reason }) {
91
+ const out = { storySlug, status }
92
+ if (branch !== undefined) out.branch = branch
93
+ if (commits !== undefined) out.commits = commits
94
+ if (prUrl !== undefined) out.prUrl = prUrl
95
+ if (blockers !== undefined) out.blockers = blockers
96
+ if (reason !== undefined) out.reason = reason
97
+ return out
98
+ }
99
+
100
+ const {
101
+ stories,
102
+ epicSlug,
103
+ releaseBranch,
104
+ contextMdPath,
105
+ claudeMdPath,
106
+ backendMode,
107
+ repoIdentifier,
108
+ personaPreambles = {},
109
+ } = args
110
+
111
+ if (!stories || stories.length === 0) {
112
+ log('No stories in sprint — exiting.')
113
+ return []
114
+ }
115
+
116
+ log(`Sprint pipeline: ${stories.length} stories on release branch ${releaseBranch} (backend=${backendMode}).`)
117
+
118
+ function buildImplementPrompt(story) {
119
+ const persona = story.persona || 'impl'
120
+ const preamble = personaPreambles[persona] || ''
121
+ const claudeMdLine = claudeMdPath
122
+ ? `Before writing any code, read ${claudeMdPath} and follow every convention.`
123
+ : 'Read the project CLAUDE.md (if present) and follow every convention.'
124
+ const contextLine = contextMdPath
125
+ ? `Before writing any code, read ${contextMdPath} if it exists. Its Naming, File Layout, Shared Types, and Patterns sections are binding for this epic — they override generic CLAUDE.md conventions for this epic.`
126
+ : ''
127
+ return `${preamble}
128
+
129
+ ---
130
+
131
+ You are implementing story ${story.slug} on release branch ${releaseBranch}.
132
+
133
+ ${claudeMdLine}
134
+ ${contextLine}
135
+
136
+ **Story:** ${story.title}
137
+ **Acceptance criteria:**
138
+ ${(story.acceptance_criteria || []).map(c => ` - ${c}`).join('\n')}
139
+
140
+ **Technical context:** ${story.technical_context || '(none provided)'}
141
+
142
+ **Branch strategy:** Create branch \`story/${story.slug}\` from \`${releaseBranch}\`. Implement. Commit with a clear message. Return the branch name, the commit SHAs, and any notes.
143
+
144
+ Do NOT open a PR yet. Do NOT merge. The next stage handles review.`
145
+ }
146
+
147
+ function buildReviewPrompt(impl, story) {
148
+ return `You are reviewing the implementation of story ${story.slug} on branch ${impl.branch}.
149
+
150
+ Read the diff between ${releaseBranch} and ${impl.branch}.
151
+
152
+ Story acceptance criteria:
153
+ ${(story.acceptance_criteria || []).map(c => ` - ${c}`).join('\n')}
154
+
155
+ Review for: correctness against acceptance criteria, project convention compliance (per CLAUDE.md), and obvious defects. Do NOT bikeshed style the project doesn't enforce.
156
+
157
+ Return a ReviewVerdict: recommendation (accept | accept-with-followups | block), findings grouped by severity, and a one-paragraph summary.`
158
+ }
159
+
160
+ function buildVerifyPrompt(review, story) {
161
+ return `You are running a lightweight verification on story ${story.slug}.
162
+
163
+ If the project has a build/lint/test command, run it on the story branch. If not, perform a smoke read of the changed files to confirm no obvious runtime defects (broken imports, syntax errors, dangling references).
164
+
165
+ Return verifyStatus (pass | warn | fail) and brief notes.`
166
+ }
167
+
168
+ function buildOpenPRPrompt(verify, story, impl) {
169
+ const ghOrLocal =
170
+ backendMode === 'github'
171
+ ? `Open a PR via gh CLI targeting ${releaseBranch}. Capture the PR URL.`
172
+ : `Merge story/${story.slug} into ${releaseBranch} locally. Capture the merge commit SHA.`
173
+ return `You are finalizing story ${story.slug}.
174
+
175
+ Verify status: ${verify.verifyStatus}. Review recommendation: (from prior stage).
176
+
177
+ ${ghOrLocal}
178
+
179
+ Return SprintStoryReturn: storySlug, status (done | blocked | failed), branch, prUrl (github mode) or merge commit (local mode), commits[], blockers[] (if blocked), reason (if failed).`
180
+ }
181
+
182
+ phase('Implement')
183
+ phase('Review')
184
+ phase('Verify')
185
+ phase('Open PR')
186
+
187
+ const results = await pipeline(
188
+ stories,
189
+ // Stage 1: Implement
190
+ story =>
191
+ agent(buildImplementPrompt(story), {
192
+ label: `impl:${story.slug}`,
193
+ phase: 'Implement',
194
+ schema: IMPL_RETURN_SCHEMA,
195
+ }),
196
+ // Stage 2: Review
197
+ (impl, story) =>
198
+ impl
199
+ ? agent(buildReviewPrompt(impl, story), {
200
+ label: `review:${story.slug}`,
201
+ phase: 'Review',
202
+ schema: REVIEW_VERDICT_SCHEMA,
203
+ }).then(review => ({ impl, review }))
204
+ : null,
205
+ // Stage 3: Verify
206
+ (prev, story) =>
207
+ prev
208
+ ? agent(buildVerifyPrompt(prev.review, story), {
209
+ label: `verify:${story.slug}`,
210
+ phase: 'Verify',
211
+ schema: VERIFY_RETURN_SCHEMA,
212
+ }).then(verify => ({ ...prev, verify }))
213
+ : null,
214
+ // Stage 4: Open PR (or local merge)
215
+ (prev, story) => {
216
+ if (!prev) return null
217
+ const { impl, review, verify } = prev
218
+ // If the reviewer said block, short-circuit to blocked status without an openPR call.
219
+ if (review.recommendation === 'block') {
220
+ const blockers = [
221
+ ...review.findings.critical.map(f => f.title),
222
+ ...review.findings.warning.map(f => f.title),
223
+ ]
224
+ return makeSprintStoryReturn({
225
+ storySlug: story.slug,
226
+ status: 'blocked',
227
+ branch: impl.branch,
228
+ commits: impl.commits,
229
+ blockers,
230
+ reason: 'Review recommended block.',
231
+ })
232
+ }
233
+ // If verify failed, also short-circuit.
234
+ if (verify.verifyStatus === 'fail') {
235
+ return makeSprintStoryReturn({
236
+ storySlug: story.slug,
237
+ status: 'blocked',
238
+ branch: impl.branch,
239
+ commits: impl.commits,
240
+ blockers: [verify.notes || 'verification failed'],
241
+ reason: 'Verification failed.',
242
+ })
243
+ }
244
+ return agent(buildOpenPRPrompt(verify, story, impl), {
245
+ label: `pr:${story.slug}`,
246
+ phase: 'Open PR',
247
+ schema: SPRINT_STORY_RETURN_SCHEMA,
248
+ })
249
+ }
250
+ )
251
+
252
+ return results.filter(Boolean)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@houseofwolvesllc/claude-scrum-skill",
3
- "version": "1.8.1",
3
+ "version": "2.0.0",
4
4
  "description": "Claude Code skills for scrum project management — PRD to production release pipeline with project scaffolding, sprint planning, status tracking, sprint releases, full-project emulation testing, autonomous orchestration, and project cleanup.",
5
5
  "bin": {},
6
6
  "publishConfig": {
@@ -32,6 +32,7 @@
32
32
  "files": [
33
33
  ".claude-plugin/",
34
34
  "skills/",
35
- "bin/"
35
+ "bin/",
36
+ "lib/"
36
37
  ]
37
38
  }
@@ -303,6 +303,33 @@ After writing new tests, re-run the full suite to confirm all tests pass and cov
303
303
 
304
304
  ---
305
305
 
306
+ ## Phase 5.5: Multi-Lens Review Panel (v2.0.0+)
307
+
308
+ After fixes are applied (or in `--report-only` mode after the catalog is built) and BEFORE Final Validation, invoke the **review_panel.js** workflow script to run a multi-lens review across the final diff or scoped change set.
309
+
310
+ #### Path Resolution
311
+
312
+ Workflow ships at `<skills-root>/_workflows/review_panel.js`.
313
+
314
+ #### Invocation
315
+
316
+ ```yaml
317
+ diff: <git diff against the pre-cleanup baseline>
318
+ files: [{ path, contents }, ...] # for files that lack a pre-baseline (new files)
319
+ lenses: ["correctness", "security", "style", "tests"] # default; override per project
320
+ projectConventionsPath: <project>/CLAUDE.md # optional
321
+ ```
322
+
323
+ The workflow returns `{ panelVerdict, perLensVerdicts }`. The panel verdict is aggregated per the workflow's rule (any lens blocks → panel blocks; any accept-with-followups → panel accept-with-followups; else accept).
324
+
325
+ #### Apply the panel verdict
326
+
327
+ - `panelVerdict.recommendation === "block"` → record the blocking findings in the cleanup report's Critical section; do NOT proceed to Final Validation; surface the per-lens verdicts to the user.
328
+ - `panelVerdict.recommendation === "accept-with-followups"` → record follow-up findings in the cleanup report; proceed to Final Validation.
329
+ - `panelVerdict.recommendation === "accept"` → proceed to Final Validation.
330
+
331
+ Per-lens verdicts (with `lens` attribution preserved on each finding) are written verbatim to the cleanup report so users can see which lens raised each concern.
332
+
306
333
  ## Phase 6: Final Validation
307
334
 
308
335
  After all fixes (or after cataloging all issues in report-only mode), run a final validation pass.
@@ -505,6 +505,35 @@ Not every project will have all stages. Skip what doesn't apply. Add stages that
505
505
 
506
506
  ---
507
507
 
508
+ ## Phase 5.5: Adversarial Verification of Findings (v2.0.0+)
509
+
510
+ After Phase 5 produces raw findings and BEFORE the Coverage Report is finalized, invoke the **adversarial_verify.js** workflow script to verify each finding via the claimant / skeptic / judge pattern. This lifts emulation from "trust the emulator" to structured verdicts.
511
+
512
+ #### Path Resolution
513
+
514
+ Workflow ships at `<skills-root>/_workflows/adversarial_verify.js` (parent of this SKILL.md's parent → `_workflows/`).
515
+
516
+ #### Invocation
517
+
518
+ Pass the finding list (per `EmulationFindingSchema`) and optional `codebaseContext`:
519
+
520
+ ```yaml
521
+ findings: [<EmulationFinding>, ...] # collected during Phases 1-5
522
+ codebaseContext: { projectRoot: <path>, languages: ["typescript", ...] }
523
+ ```
524
+
525
+ The workflow returns `[{ finding, claim, skeptic, verdict }, ...]` where `verdict.isReal` is a boolean and `verdict.severity_adjustment` may suggest raising/lowering severity.
526
+
527
+ #### Apply the verdicts
528
+
529
+ For each verified finding:
530
+ - `verdict.isReal === false` → demote to Info OR drop entirely (your choice; if dropping, log the false-positive in a separate "Dismissed" section of ISSUES.md).
531
+ - `verdict.isReal === true` AND `verdict.severity_adjustment === "raise"` → bump severity one level.
532
+ - `verdict.isReal === true` AND `verdict.severity_adjustment === "lower"` → drop severity one level (Critical → Warning, Warning → Info).
533
+ - Otherwise keep as-is.
534
+
535
+ Findings that survive verification (and the survivors only) drive the Coverage Report and any hardening PRD downstream skills generate.
536
+
508
537
  ## Phase 6: Coverage Report
509
538
 
510
539
  After the walkthrough, produce a structured report: