@codyswann/lisa 2.56.0 → 2.58.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/package.json CHANGED
@@ -82,7 +82,7 @@
82
82
  "lodash": ">=4.18.1"
83
83
  },
84
84
  "name": "@codyswann/lisa",
85
- "version": "2.56.0",
85
+ "version": "2.58.0",
86
86
  "description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
87
87
  "main": "dist/index.js",
88
88
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.56.0",
3
+ "version": "2.58.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.56.0",
3
+ "version": "2.58.0",
4
4
  "description": "Universal governance: agents, skills, commands, hooks, and rules for all projects.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: verify-prd
3
- description: "Initiative-level PRD acceptance gate. Given a PRD ref/URL (GitHub Issue, Linear project/issue, Notion page, Confluence page, or JIRA issue), resolves the source vendor, reads the PRD body and its generated top-level child work set via the prd-lifecycle-rollup contract (native hierarchy first, machine-readable generated-work section fallback — never reimplementing child enumeration), and confirms every required generated top-level work item is terminal before any verification runs. If any required top-level child is non-terminal, it reports the incomplete child set and STOPS without verifying or transitioning the PRD. When the guard passes, it runs the PASS path: spec-conformance against the original PRD requirements (via the spec-conformance skill) plus empirical verification appropriate to the shipped surface (via verification-lifecycle), and on a CONFORMS verdict with all empirical checks passing transitions the PRD shipped → verified and posts verification evidence. The FAIL path (shipped → blocked + fix issues) and idempotency are handled by sibling work."
3
+ description: "Initiative-level PRD acceptance gate. Given a PRD ref/URL (GitHub Issue, Linear project/issue, Notion page, Confluence page, or JIRA issue), resolves the source vendor, reads the PRD body and its generated top-level child work set via the prd-lifecycle-rollup contract (native hierarchy first, machine-readable generated-work section fallback — never reimplementing child enumeration), and confirms every required generated top-level work item is terminal before any verification runs. If any required top-level child is non-terminal, it reports the incomplete child set and STOPS without verifying or transitioning the PRD. When the guard passes, it runs spec-conformance against the original PRD requirements (via the spec-conformance skill) plus empirical verification appropriate to the shipped surface (via verification-lifecycle). On a CONFORMS verdict with all empirical checks passing it runs the PASS path: transitions the PRD shipped → verified and posts verification evidence. On a PARTIAL/DIVERGES conformance verdict or any failing empirical check it runs the FAIL path: transitions the PRD shipped → blocked (reusing the existing blocked role — no new failure state), posts a product-readable failure report naming which requirements/ACs failed with observed-vs-expected evidence, and creates linked fix issues (via tracker-write) back-linked to the PRD and the failure report, each carrying the captured evidence and acceptance criteria. Re-runs are idempotent: evidence/failure-report comments are regenerated in place via a stable sentinel marker (never appended), fix issues are deduped by a stable PRD-ref + requirement marker (referenced/updated, never duplicated), and the lifecycle transition is a no-op when the PRD already carries the target role (exactly one lifecycle label/status remains) — per the prd-lifecycle-rollup idempotency dedupe key (match by stable ref, never by title)."
4
4
  allowed-tools: ["Skill", "Bash", "Read", "mcp__claude_ai_Notion__notion-fetch", "mcp__claude_ai_Notion__notion-get-comments", "mcp__atlassian__getConfluencePage", "mcp__atlassian__getConfluencePageDescendants", "mcp__atlassian__getJiraIssue", "mcp__atlassian__searchJiraIssuesUsingJql", "mcp__atlassian__getAccessibleAtlassianResources", "mcp__linear-server__get_project", "mcp__linear-server__list_issues", "mcp__linear-server__get_issue", "mcp__linear-server__list_documents", "mcp__linear-server__get_document"]
5
5
  ---
6
6
 
@@ -18,7 +18,7 @@ Do **not** re-prompt once invoked. Like the `*-prd-intake` skills, the caller ha
18
18
 
19
19
  ## Scope of this skill
20
20
 
21
- This skill covers the **read/guard front-half** plus the **PASS path** of PRD-level verification:
21
+ This skill covers the **read/guard front-half**, **both verdict branches** (PASS and FAIL), and the **idempotency** of PRD-level verification:
22
22
 
23
23
  1. Resolve the PRD ref and detect its source vendor.
24
24
  2. Read the PRD body and its **generated top-level child work set** via the `prd-lifecycle-rollup` contract.
@@ -26,13 +26,10 @@ This skill covers the **read/guard front-half** plus the **PASS path** of PRD-le
26
26
  4. **Spec conformance** — when the guard passes, invoke the `spec-conformance` skill with the PRD as the spec source to build a section-by-section coverage matrix against the shipped product (never reimplementing the matrix).
27
27
  5. **Empirical verification** — invoke `verification-lifecycle` to run empirical checks appropriate to the PRD's surface (browser/computer-use, API, CLI, DB, screenshots, logs), honoring the `verification` rule. Quality gates (test/typecheck/lint) are **not** verification.
28
28
  6. **PASS transition + evidence** — when spec conformance is `CONFORMS` **and** every applicable empirical check passes, transition the PRD lifecycle from the resolved `shipped` role to the resolved `verified` role (vendor-neutral via `config-resolution`) and post verification evidence (the coverage matrix + empirical proof artifacts) back on the PRD.
29
+ 7. **FAIL transition + failure report + fix issues** — when spec conformance is `PARTIAL`/`DIVERGES`, or any applicable empirical check fails (or a required surface is unavailable), transition the PRD from the resolved `shipped` role to the resolved `blocked` role (reusing the existing `blocked` role — **no new failure state**, vendor-neutral via `config-resolution`), post a product-readable failure report on the PRD, and create linked fix issues via `tracker-write` for each missing/incorrect/divergent behavior.
30
+ 8. **Idempotency** — every write in Phases 6 and 7 is safe to re-run: evidence/failure-report comments carry a stable sentinel marker and are **regenerated in place** (never appended), fix issues are deduped by a stable PRD-ref + requirement marker (**referenced/updated, never duplicated**), and the lifecycle transition is a **no-op when the PRD already carries the target role** (exactly one lifecycle label/status remains). See **Phase 8 — Idempotency** for the per-write guards.
29
31
 
30
- The remaining phases of PRD-level verification are **out of scope** here and are delivered by sibling work:
31
-
32
- - **FAIL path** — on verification failure (spec conformance not `CONFORMS`, or any empirical check failing), the `shipped → blocked` transition, a product-readable failure report, and linked fix issues for the missing/incorrect behavior.
33
- - **Idempotency** — re-runs producing no duplicate evidence, fix issues, or lifecycle transitions.
34
-
35
- This skill implements only the **PASS** branch of Phase 6. When verification does not pass it stops at the verdict and **leaves the PRD at `shipped`** (it does not transition to `blocked`, does not open fix issues) — that is the FAIL sibling's job. Re-running before the idempotency sibling lands may re-post evidence or re-apply the (idempotent-by-label) transition; full no-duplicate guarantees are the idempotency sibling's job.
32
+ When verification passes, this skill runs the **PASS** branch of Phase 6 (`shipped → verified`). When it does not pass — spec conformance not `CONFORMS`, or any empirical check failing — this skill runs the **FAIL** branch of Phase 7 (`shipped → blocked` + failure report + fix issues); it does **not** leave the PRD at `shipped`. Re-running the skill against the same PRD produces no duplicate evidence comments, no duplicate fix issues, and no duplicate lifecycle labels/statuses — the **Phase 8** guards make each Phase 6/7 write idempotent, exactly as `prd-backlink` regenerates its `## Tickets` section in place and `github-prd-intake` no-ops a rollup on an already-shipped PRD.
36
33
 
37
34
  ## Phase 1 — Resolve the PRD ref and detect the source vendor
38
35
 
@@ -113,7 +110,7 @@ Spec conformance at the PRD level differs from the leaf-ticket conformance run d
113
110
  **Branch on the verdict:**
114
111
 
115
112
  - **`CONFORMS`** — continue to Phase 5 (empirical verification).
116
- - **`PARTIAL` or `DIVERGES`** — verification has **not** passed. Stop the PASS path: record the verdict and the matrix in the output, **leave the PRD at `shipped`**, and do not transition or post a verified-evidence comment. Handing the `shipped → blocked` transition, the product-readable failure report, and the linked fix issues to the FAIL sibling is out of scope here (see [Scope of this skill](#scope-of-this-skill)).
113
+ - **`PARTIAL` or `DIVERGES`** — verification has **not** passed. Do **not** run Phase 5 (empirical verification adds nothing once the spec already diverges) and do **not** enter the PASS path. Record the verdict and the matrix, then go to **Phase 7 FAIL** with a `CONFORMANCE_FAILED` cause: the failed/missing/scope-crept requirements the matrix flagged become the failure report's findings and the seeds for the linked fix issues.
117
114
 
118
115
  ## Phase 5 — Empirical verification of the shipped surface
119
116
 
@@ -137,8 +134,8 @@ If a required surface or its tooling is unavailable, follow the lifecycle's Esca
137
134
 
138
135
  **Branch on the result:**
139
136
 
140
- - **Every applicable empirical check passes** (and is codified where the lifecycle requires) — continue to Phase 6.
141
- - **Any applicable empirical check fails, or a required surface is unavailable** — verification has **not** passed. Stop the PASS path: record what failed/was-blocked in the output, **leave the PRD at `shipped`**, and do not transition or post verified evidence. The `shipped blocked` hop + fix issues are the FAIL sibling's job (out of scope here).
137
+ - **Every applicable empirical check passes** (and is codified where the lifecycle requires) — continue to Phase 6 (PASS).
138
+ - **Any applicable empirical check fails, or a required surface is unavailable** — verification has **not** passed. Record what failed/was-blocked (the check, the tool/command, observed vs expected, and any proof artifacts captured), then go to **Phase 7 FAIL** with an `EMPIRICAL_FAILED` cause: each failed check (or unavailable required surface) becomes a failure-report finding and a seed for a linked fix issue.
142
139
 
143
140
  > **Single-environment note.** In a single-environment project (`main`/production only, no dev/staging), the shipped surface is whatever production exposes. A project with no deployed application, sign-in, or end-to-end environment variables (Lisa itself) verifies on its CLI/dry-run surface — running the documentation/skill build and drift check — which is the empirical surface the PRD's Validation Journey declares. The surface is always PRD-dependent: read the PRD's Empirical Verification Plan and verify what it says ships.
144
141
 
@@ -149,7 +146,7 @@ Reach this phase **only** when **both** are true:
149
146
  - Phase 4 spec conformance returned **`CONFORMS`**, and
150
147
  - Phase 5 every applicable empirical check **passed** (and was codified where required).
151
148
 
152
- If either is false, do not enter this phase — stop at the verdict and leave the PRD at `shipped` (the FAIL sibling owns the `blocked` path).
149
+ If either is false, do not enter this phase — record the verdict and route to **Phase 7 FAIL**, which owns the `shipped → blocked` path.
153
150
 
154
151
  ### 6.1 — Resolve the `verified` and `shipped` roles
155
152
 
@@ -178,31 +175,149 @@ VERIFIED=$(read_role verified prd-verified)
178
175
 
179
176
  ### 6.2 — Transition the PRD `shipped → verified`
180
177
 
181
- Apply the vendor-appropriate transition. This is the `shipped verified` PASS hop the `prd-lifecycle-rollup` rule defines (cite it by slug; this skill is its PASS-path implementation, not a second source of truth):
178
+ **Idempotency guard (no-op if already verified).** Before transitioning, read the PRD's current lifecycle role. If the PRD **already carries `$VERIFIED`**, the transition is a **no-op** — do not re-add the label/status, do not re-remove `$SHIPPED` (already gone). Record it as `already verified (no-op)` and proceed to 6.3 (the evidence comment is still refreshed in place, per Phase 8). This mirrors `github-prd-intake` Phase 3f.1's "no-op if already shipped" guard and the `prd-lifecycle-rollup` "rollup is keyed by the PRD's current state" rule (cite both by slug).
179
+
180
+ Otherwise apply the vendor-appropriate transition. This is the `shipped → verified` PASS hop the `prd-lifecycle-rollup` rule defines (cite it by slug; this skill is its PASS-path implementation, not a second source of truth):
182
181
 
183
182
  - **GitHub / Linear** — remove the `shipped` label and add the `verified` label. For GitHub:
184
183
  ```bash
185
184
  gh issue edit <prd-num> --repo <org>/<repo> --remove-label "$SHIPPED" --add-label "$VERIFIED"
186
185
  ```
187
- Verify exactly **one** PRD-lifecycle label remains afterward (the single-label invariant `github-prd-intake` enforces). For Linear, set the project/issue label equivalently.
188
- - **Notion** — set the PRD page's `notion.statusProperty` (default `Status`) to the resolved `verified` value (default `Verified`).
189
- - **Confluence** — move the PRD page's `parentId` to `confluence.parents.verified` (the parent-page-based lifecycle; Atlassian scoped tokens cannot write labels — see `config-resolution`).
190
- - **JIRA** — transition the PRD issue to the configured `verified` status.
186
+ Verify exactly **one** PRD-lifecycle label remains afterward (the single-label invariant `github-prd-intake` enforces) — a re-run must never leave both `$SHIPPED` and `$VERIFIED`, nor two copies of `$VERIFIED`. For Linear, set the project/issue label equivalently.
187
+ - **Notion** — set the PRD page's `notion.statusProperty` (default `Status`) to the resolved `verified` value (default `Verified`). A status property holds exactly one value, so re-setting the same value is inherently a no-op.
188
+ - **Confluence** — move the PRD page's `parentId` to `confluence.parents.verified` (the parent-page-based lifecycle; Atlassian scoped tokens cannot write labels — see `config-resolution`). A page has exactly one parent, so re-parenting to the same parent is a no-op.
189
+ - **JIRA** — transition the PRD issue to the configured `verified` status. An issue holds exactly one status; if already `verified`, skip the transition.
191
190
 
192
191
  `verified` is the terminal, product-owned PRD state; this skill is the **only** automated writer of it (intake/rollup never set it). Do **not** close or archive the PRD here — closure is governed separately by `prd.rollup.closeOnShipped` at the `shipped` hop, not the verify hop.
193
192
 
194
193
  ### 6.3 — Post verification evidence on the PRD
195
194
 
196
- Post a verification-evidence comment back on the PRD, in the spirit of `tracker-evidence` (the vendor-neutral evidence poster). Because the evidence lands on the **PRD source** — which may be Notion or Confluence, not a tracker ticket — post via the vendor surface that owns the PRD: `gh issue comment` for GitHub, the Linear comment API, the Notion/Confluence page comment surface, or a JIRA comment. Where the PRD lives in the configured `tracker`, you may dispatch through `tracker-evidence`; for Notion/Confluence/cross-vendor PRDs, comment on the PRD page directly. The evidence comment MUST include:
195
+ Post a verification-evidence comment back on the PRD, in the spirit of `tracker-evidence` (the vendor-neutral evidence poster). Because the evidence lands on the **PRD source** — which may be Notion or Confluence, not a tracker ticket — post via the vendor surface that owns the PRD: `gh issue comment` for GitHub, the Linear comment API, the Notion/Confluence page comment surface, or a JIRA comment. Where the PRD lives in the configured `tracker`, you may dispatch through `tracker-evidence`; for Notion/Confluence/cross-vendor PRDs, comment on the PRD page directly.
196
+
197
+ **Idempotent — regenerate the evidence comment in place, never append.** Lead the comment body with the stable sentinel marker `<!-- lisa:verify-prd-evidence -->`. Before posting, look up an existing evidence comment authored by this skill on the PRD whose body contains that sentinel (the same regenerate-don't-append discipline `prd-backlink` uses for its `## Tickets` section; **match by the marker, never by comment text or position**). If one exists, **edit it in place** with the freshly regenerated body; only create a new comment when none exists. Per vendor:
197
198
 
198
- 1. **AI disclosure** — lead with "PRD-level verification by Claude (AI agent, not a human)."
199
- 2. **Verdict line** — `shipped verified PASS`.
200
- 3. **Spec-conformance coverage matrix** — the section-by-section matrix from Phase 4 verbatim, with the `CONFORMS` verdict.
201
- 4. **Empirical proof artifacts** — the Phase 5 artifacts per surface: screenshots (upload via `gh release upload pr-assets <files> --clobber` and reference as plain URLs, per the `tracker-evidence` UI Evidence Checklist), request/response captures, query outputs, log excerpts, and the codified regression test(s) added.
202
- 5. **What was verified** — which PRD acceptance criteria each artifact covers, and the verification surface used.
199
+ - **GitHub** — `gh issue view <prd-num> --repo <org>/<repo> --json comments` and select the comment whose `body` contains `<!-- lisa:verify-prd-evidence -->`; update it with `gh api -X PATCH /repos/<org>/<repo>/issues/comments/<comment-id> -f body=@evidence.md`. Only `gh issue comment <prd-num> --body-file evidence.md` when no marked comment exists.
200
+ - **Linear** — find the existing comment carrying the sentinel and update it via the Linear comment-update API; create only if absent.
201
+ - **Notion / Confluence** — update the existing marked page comment in place; create only if absent.
202
+ - **JIRA** — update the existing marked comment in place; create only if absent.
203
+
204
+ The marked comment is the single canonical evidence comment for the PRD — a re-run refreshes it, never stacking a second one. The evidence comment MUST include:
205
+
206
+ 1. **Sentinel marker** — the literal `<!-- lisa:verify-prd-evidence -->` as the first line, so the next run finds and regenerates this exact comment.
207
+ 2. **AI disclosure** — lead with "PRD-level verification by Claude (AI agent, not a human)."
208
+ 3. **Verdict line** — `shipped → verified — PASS`.
209
+ 4. **Spec-conformance coverage matrix** — the section-by-section matrix from Phase 4 verbatim, with the `CONFORMS` verdict.
210
+ 5. **Empirical proof artifacts** — the Phase 5 artifacts per surface: screenshots (upload via `gh release upload pr-assets <files> --clobber` and reference as plain URLs, per the `tracker-evidence` UI Evidence Checklist), request/response captures, query outputs, log excerpts, and the codified regression test(s) added.
211
+ 6. **What was verified** — which PRD acceptance criteria each artifact covers, and the verification surface used.
203
212
 
204
213
  Then emit the PASS output block (below).
205
214
 
215
+ ## Phase 7 — FAIL: transition `shipped → blocked`, post a failure report, and create fix issues
216
+
217
+ Reach this phase when verification did **not** pass — i.e. **either** is true:
218
+
219
+ - Phase 4 spec conformance returned **`PARTIAL`** or **`DIVERGES`** (`CONFORMANCE_FAILED` cause), or
220
+ - Phase 5 had **any** applicable empirical check fail or a required surface unavailable (`EMPIRICAL_FAILED` cause).
221
+
222
+ This is the FAIL counterpart of the Phase 6 PASS hop. It is the `shipped → blocked` FAIL hop the `prd-lifecycle-rollup` rule defines (cite it by slug; this skill is its FAIL-path implementation, not a second source of truth). It **reuses the existing `blocked` role** — it does **not** introduce a `prd-verification-failed` / `prd-verifying` state, per the "No extra failure states" rule in `prd-lifecycle-rollup`.
223
+
224
+ Carry forward the verdict cause and the concrete **findings** that produced it: from `CONFORMANCE_FAILED`, the matrix's missed/divergent/scope-crept requirements; from `EMPIRICAL_FAILED`, each failing check (the requirement/AC it exercised, the tool/command, observed vs expected, and any captured artifacts). These findings drive both the failure report (7.3) and the fix issues (7.4).
225
+
226
+ ### 7.1 — Resolve the `blocked` and `shipped` roles
227
+
228
+ Resolve the PRD-lifecycle roles from `.lisa.config.json` (then `.lisa.config.local.json` override) per the `config-resolution` rule — the same role-resolution Phase 6.1 and the `*-prd-intake` skills use. **Cite `config-resolution` for the role vocabulary; do not hardcode label strings except as the documented defaults.** Resolution per vendor:
229
+
230
+ | Vendor | `shipped` role | `blocked` role | Default `blocked` |
231
+ |---|---|---|---|
232
+ | **GitHub** | `github.labels.prd.shipped` | `github.labels.prd.blocked` | `prd-blocked` (label) |
233
+ | **Linear** | `linear.labels.prd.shipped` | `linear.labels.prd.blocked` | `prd-blocked` (project/issue label) |
234
+ | **Notion** | `notion.values.shipped` | `notion.values.blocked` | `Blocked` (status value) |
235
+ | **Confluence** | `confluence.parents.shipped` | `confluence.parents.blocked` | the `Blocked` parent page id |
236
+ | **JIRA** | the configured shipped status | the configured blocked status | per `config-resolution` |
237
+
238
+ For GitHub, resolve with the same helper Phase 6.1 / `github-prd-intake` use:
239
+
240
+ ```bash
241
+ read_role() { # role default → resolved value (local override wins)
242
+ local role="$1" default="$2" local_v global_v
243
+ local_v=$(jq -r ".github.labels.prd.${role} // empty" .lisa.config.local.json 2>/dev/null)
244
+ global_v=$(jq -r ".github.labels.prd.${role} // empty" .lisa.config.json 2>/dev/null)
245
+ echo "${local_v:-${global_v:-$default}}"
246
+ }
247
+ SHIPPED=$(read_role shipped prd-shipped)
248
+ BLOCKED=$(read_role blocked prd-blocked)
249
+ ```
250
+
251
+ ### 7.2 — Transition the PRD `shipped → blocked`
252
+
253
+ **Idempotency guard (no-op if already blocked).** Before transitioning, read the PRD's current lifecycle role. If the PRD **already carries `$BLOCKED`** (the common re-run-after-a-previous-failure case — same unsatisfiable requirement still missing), the transition is a **no-op** — do not re-add the label/status, do not re-remove `$SHIPPED` (already gone). Record it as `already blocked (no-op)` and proceed to 7.3, where the existing failure report is **updated in place** (not stacked) and 7.4, where existing fix issues are **referenced** rather than re-created. This mirrors `github-prd-intake` Phase 3f.1's "no-op if already shipped" guard and the `prd-lifecycle-rollup` "rollup is keyed by the PRD's current state" rule (cite both by slug).
254
+
255
+ Otherwise apply the vendor-appropriate transition. This is the `shipped → blocked` FAIL hop from `prd-lifecycle-rollup` (cite it by slug):
256
+
257
+ - **GitHub / Linear** — remove the `shipped` label and add the `blocked` label. For GitHub:
258
+ ```bash
259
+ gh issue edit <prd-num> --repo <org>/<repo> --remove-label "$SHIPPED" --add-label "$BLOCKED"
260
+ ```
261
+ Verify exactly **one** PRD-lifecycle label remains afterward (the single-label invariant `github-prd-intake` enforces) — a re-run must never leave both `$SHIPPED` and `$BLOCKED`, nor two copies of `$BLOCKED`. For Linear, set the project/issue label equivalently.
262
+ - **Notion** — set the PRD page's `notion.statusProperty` (default `Status`) to the resolved `blocked` value (default `Blocked`). A status property holds exactly one value, so re-setting the same value is inherently a no-op.
263
+ - **Confluence** — move the PRD page's `parentId` to `confluence.parents.blocked` (the parent-page-based lifecycle; Atlassian scoped tokens cannot write labels — see `config-resolution`). A page has exactly one parent, so re-parenting to the same parent is a no-op.
264
+ - **JIRA** — transition the PRD issue to the configured `blocked` status. An issue holds exactly one status; if already `blocked`, skip the transition.
265
+
266
+ Do **not** close or archive the PRD here — `blocked` signals "verification failed; human attention required," not "done." The PRD stays open so product can see it failed acceptance.
267
+
268
+ ### 7.3 — Post a product-readable failure report on the PRD
269
+
270
+ Post a **failure report** comment back on the PRD, via the same vendor surface Phase 6.3 uses for evidence (`gh issue comment` for GitHub, the Linear comment API, the Notion/Confluence page comment surface, or a JIRA comment; dispatch through `tracker-evidence` where the PRD lives in the configured `tracker`). The report is written for a **non-engineer product owner** — plain language, no stack traces dumped raw. Capture its URL/anchor so the fix issues in 7.4 can back-link to it.
271
+
272
+ **Idempotent — regenerate the failure report in place, never append.** Lead the comment body with the stable sentinel marker `<!-- lisa:verify-prd-failure-report -->`. Before posting, look up an existing failure-report comment on the PRD whose body contains that sentinel (**match by the marker, never by comment text or position** — the same regenerate-don't-append discipline as Phase 6.3). If one exists, **edit it in place** with the freshly regenerated findings (so a re-run-after-a-previous-failure refreshes the same report rather than stacking a second one); only create a new comment when none exists. The GitHub mechanics are identical to Phase 6.3 (`gh issue view --json comments` to find the marked comment, `gh api -X PATCH .../issues/comments/<id>` to update, `gh issue comment` only when absent). It MUST include:
273
+
274
+ 1. **Sentinel marker** — the literal `<!-- lisa:verify-prd-failure-report -->` as the first line, so the next run finds and regenerates this exact comment.
275
+ 2. **AI disclosure** — lead with "PRD-level verification by Claude (AI agent, not a human)."
276
+ 3. **Verdict line** — `shipped → blocked — FAIL` and the cause (`CONFORMANCE_FAILED` or `EMPIRICAL_FAILED`).
277
+ 4. **What failed, in plain language** — for each finding, name the **specific PRD requirement / acceptance criterion** that was not met, then **what was expected vs what was observed** (the empirical evidence: what was checked, what the shipped product did instead). One bullet per finding so product can follow each independently.
278
+ 5. **Spec-conformance coverage matrix** — for a `CONFORMANCE_FAILED` cause, the section-by-section matrix from Phase 4 verbatim with the `PARTIAL`/`DIVERGES` verdict, so the missed/divergent/scope-crept rows are visible.
279
+ 6. **Proof artifacts** — any captured empirical artifacts (screenshots uploaded via `gh release upload pr-assets <files> --clobber` and referenced as plain URLs per the `tracker-evidence` UI Evidence Checklist, request/response captures, query outputs, log excerpts).
280
+ 7. **Fix issues** — a list of the fix issues created/referenced in 7.4 (filled in after 7.4 runs, or posted as a brief follow-up edit), so the report is the single product-facing index of "what's wrong and where it's being fixed."
281
+
282
+ ### 7.4 — Create linked fix issues for the missing/incorrect behavior
283
+
284
+ For **each** failed/missing/incorrect/divergent finding, create a **fix issue** via `tracker-write` (the vendor-neutral writer) — never by hand-rolling `gh issue create`, so each issue passes the same quality gates (`tracker-validate`) every Lisa ticket does: three-audience description, **Gherkin acceptance criteria**, labels, and explicit relationship discovery. Group findings that share one root cause into one fix issue; do not fan out one issue per matrix cell when several rows are the same defect.
285
+
286
+ **Idempotent — dedupe fix issues by a stable marker; reference/update, never duplicate.** This is the "re-run after a previous failure with the same missing behavior" scenario: the prior run already opened a fix issue for that requirement, so the re-run must **find and reuse it**, not create a second one. Apply the `prd-lifecycle-rollup` idempotency dedupe key discipline (**match by a stable ref, never by title**):
287
+
288
+ 1. **Compute a stable dedupe key per finding** — the PRD ref plus a stable requirement/AC identity (e.g. the AC's heading/number or a slug of the requirement), independent of any mutable wording. Encode it in the fix-issue body as the marker `<!-- lisa:verify-prd-fix prd=<prd-ref> req=<stable-req-id> -->`.
289
+ 2. **Look up an existing OPEN fix issue carrying that exact marker** before creating anything. On GitHub, search the repo for open issues whose body contains the marker (`gh issue list --repo <org>/<repo> --state open --search '"<!-- lisa:verify-prd-fix prd=<prd-ref> req=<stable-req-id> -->"' --json number,url,body` — or fetch and grep the marker); on Linear/JIRA, query by the marker stored in the body/a custom field. **Match on the marker, never on the issue title** (a title may have been edited; the marker is the stable identity).
290
+ 3. **If a matching open fix issue exists, reference/update it — do not create a duplicate.** Refresh its captured evidence (the latest observed-vs-expected) and re-affirm the back-links to the PRD and the regenerated failure report, then fold its existing ref into the failure report's **Fix issues** list. A closed prior fix issue does **not** suppress a new one — if the requirement is failing again after the fix was closed, that is a regression and a fresh fix issue is correct.
291
+ 4. **Only when no matching open fix issue exists, create a new one** via `tracker-write`.
292
+
293
+ Each fix issue (whether freshly created or referenced/updated) MUST:
294
+
295
+ 1. **Carry the dedupe marker** — `<!-- lisa:verify-prd-fix prd=<prd-ref> req=<stable-req-id> -->` in its body, so the next run finds and reuses it.
296
+ 2. **Reference the specific failed requirement/AC** — quote or cite the exact PRD requirement / acceptance criterion the finding violated, so the fix is scoped to a real gap (not a vague "make it work").
297
+ 3. **Carry the captured evidence** — the observed-vs-expected from the failure report (what was checked, what was expected, what the shipped product did), so an implementer can reproduce without re-deriving it.
298
+ 4. **Back-link to the PRD and the failure report** — link to the PRD (so the fix rolls back up to the initiative) and to the failure-report comment from 7.3 (so the full context is one click away). On GitHub, reference the PRD issue number and the failure-report comment URL in the body and, where supported, as a sub-issue/`Relates to` link; on Linear, set the relation; on JIRA, add the issue link and remote link.
299
+ 5. **Have acceptance criteria** — Gherkin ACs describing the corrected behavior (what "fixed" looks like), enforced by `tracker-write` → the vendor `*-validate-issue` gate.
300
+
301
+ Pass each new fix issue's spec to `tracker-write` (which dispatches to `github-write-issue` / `jira-write-ticket` / `linear-write-issue` per config). Collect the created **and referenced** refs/URLs and fold them into the failure report's **Fix issues** list (7.3 item 7).
302
+
303
+ > **Why not reopen children?** The generated top-level children are already terminal (that is the Phase 3 precondition for verification). A failed PRD-level acceptance is a **new** defect discovered against the shipped initiative, so it gets **new** fix issues linked to the PRD — not a reopen of closed build tickets, which would corrupt their build lifecycle (`leaf-only-lifecycle`).
304
+
305
+ Then emit the FAIL output block (below).
306
+
307
+ ## Phase 8 — Idempotency: re-runs produce no duplicates
308
+
309
+ `/lisa:verify-prd` MUST be safe to re-run against the same PRD — after a fix attempt, in a batch sweep, or simply twice. A re-run produces **no duplicate evidence comments, no duplicate fix issues, and no duplicate lifecycle labels/statuses**. This is the same guarantee `prd-backlink` gives for its `## Tickets` section and `github-prd-intake` gives for its rollup; this skill consumes the `prd-lifecycle-rollup` rule's **idempotency dedupe key** (cite by slug — **match by stable ref, never by title**), it does not invent a second one.
310
+
311
+ The guards are woven into Phases 6 and 7 above; this phase collects them as one contract:
312
+
313
+ 1. **Evidence / failure-report comments — regenerate in place, never append.** Each is led by a stable HTML-comment sentinel: `<!-- lisa:verify-prd-evidence -->` (PASS, Phase 6.3) and `<!-- lisa:verify-prd-failure-report -->` (FAIL, Phase 7.3). Before posting, find the existing comment whose body contains the sentinel and **edit it in place**; create a new comment only when none exists. The sentinel is matched literally — never the comment text, author display name, or position. A second run thus refreshes the one canonical comment rather than stacking a duplicate (the regenerate-don't-append discipline from `prd-backlink`).
314
+
315
+ 2. **Fix issues — dedupe by a stable marker, reference don't duplicate.** Each fix issue carries `<!-- lisa:verify-prd-fix prd=<prd-ref> req=<stable-req-id> -->`, keyed by the PRD ref + a stable requirement/AC identity. Before creating a fix issue, search for an **open** issue carrying that exact marker; if found, reference/update it instead of creating a second one (Phase 7.4). The dedupe key is the marker (a stable ref), **never the issue title** — a renamed fix issue is still matched by its marker, and two distinct requirements get two distinct markers even if their titles collide (`prd-lifecycle-rollup`: "Match by stable ref, never by title"). A *closed* prior fix issue does not suppress a new one (a re-failure after a closed fix is a genuine regression).
316
+
317
+ 3. **Lifecycle transition — no-op when already at the target role.** The Phase 6.2 / 7.2 transition is keyed by the PRD's current state: if the PRD already carries `$VERIFIED` (PASS) or `$BLOCKED` (FAIL), the transition is a no-op — no re-label, no second copy of the label/status — mirroring `github-prd-intake` Phase 3f.1's "no-op if already shipped." After any transition, exactly **one** PRD-lifecycle label/status remains (the single-label invariant); a re-run never leaves both `$SHIPPED` and the target role, nor two copies of the target role. For Notion/Confluence/JIRA the single-value status/parent makes re-setting the same value inherently idempotent.
318
+
319
+ Because every Phase 6/7 write is one of these three idempotent operations, the **whole skill is idempotent**: the end state after N runs equals the end state after 1 run — one evidence-or-failure comment, one fix issue per still-failing requirement, one lifecycle label/status. Computing the verdict itself is a pure function of the PRD's current state and its children's current states, so recomputing it on a re-run is safe (`prd-lifecycle-rollup` idempotency rule).
320
+
206
321
  ## Output
207
322
 
208
323
  Emit a single fenced text block so callers can parse it.
@@ -228,28 +343,32 @@ Verdict: <CONFORMS | PARTIAL | DIVERGES>
228
343
  Surface: <browser | api | cli | db | logs | ...> (PRD-dependent)
229
344
  <each check — tool/command → PASS/FAIL → artifact ref; codified test(s)>
230
345
 
231
- ### Lifecycle transition (only on PASS)
232
- shipped → verified (role: <resolved verified role>) evidence posted: <link>
346
+ ### Lifecycle transition (PASS or FAIL)
347
+ shipped → verified (role: <resolved verified role>) evidence posted: <link> # on VERIFIED_PASS (re-run: evidence comment regenerated in place; transition no-op if already verified)
348
+ shipped → blocked (role: <resolved blocked role>) failure report: <link> fix issues: <refs> # on CONFORMANCE_FAILED | EMPIRICAL_FAILED (re-run: failure report regenerated in place; fix issues deduped by marker; transition no-op if already blocked)
233
349
 
234
350
  ### Verdict: VERIFIED_PASS | CONFORMANCE_FAILED | EMPIRICAL_FAILED | GUARD_BLOCKED | NO_CHILDREN
235
351
  ```
236
352
 
237
353
  - `GUARD_BLOCKED` — one or more required top-level children are non-terminal; verification did not run; the PRD was left at `shipped`.
238
354
  - `NO_CHILDREN` — no generated top-level children found; cannot verify; the PRD was left untouched.
239
- - `CONFORMANCE_FAILED` — guard passed but spec conformance returned `PARTIAL`/`DIVERGES`; empirical verification did not run; the PRD was left at `shipped` (the `shipped → blocked` transition + fix issues are the FAIL sibling's job).
240
- - `EMPIRICAL_FAILED` — guard passed and conformance `CONFORMS`, but an applicable empirical check failed or a required surface was unavailable; the PRD was left at `shipped` (FAIL sibling owns the `blocked` path).
241
- - `VERIFIED_PASS` — guard passed, conformance `CONFORMS`, every applicable empirical check passed and was codified; the PRD was transitioned `shipped → verified` and verification evidence was posted.
355
+ - `CONFORMANCE_FAILED` — guard passed but spec conformance returned `PARTIAL`/`DIVERGES`; empirical verification was skipped; the FAIL path ran — the PRD was transitioned `shipped → blocked` (reusing the `blocked` role), a product-readable failure report was posted, and linked fix issues were created (Phase 7).
356
+ - `EMPIRICAL_FAILED` — guard passed and conformance `CONFORMS`, but an applicable empirical check failed or a required surface was unavailable; the FAIL path ran — the PRD was transitioned `shipped → blocked` (reusing the `blocked` role), a product-readable failure report was posted, and linked fix issues were created (Phase 7).
357
+ - `VERIFIED_PASS` — guard passed, conformance `CONFORMS`, every applicable empirical check passed and was codified; the PRD was transitioned `shipped → verified` and verification evidence was posted (Phase 6).
242
358
 
243
359
  ## Rules
244
360
 
245
- - **The only lifecycle write is the PASS hop `shipped → verified`.** The front-half (resolve → read child set → guard) is read-only and never transitions the PRD. The only write this skill performs is the Phase 6 PASS hop and **only** when spec conformance is `CONFORMS` and every applicable empirical check passes. The guard-blocked, no-children, conformance-failed, and empirical-failed paths all leave the PRD at `shipped` untouched. The `shipped blocked` FAIL hop, fix issues, and re-run idempotency are sibling work (out of scope).
361
+ - **The lifecycle writes are the PASS hop `shipped → verified` and the FAIL hop `shipped → blocked`.** The front-half (resolve → read child set → guard) is read-only and never transitions the PRD. After the guard passes and verification runs, this skill writes exactly one of two transitions: the Phase 6 PASS hop `shipped verified` (when spec conformance is `CONFORMS` and every applicable empirical check passes), or the Phase 7 FAIL hop `shipped blocked` (when conformance is `PARTIAL`/`DIVERGES` or any applicable empirical check fails). The FAIL hop **reuses the existing `blocked` role it introduces no new failure state.** The guard-blocked and no-children paths run no verification and leave the PRD at `shipped` untouched.
362
+ - **Every write is idempotent (Phase 8).** Re-running the skill against the same PRD produces no duplicate evidence/failure-report comments, no duplicate fix issues, and no duplicate lifecycle labels/statuses. Evidence and failure-report comments are regenerated in place via a stable sentinel marker (`<!-- lisa:verify-prd-evidence -->` / `<!-- lisa:verify-prd-failure-report -->`); fix issues are deduped by a stable PRD-ref + requirement marker (`<!-- lisa:verify-prd-fix prd=… req=… -->`) and referenced/updated rather than re-created; the lifecycle transition is a no-op when the PRD already carries the target role, leaving exactly one lifecycle label/status. The dedupe key is the `prd-lifecycle-rollup` idempotency dedupe key — **match by stable ref, never by title** — and the no-op-already-at-target-role guard mirrors `github-prd-intake` Phase 3f.1.
363
+ - **The FAIL path opens fix issues via `tracker-write`, never by hand.** Each fix issue is created through the vendor-neutral writer so it passes the same `tracker-validate` quality gate (three-audience description, Gherkin ACs, labels, relationships) every Lisa ticket does. Fix issues are **new** defects against the shipped initiative, back-linked to the PRD and the failure report — never reopens of the already-terminal generated children (`leaf-only-lifecycle`).
246
364
  - **Never reimplement child enumeration.** Consume the recorded PRD→child relationship (`prd-lifecycle-rollup` native linking + machine-readable generated-work section). The two-source read here mirrors `github-prd-intake` Phase 3f.2 — same sources, same dedupe-by-child-ref, same top-level-only boundary.
247
365
  - **Never reimplement spec conformance or verification.** Phase 4 invokes the `spec-conformance` skill (the single source of truth for the coverage matrix and the `CONFORMS`/`PARTIAL`/`DIVERGES` verdict); Phase 5 invokes `verification-lifecycle` (which in turn invokes `codify-verification` and, for UI, `product-walkthrough`). This skill orchestrates those skills against the PRD; it does not duplicate their logic.
248
366
  - **Quality gates are not verification.** Tests, typecheck, and lint are prerequisites enforced by hooks/CI. Phase 5 requires running the actual shipped system and observing results on a surface chosen from what the PRD delivered — never substituting a green test suite for empirical proof (`verification` rule).
249
367
  - **The verification surface is PRD-dependent.** Classify the empirical surface (browser/API/CLI/DB/logs/…) from what the PRD shipped; do not assume a fixed surface. A single-environment project with no deployed app verifies on its CLI/dry-run surface per the PRD's Empirical Verification Plan.
250
368
  - **`verified` is product-owned and terminal.** This skill is the only automated writer of the `verified` role; intake/rollup never set it. The PASS hop does not close or archive the PRD (closure is governed by `prd.rollup.closeOnShipped` at the `shipped` hop).
369
+ - **`blocked` is reused, not invented, and is non-terminal.** The FAIL hop sets the existing `blocked` PRD role (`config-resolution`) — the same role intake uses for failed validation — so the lifecycle stays small (`prd-lifecycle-rollup` "No extra failure states"). `blocked` means "verification failed; human attention required"; the FAIL hop never closes or archives the PRD.
251
370
  - **Top-level only.** Exclude leaf Sub-tasks and Stories nested under a generated Epic. The PRD owns its top-level work; those top-level units own their descendants (`prd-lifecycle-rollup` generated-top-level-work contract).
252
- - **Cite, don't restate.** The generated-top-level-work boundary, the per-vendor terminal predicate, the env-keyed `done` resolution, the dedupe-by-child-ref idempotency key, and the `shipped → verified` PASS hop all come from the `prd-lifecycle-rollup` rule; the `verified`/`shipped` role vocabulary comes from `config-resolution`. This skill is a consumer of those contracts, not a second source of truth.
371
+ - **Cite, don't restate.** The generated-top-level-work boundary, the per-vendor terminal predicate, the env-keyed `done` resolution, the dedupe-by-child-ref idempotency key, and the `shipped → verified | blocked` PRD-level verification hops all come from the `prd-lifecycle-rollup` rule; the `verified`/`shipped`/`blocked` role vocabulary comes from `config-resolution`. This skill is a consumer of those contracts, not a second source of truth.
253
372
 
254
373
  ## Related skills
255
374
 
@@ -257,11 +376,14 @@ shipped → verified (role: <resolved verified role>) evidence posted: <link
257
376
  - `verification-lifecycle` — Phase 5 invokes it to run empirical verification of the shipped surface (classify → check tooling → plan → execute → codify → loop). It in turn invokes `codify-verification` and, for UI surfaces, `product-walkthrough`.
258
377
  - `codify-verification` — turns each passing empirical verification into a regression test so the PRD's verified behavior cannot silently regress; invoked transitively via `verification-lifecycle`.
259
378
  - `product-walkthrough` — drives the live product through a real browser to ground UI-surface verification and the evidence comment in what actually renders.
260
- - `tracker-evidence` — the vendor-neutral evidence poster whose UI Evidence Checklist and `pr-assets` upload mechanics Phase 6.3 follows when posting the verification evidence comment on the PRD.
379
+ - `tracker-evidence` — the vendor-neutral evidence poster whose UI Evidence Checklist and `pr-assets` upload mechanics Phase 6.3 (PASS evidence) and Phase 7.3 (FAIL failure report) follow when commenting on the PRD.
380
+ - `tracker-write` — the vendor-neutral ticket writer Phase 7.4 invokes to create each linked fix issue (dispatching to `github-write-issue` / `jira-write-ticket` / `linear-write-issue` per config), so every fix issue clears the `tracker-validate` quality gate (Gherkin ACs, three-audience description, labels, relationships). This skill never hand-rolls issue creation.
381
+ - `prd-backlink` — the regenerate-in-place-via-marker idempotency pattern Phase 6.3 / 7.3 / 8 follow: it regenerates its `## Tickets` section from the current child set on every run (never appending) and dedupes by child-ref. The evidence/failure-report sentinel comments here apply the same discipline to PRD comments.
382
+ - `github-prd-intake` — the no-op-if-already-at-target-role guard Phase 6.2 / 7.2 / 8 mirror: its Phase 3f.1 rollup is a no-op on a PRD already carrying `$SHIPPED`, and it enforces the single-label invariant after every transition. This skill applies the same guard to the `verified` / `blocked` hops.
261
383
 
262
384
  ## Related rules
263
385
 
264
- - `prd-lifecycle-rollup` — the vendor-neutral source of truth for PRD→generated-top-level-work ownership, the per-vendor terminal predicate, the `shipped` rollup, the `shipped → verified | blocked` PRD-level verification hops, and the child-ref idempotency dedupe key. This skill consumes that contract — including the `shipped → verified` PASS hop it implements — citing the rule by slug rather than restating its taxonomy.
386
+ - `prd-lifecycle-rollup` — the vendor-neutral source of truth for PRD→generated-top-level-work ownership, the per-vendor terminal predicate, the `shipped` rollup, the `shipped → verified | blocked` PRD-level verification hops, the "no extra failure states" rule (the FAIL hop reuses `blocked`), and the **idempotency dedupe key** ("match by stable ref, never by title"; no-op already-shipped rollup). This skill consumes that contract — implementing the `shipped → verified` PASS hop, the `shipped → blocked` FAIL hop, and the Phase 8 idempotency guards (marker-based comment regeneration, marker-based fix-issue dedupe, no-op-already-at-target-role transition) — citing the rule by slug rather than restating its taxonomy.
265
387
  - `verification` — defines what counts as empirical verification (the Verification Types table) and that quality gates (test/typecheck/lint) are prerequisites, not verification. Phase 5 honors it when classifying and running the surface-appropriate checks.
266
388
  - `leaf-only-lifecycle` — governs the build lifecycle of leaf work units and how a generated Epic rolls up from its own children; this skill trusts that bottom-up rollup when reading a top-level child's resolved state.
267
- - `config-resolution` — the PRD-lifecycle role vocabulary (`shipped`, `verified`, `blocked`), the per-vendor `verified` role maps (`prd-verified` label for GitHub/Linear, `Verified` status for Notion, `confluence.parents.verified` parent page) Phase 6.1 resolves, and the env-keyed `done` map the terminal predicate resolves against.
389
+ - `config-resolution` — the PRD-lifecycle role vocabulary (`shipped`, `verified`, `blocked`), the per-vendor `verified` role maps (`prd-verified` label for GitHub/Linear, `Verified` status for Notion, `confluence.parents.verified` parent page) Phase 6.1 resolves, the per-vendor `blocked` role maps (`prd-blocked` label for GitHub/Linear, `Blocked` status for Notion, `confluence.parents.blocked` parent page) Phase 7.1 resolves, and the env-keyed `done` map the terminal predicate resolves against.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.56.0",
3
+ "version": "2.58.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.56.0",
3
+ "version": "2.58.0",
4
4
  "description": "AWS CDK-specific Lisa plugin.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.56.0",
3
+ "version": "2.58.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.56.0",
3
+ "version": "2.58.0",
4
4
  "description": "Expo and React Native-specific skills, agents, rules, and MCP servers.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.56.0",
3
+ "version": "2.58.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.56.0",
3
+ "version": "2.58.0",
4
4
  "description": "Harper/Fabric-specific Lisa rules for TypeScript component apps.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.56.0",
3
+ "version": "2.58.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.56.0",
3
+ "version": "2.58.0",
4
4
  "description": "NestJS-specific skills and migration write-protection hooks.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.56.0",
3
+ "version": "2.58.0",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.56.0",
3
+ "version": "2.58.0",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.56.0",
3
+ "version": "2.58.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.56.0",
3
+ "version": "2.58.0",
4
4
  "description": "Ruby on Rails-specific skills and hooks for RuboCop and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.56.0",
3
+ "version": "2.58.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.56.0",
3
+ "version": "2.58.0",
4
4
  "description": "TypeScript-specific hooks for formatting, linting, and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.56.0",
3
+ "version": "2.58.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.56.0",
3
+ "version": "2.58.0",
4
4
  "description": "Distributable LLM Wiki kernel — ingest, query, lint, and maintain a git-native markdown knowledge base across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: verify-prd
3
- description: "Initiative-level PRD acceptance gate. Given a PRD ref/URL (GitHub Issue, Linear project/issue, Notion page, Confluence page, or JIRA issue), resolves the source vendor, reads the PRD body and its generated top-level child work set via the prd-lifecycle-rollup contract (native hierarchy first, machine-readable generated-work section fallback — never reimplementing child enumeration), and confirms every required generated top-level work item is terminal before any verification runs. If any required top-level child is non-terminal, it reports the incomplete child set and STOPS without verifying or transitioning the PRD. When the guard passes, it runs the PASS path: spec-conformance against the original PRD requirements (via the spec-conformance skill) plus empirical verification appropriate to the shipped surface (via verification-lifecycle), and on a CONFORMS verdict with all empirical checks passing transitions the PRD shipped → verified and posts verification evidence. The FAIL path (shipped → blocked + fix issues) and idempotency are handled by sibling work."
3
+ description: "Initiative-level PRD acceptance gate. Given a PRD ref/URL (GitHub Issue, Linear project/issue, Notion page, Confluence page, or JIRA issue), resolves the source vendor, reads the PRD body and its generated top-level child work set via the prd-lifecycle-rollup contract (native hierarchy first, machine-readable generated-work section fallback — never reimplementing child enumeration), and confirms every required generated top-level work item is terminal before any verification runs. If any required top-level child is non-terminal, it reports the incomplete child set and STOPS without verifying or transitioning the PRD. When the guard passes, it runs spec-conformance against the original PRD requirements (via the spec-conformance skill) plus empirical verification appropriate to the shipped surface (via verification-lifecycle). On a CONFORMS verdict with all empirical checks passing it runs the PASS path: transitions the PRD shipped → verified and posts verification evidence. On a PARTIAL/DIVERGES conformance verdict or any failing empirical check it runs the FAIL path: transitions the PRD shipped → blocked (reusing the existing blocked role — no new failure state), posts a product-readable failure report naming which requirements/ACs failed with observed-vs-expected evidence, and creates linked fix issues (via tracker-write) back-linked to the PRD and the failure report, each carrying the captured evidence and acceptance criteria. Re-runs are idempotent: evidence/failure-report comments are regenerated in place via a stable sentinel marker (never appended), fix issues are deduped by a stable PRD-ref + requirement marker (referenced/updated, never duplicated), and the lifecycle transition is a no-op when the PRD already carries the target role (exactly one lifecycle label/status remains) — per the prd-lifecycle-rollup idempotency dedupe key (match by stable ref, never by title)."
4
4
  allowed-tools: ["Skill", "Bash", "Read", "mcp__claude_ai_Notion__notion-fetch", "mcp__claude_ai_Notion__notion-get-comments", "mcp__atlassian__getConfluencePage", "mcp__atlassian__getConfluencePageDescendants", "mcp__atlassian__getJiraIssue", "mcp__atlassian__searchJiraIssuesUsingJql", "mcp__atlassian__getAccessibleAtlassianResources", "mcp__linear-server__get_project", "mcp__linear-server__list_issues", "mcp__linear-server__get_issue", "mcp__linear-server__list_documents", "mcp__linear-server__get_document"]
5
5
  ---
6
6
 
@@ -18,7 +18,7 @@ Do **not** re-prompt once invoked. Like the `*-prd-intake` skills, the caller ha
18
18
 
19
19
  ## Scope of this skill
20
20
 
21
- This skill covers the **read/guard front-half** plus the **PASS path** of PRD-level verification:
21
+ This skill covers the **read/guard front-half**, **both verdict branches** (PASS and FAIL), and the **idempotency** of PRD-level verification:
22
22
 
23
23
  1. Resolve the PRD ref and detect its source vendor.
24
24
  2. Read the PRD body and its **generated top-level child work set** via the `prd-lifecycle-rollup` contract.
@@ -26,13 +26,10 @@ This skill covers the **read/guard front-half** plus the **PASS path** of PRD-le
26
26
  4. **Spec conformance** — when the guard passes, invoke the `spec-conformance` skill with the PRD as the spec source to build a section-by-section coverage matrix against the shipped product (never reimplementing the matrix).
27
27
  5. **Empirical verification** — invoke `verification-lifecycle` to run empirical checks appropriate to the PRD's surface (browser/computer-use, API, CLI, DB, screenshots, logs), honoring the `verification` rule. Quality gates (test/typecheck/lint) are **not** verification.
28
28
  6. **PASS transition + evidence** — when spec conformance is `CONFORMS` **and** every applicable empirical check passes, transition the PRD lifecycle from the resolved `shipped` role to the resolved `verified` role (vendor-neutral via `config-resolution`) and post verification evidence (the coverage matrix + empirical proof artifacts) back on the PRD.
29
+ 7. **FAIL transition + failure report + fix issues** — when spec conformance is `PARTIAL`/`DIVERGES`, or any applicable empirical check fails (or a required surface is unavailable), transition the PRD from the resolved `shipped` role to the resolved `blocked` role (reusing the existing `blocked` role — **no new failure state**, vendor-neutral via `config-resolution`), post a product-readable failure report on the PRD, and create linked fix issues via `tracker-write` for each missing/incorrect/divergent behavior.
30
+ 8. **Idempotency** — every write in Phases 6 and 7 is safe to re-run: evidence/failure-report comments carry a stable sentinel marker and are **regenerated in place** (never appended), fix issues are deduped by a stable PRD-ref + requirement marker (**referenced/updated, never duplicated**), and the lifecycle transition is a **no-op when the PRD already carries the target role** (exactly one lifecycle label/status remains). See **Phase 8 — Idempotency** for the per-write guards.
29
31
 
30
- The remaining phases of PRD-level verification are **out of scope** here and are delivered by sibling work:
31
-
32
- - **FAIL path** — on verification failure (spec conformance not `CONFORMS`, or any empirical check failing), the `shipped → blocked` transition, a product-readable failure report, and linked fix issues for the missing/incorrect behavior.
33
- - **Idempotency** — re-runs producing no duplicate evidence, fix issues, or lifecycle transitions.
34
-
35
- This skill implements only the **PASS** branch of Phase 6. When verification does not pass it stops at the verdict and **leaves the PRD at `shipped`** (it does not transition to `blocked`, does not open fix issues) — that is the FAIL sibling's job. Re-running before the idempotency sibling lands may re-post evidence or re-apply the (idempotent-by-label) transition; full no-duplicate guarantees are the idempotency sibling's job.
32
+ When verification passes, this skill runs the **PASS** branch of Phase 6 (`shipped → verified`). When it does not pass — spec conformance not `CONFORMS`, or any empirical check failing — this skill runs the **FAIL** branch of Phase 7 (`shipped → blocked` + failure report + fix issues); it does **not** leave the PRD at `shipped`. Re-running the skill against the same PRD produces no duplicate evidence comments, no duplicate fix issues, and no duplicate lifecycle labels/statuses — the **Phase 8** guards make each Phase 6/7 write idempotent, exactly as `prd-backlink` regenerates its `## Tickets` section in place and `github-prd-intake` no-ops a rollup on an already-shipped PRD.
36
33
 
37
34
  ## Phase 1 — Resolve the PRD ref and detect the source vendor
38
35
 
@@ -113,7 +110,7 @@ Spec conformance at the PRD level differs from the leaf-ticket conformance run d
113
110
  **Branch on the verdict:**
114
111
 
115
112
  - **`CONFORMS`** — continue to Phase 5 (empirical verification).
116
- - **`PARTIAL` or `DIVERGES`** — verification has **not** passed. Stop the PASS path: record the verdict and the matrix in the output, **leave the PRD at `shipped`**, and do not transition or post a verified-evidence comment. Handing the `shipped → blocked` transition, the product-readable failure report, and the linked fix issues to the FAIL sibling is out of scope here (see [Scope of this skill](#scope-of-this-skill)).
113
+ - **`PARTIAL` or `DIVERGES`** — verification has **not** passed. Do **not** run Phase 5 (empirical verification adds nothing once the spec already diverges) and do **not** enter the PASS path. Record the verdict and the matrix, then go to **Phase 7 FAIL** with a `CONFORMANCE_FAILED` cause: the failed/missing/scope-crept requirements the matrix flagged become the failure report's findings and the seeds for the linked fix issues.
117
114
 
118
115
  ## Phase 5 — Empirical verification of the shipped surface
119
116
 
@@ -137,8 +134,8 @@ If a required surface or its tooling is unavailable, follow the lifecycle's Esca
137
134
 
138
135
  **Branch on the result:**
139
136
 
140
- - **Every applicable empirical check passes** (and is codified where the lifecycle requires) — continue to Phase 6.
141
- - **Any applicable empirical check fails, or a required surface is unavailable** — verification has **not** passed. Stop the PASS path: record what failed/was-blocked in the output, **leave the PRD at `shipped`**, and do not transition or post verified evidence. The `shipped blocked` hop + fix issues are the FAIL sibling's job (out of scope here).
137
+ - **Every applicable empirical check passes** (and is codified where the lifecycle requires) — continue to Phase 6 (PASS).
138
+ - **Any applicable empirical check fails, or a required surface is unavailable** — verification has **not** passed. Record what failed/was-blocked (the check, the tool/command, observed vs expected, and any proof artifacts captured), then go to **Phase 7 FAIL** with an `EMPIRICAL_FAILED` cause: each failed check (or unavailable required surface) becomes a failure-report finding and a seed for a linked fix issue.
142
139
 
143
140
  > **Single-environment note.** In a single-environment project (`main`/production only, no dev/staging), the shipped surface is whatever production exposes. A project with no deployed application, sign-in, or end-to-end environment variables (Lisa itself) verifies on its CLI/dry-run surface — running the documentation/skill build and drift check — which is the empirical surface the PRD's Validation Journey declares. The surface is always PRD-dependent: read the PRD's Empirical Verification Plan and verify what it says ships.
144
141
 
@@ -149,7 +146,7 @@ Reach this phase **only** when **both** are true:
149
146
  - Phase 4 spec conformance returned **`CONFORMS`**, and
150
147
  - Phase 5 every applicable empirical check **passed** (and was codified where required).
151
148
 
152
- If either is false, do not enter this phase — stop at the verdict and leave the PRD at `shipped` (the FAIL sibling owns the `blocked` path).
149
+ If either is false, do not enter this phase — record the verdict and route to **Phase 7 FAIL**, which owns the `shipped → blocked` path.
153
150
 
154
151
  ### 6.1 — Resolve the `verified` and `shipped` roles
155
152
 
@@ -178,31 +175,149 @@ VERIFIED=$(read_role verified prd-verified)
178
175
 
179
176
  ### 6.2 — Transition the PRD `shipped → verified`
180
177
 
181
- Apply the vendor-appropriate transition. This is the `shipped verified` PASS hop the `prd-lifecycle-rollup` rule defines (cite it by slug; this skill is its PASS-path implementation, not a second source of truth):
178
+ **Idempotency guard (no-op if already verified).** Before transitioning, read the PRD's current lifecycle role. If the PRD **already carries `$VERIFIED`**, the transition is a **no-op** — do not re-add the label/status, do not re-remove `$SHIPPED` (already gone). Record it as `already verified (no-op)` and proceed to 6.3 (the evidence comment is still refreshed in place, per Phase 8). This mirrors `github-prd-intake` Phase 3f.1's "no-op if already shipped" guard and the `prd-lifecycle-rollup` "rollup is keyed by the PRD's current state" rule (cite both by slug).
179
+
180
+ Otherwise apply the vendor-appropriate transition. This is the `shipped → verified` PASS hop the `prd-lifecycle-rollup` rule defines (cite it by slug; this skill is its PASS-path implementation, not a second source of truth):
182
181
 
183
182
  - **GitHub / Linear** — remove the `shipped` label and add the `verified` label. For GitHub:
184
183
  ```bash
185
184
  gh issue edit <prd-num> --repo <org>/<repo> --remove-label "$SHIPPED" --add-label "$VERIFIED"
186
185
  ```
187
- Verify exactly **one** PRD-lifecycle label remains afterward (the single-label invariant `github-prd-intake` enforces). For Linear, set the project/issue label equivalently.
188
- - **Notion** — set the PRD page's `notion.statusProperty` (default `Status`) to the resolved `verified` value (default `Verified`).
189
- - **Confluence** — move the PRD page's `parentId` to `confluence.parents.verified` (the parent-page-based lifecycle; Atlassian scoped tokens cannot write labels — see `config-resolution`).
190
- - **JIRA** — transition the PRD issue to the configured `verified` status.
186
+ Verify exactly **one** PRD-lifecycle label remains afterward (the single-label invariant `github-prd-intake` enforces) — a re-run must never leave both `$SHIPPED` and `$VERIFIED`, nor two copies of `$VERIFIED`. For Linear, set the project/issue label equivalently.
187
+ - **Notion** — set the PRD page's `notion.statusProperty` (default `Status`) to the resolved `verified` value (default `Verified`). A status property holds exactly one value, so re-setting the same value is inherently a no-op.
188
+ - **Confluence** — move the PRD page's `parentId` to `confluence.parents.verified` (the parent-page-based lifecycle; Atlassian scoped tokens cannot write labels — see `config-resolution`). A page has exactly one parent, so re-parenting to the same parent is a no-op.
189
+ - **JIRA** — transition the PRD issue to the configured `verified` status. An issue holds exactly one status; if already `verified`, skip the transition.
191
190
 
192
191
  `verified` is the terminal, product-owned PRD state; this skill is the **only** automated writer of it (intake/rollup never set it). Do **not** close or archive the PRD here — closure is governed separately by `prd.rollup.closeOnShipped` at the `shipped` hop, not the verify hop.
193
192
 
194
193
  ### 6.3 — Post verification evidence on the PRD
195
194
 
196
- Post a verification-evidence comment back on the PRD, in the spirit of `tracker-evidence` (the vendor-neutral evidence poster). Because the evidence lands on the **PRD source** — which may be Notion or Confluence, not a tracker ticket — post via the vendor surface that owns the PRD: `gh issue comment` for GitHub, the Linear comment API, the Notion/Confluence page comment surface, or a JIRA comment. Where the PRD lives in the configured `tracker`, you may dispatch through `tracker-evidence`; for Notion/Confluence/cross-vendor PRDs, comment on the PRD page directly. The evidence comment MUST include:
195
+ Post a verification-evidence comment back on the PRD, in the spirit of `tracker-evidence` (the vendor-neutral evidence poster). Because the evidence lands on the **PRD source** — which may be Notion or Confluence, not a tracker ticket — post via the vendor surface that owns the PRD: `gh issue comment` for GitHub, the Linear comment API, the Notion/Confluence page comment surface, or a JIRA comment. Where the PRD lives in the configured `tracker`, you may dispatch through `tracker-evidence`; for Notion/Confluence/cross-vendor PRDs, comment on the PRD page directly.
196
+
197
+ **Idempotent — regenerate the evidence comment in place, never append.** Lead the comment body with the stable sentinel marker `<!-- lisa:verify-prd-evidence -->`. Before posting, look up an existing evidence comment authored by this skill on the PRD whose body contains that sentinel (the same regenerate-don't-append discipline `prd-backlink` uses for its `## Tickets` section; **match by the marker, never by comment text or position**). If one exists, **edit it in place** with the freshly regenerated body; only create a new comment when none exists. Per vendor:
197
198
 
198
- 1. **AI disclosure** — lead with "PRD-level verification by Claude (AI agent, not a human)."
199
- 2. **Verdict line** — `shipped verified PASS`.
200
- 3. **Spec-conformance coverage matrix** — the section-by-section matrix from Phase 4 verbatim, with the `CONFORMS` verdict.
201
- 4. **Empirical proof artifacts** — the Phase 5 artifacts per surface: screenshots (upload via `gh release upload pr-assets <files> --clobber` and reference as plain URLs, per the `tracker-evidence` UI Evidence Checklist), request/response captures, query outputs, log excerpts, and the codified regression test(s) added.
202
- 5. **What was verified** — which PRD acceptance criteria each artifact covers, and the verification surface used.
199
+ - **GitHub** — `gh issue view <prd-num> --repo <org>/<repo> --json comments` and select the comment whose `body` contains `<!-- lisa:verify-prd-evidence -->`; update it with `gh api -X PATCH /repos/<org>/<repo>/issues/comments/<comment-id> -f body=@evidence.md`. Only `gh issue comment <prd-num> --body-file evidence.md` when no marked comment exists.
200
+ - **Linear** — find the existing comment carrying the sentinel and update it via the Linear comment-update API; create only if absent.
201
+ - **Notion / Confluence** — update the existing marked page comment in place; create only if absent.
202
+ - **JIRA** — update the existing marked comment in place; create only if absent.
203
+
204
+ The marked comment is the single canonical evidence comment for the PRD — a re-run refreshes it, never stacking a second one. The evidence comment MUST include:
205
+
206
+ 1. **Sentinel marker** — the literal `<!-- lisa:verify-prd-evidence -->` as the first line, so the next run finds and regenerates this exact comment.
207
+ 2. **AI disclosure** — lead with "PRD-level verification by Claude (AI agent, not a human)."
208
+ 3. **Verdict line** — `shipped → verified — PASS`.
209
+ 4. **Spec-conformance coverage matrix** — the section-by-section matrix from Phase 4 verbatim, with the `CONFORMS` verdict.
210
+ 5. **Empirical proof artifacts** — the Phase 5 artifacts per surface: screenshots (upload via `gh release upload pr-assets <files> --clobber` and reference as plain URLs, per the `tracker-evidence` UI Evidence Checklist), request/response captures, query outputs, log excerpts, and the codified regression test(s) added.
211
+ 6. **What was verified** — which PRD acceptance criteria each artifact covers, and the verification surface used.
203
212
 
204
213
  Then emit the PASS output block (below).
205
214
 
215
+ ## Phase 7 — FAIL: transition `shipped → blocked`, post a failure report, and create fix issues
216
+
217
+ Reach this phase when verification did **not** pass — i.e. **either** is true:
218
+
219
+ - Phase 4 spec conformance returned **`PARTIAL`** or **`DIVERGES`** (`CONFORMANCE_FAILED` cause), or
220
+ - Phase 5 had **any** applicable empirical check fail or a required surface unavailable (`EMPIRICAL_FAILED` cause).
221
+
222
+ This is the FAIL counterpart of the Phase 6 PASS hop. It is the `shipped → blocked` FAIL hop the `prd-lifecycle-rollup` rule defines (cite it by slug; this skill is its FAIL-path implementation, not a second source of truth). It **reuses the existing `blocked` role** — it does **not** introduce a `prd-verification-failed` / `prd-verifying` state, per the "No extra failure states" rule in `prd-lifecycle-rollup`.
223
+
224
+ Carry forward the verdict cause and the concrete **findings** that produced it: from `CONFORMANCE_FAILED`, the matrix's missed/divergent/scope-crept requirements; from `EMPIRICAL_FAILED`, each failing check (the requirement/AC it exercised, the tool/command, observed vs expected, and any captured artifacts). These findings drive both the failure report (7.3) and the fix issues (7.4).
225
+
226
+ ### 7.1 — Resolve the `blocked` and `shipped` roles
227
+
228
+ Resolve the PRD-lifecycle roles from `.lisa.config.json` (then `.lisa.config.local.json` override) per the `config-resolution` rule — the same role-resolution Phase 6.1 and the `*-prd-intake` skills use. **Cite `config-resolution` for the role vocabulary; do not hardcode label strings except as the documented defaults.** Resolution per vendor:
229
+
230
+ | Vendor | `shipped` role | `blocked` role | Default `blocked` |
231
+ |---|---|---|---|
232
+ | **GitHub** | `github.labels.prd.shipped` | `github.labels.prd.blocked` | `prd-blocked` (label) |
233
+ | **Linear** | `linear.labels.prd.shipped` | `linear.labels.prd.blocked` | `prd-blocked` (project/issue label) |
234
+ | **Notion** | `notion.values.shipped` | `notion.values.blocked` | `Blocked` (status value) |
235
+ | **Confluence** | `confluence.parents.shipped` | `confluence.parents.blocked` | the `Blocked` parent page id |
236
+ | **JIRA** | the configured shipped status | the configured blocked status | per `config-resolution` |
237
+
238
+ For GitHub, resolve with the same helper Phase 6.1 / `github-prd-intake` use:
239
+
240
+ ```bash
241
+ read_role() { # role default → resolved value (local override wins)
242
+ local role="$1" default="$2" local_v global_v
243
+ local_v=$(jq -r ".github.labels.prd.${role} // empty" .lisa.config.local.json 2>/dev/null)
244
+ global_v=$(jq -r ".github.labels.prd.${role} // empty" .lisa.config.json 2>/dev/null)
245
+ echo "${local_v:-${global_v:-$default}}"
246
+ }
247
+ SHIPPED=$(read_role shipped prd-shipped)
248
+ BLOCKED=$(read_role blocked prd-blocked)
249
+ ```
250
+
251
+ ### 7.2 — Transition the PRD `shipped → blocked`
252
+
253
+ **Idempotency guard (no-op if already blocked).** Before transitioning, read the PRD's current lifecycle role. If the PRD **already carries `$BLOCKED`** (the common re-run-after-a-previous-failure case — same unsatisfiable requirement still missing), the transition is a **no-op** — do not re-add the label/status, do not re-remove `$SHIPPED` (already gone). Record it as `already blocked (no-op)` and proceed to 7.3, where the existing failure report is **updated in place** (not stacked) and 7.4, where existing fix issues are **referenced** rather than re-created. This mirrors `github-prd-intake` Phase 3f.1's "no-op if already shipped" guard and the `prd-lifecycle-rollup` "rollup is keyed by the PRD's current state" rule (cite both by slug).
254
+
255
+ Otherwise apply the vendor-appropriate transition. This is the `shipped → blocked` FAIL hop from `prd-lifecycle-rollup` (cite it by slug):
256
+
257
+ - **GitHub / Linear** — remove the `shipped` label and add the `blocked` label. For GitHub:
258
+ ```bash
259
+ gh issue edit <prd-num> --repo <org>/<repo> --remove-label "$SHIPPED" --add-label "$BLOCKED"
260
+ ```
261
+ Verify exactly **one** PRD-lifecycle label remains afterward (the single-label invariant `github-prd-intake` enforces) — a re-run must never leave both `$SHIPPED` and `$BLOCKED`, nor two copies of `$BLOCKED`. For Linear, set the project/issue label equivalently.
262
+ - **Notion** — set the PRD page's `notion.statusProperty` (default `Status`) to the resolved `blocked` value (default `Blocked`). A status property holds exactly one value, so re-setting the same value is inherently a no-op.
263
+ - **Confluence** — move the PRD page's `parentId` to `confluence.parents.blocked` (the parent-page-based lifecycle; Atlassian scoped tokens cannot write labels — see `config-resolution`). A page has exactly one parent, so re-parenting to the same parent is a no-op.
264
+ - **JIRA** — transition the PRD issue to the configured `blocked` status. An issue holds exactly one status; if already `blocked`, skip the transition.
265
+
266
+ Do **not** close or archive the PRD here — `blocked` signals "verification failed; human attention required," not "done." The PRD stays open so product can see it failed acceptance.
267
+
268
+ ### 7.3 — Post a product-readable failure report on the PRD
269
+
270
+ Post a **failure report** comment back on the PRD, via the same vendor surface Phase 6.3 uses for evidence (`gh issue comment` for GitHub, the Linear comment API, the Notion/Confluence page comment surface, or a JIRA comment; dispatch through `tracker-evidence` where the PRD lives in the configured `tracker`). The report is written for a **non-engineer product owner** — plain language, no stack traces dumped raw. Capture its URL/anchor so the fix issues in 7.4 can back-link to it.
271
+
272
+ **Idempotent — regenerate the failure report in place, never append.** Lead the comment body with the stable sentinel marker `<!-- lisa:verify-prd-failure-report -->`. Before posting, look up an existing failure-report comment on the PRD whose body contains that sentinel (**match by the marker, never by comment text or position** — the same regenerate-don't-append discipline as Phase 6.3). If one exists, **edit it in place** with the freshly regenerated findings (so a re-run-after-a-previous-failure refreshes the same report rather than stacking a second one); only create a new comment when none exists. The GitHub mechanics are identical to Phase 6.3 (`gh issue view --json comments` to find the marked comment, `gh api -X PATCH .../issues/comments/<id>` to update, `gh issue comment` only when absent). It MUST include:
273
+
274
+ 1. **Sentinel marker** — the literal `<!-- lisa:verify-prd-failure-report -->` as the first line, so the next run finds and regenerates this exact comment.
275
+ 2. **AI disclosure** — lead with "PRD-level verification by Claude (AI agent, not a human)."
276
+ 3. **Verdict line** — `shipped → blocked — FAIL` and the cause (`CONFORMANCE_FAILED` or `EMPIRICAL_FAILED`).
277
+ 4. **What failed, in plain language** — for each finding, name the **specific PRD requirement / acceptance criterion** that was not met, then **what was expected vs what was observed** (the empirical evidence: what was checked, what the shipped product did instead). One bullet per finding so product can follow each independently.
278
+ 5. **Spec-conformance coverage matrix** — for a `CONFORMANCE_FAILED` cause, the section-by-section matrix from Phase 4 verbatim with the `PARTIAL`/`DIVERGES` verdict, so the missed/divergent/scope-crept rows are visible.
279
+ 6. **Proof artifacts** — any captured empirical artifacts (screenshots uploaded via `gh release upload pr-assets <files> --clobber` and referenced as plain URLs per the `tracker-evidence` UI Evidence Checklist, request/response captures, query outputs, log excerpts).
280
+ 7. **Fix issues** — a list of the fix issues created/referenced in 7.4 (filled in after 7.4 runs, or posted as a brief follow-up edit), so the report is the single product-facing index of "what's wrong and where it's being fixed."
281
+
282
+ ### 7.4 — Create linked fix issues for the missing/incorrect behavior
283
+
284
+ For **each** failed/missing/incorrect/divergent finding, create a **fix issue** via `tracker-write` (the vendor-neutral writer) — never by hand-rolling `gh issue create`, so each issue passes the same quality gates (`tracker-validate`) every Lisa ticket does: three-audience description, **Gherkin acceptance criteria**, labels, and explicit relationship discovery. Group findings that share one root cause into one fix issue; do not fan out one issue per matrix cell when several rows are the same defect.
285
+
286
+ **Idempotent — dedupe fix issues by a stable marker; reference/update, never duplicate.** This is the "re-run after a previous failure with the same missing behavior" scenario: the prior run already opened a fix issue for that requirement, so the re-run must **find and reuse it**, not create a second one. Apply the `prd-lifecycle-rollup` idempotency dedupe key discipline (**match by a stable ref, never by title**):
287
+
288
+ 1. **Compute a stable dedupe key per finding** — the PRD ref plus a stable requirement/AC identity (e.g. the AC's heading/number or a slug of the requirement), independent of any mutable wording. Encode it in the fix-issue body as the marker `<!-- lisa:verify-prd-fix prd=<prd-ref> req=<stable-req-id> -->`.
289
+ 2. **Look up an existing OPEN fix issue carrying that exact marker** before creating anything. On GitHub, search the repo for open issues whose body contains the marker (`gh issue list --repo <org>/<repo> --state open --search '"<!-- lisa:verify-prd-fix prd=<prd-ref> req=<stable-req-id> -->"' --json number,url,body` — or fetch and grep the marker); on Linear/JIRA, query by the marker stored in the body/a custom field. **Match on the marker, never on the issue title** (a title may have been edited; the marker is the stable identity).
290
+ 3. **If a matching open fix issue exists, reference/update it — do not create a duplicate.** Refresh its captured evidence (the latest observed-vs-expected) and re-affirm the back-links to the PRD and the regenerated failure report, then fold its existing ref into the failure report's **Fix issues** list. A closed prior fix issue does **not** suppress a new one — if the requirement is failing again after the fix was closed, that is a regression and a fresh fix issue is correct.
291
+ 4. **Only when no matching open fix issue exists, create a new one** via `tracker-write`.
292
+
293
+ Each fix issue (whether freshly created or referenced/updated) MUST:
294
+
295
+ 1. **Carry the dedupe marker** — `<!-- lisa:verify-prd-fix prd=<prd-ref> req=<stable-req-id> -->` in its body, so the next run finds and reuses it.
296
+ 2. **Reference the specific failed requirement/AC** — quote or cite the exact PRD requirement / acceptance criterion the finding violated, so the fix is scoped to a real gap (not a vague "make it work").
297
+ 3. **Carry the captured evidence** — the observed-vs-expected from the failure report (what was checked, what was expected, what the shipped product did), so an implementer can reproduce without re-deriving it.
298
+ 4. **Back-link to the PRD and the failure report** — link to the PRD (so the fix rolls back up to the initiative) and to the failure-report comment from 7.3 (so the full context is one click away). On GitHub, reference the PRD issue number and the failure-report comment URL in the body and, where supported, as a sub-issue/`Relates to` link; on Linear, set the relation; on JIRA, add the issue link and remote link.
299
+ 5. **Have acceptance criteria** — Gherkin ACs describing the corrected behavior (what "fixed" looks like), enforced by `tracker-write` → the vendor `*-validate-issue` gate.
300
+
301
+ Pass each new fix issue's spec to `tracker-write` (which dispatches to `github-write-issue` / `jira-write-ticket` / `linear-write-issue` per config). Collect the created **and referenced** refs/URLs and fold them into the failure report's **Fix issues** list (7.3 item 7).
302
+
303
+ > **Why not reopen children?** The generated top-level children are already terminal (that is the Phase 3 precondition for verification). A failed PRD-level acceptance is a **new** defect discovered against the shipped initiative, so it gets **new** fix issues linked to the PRD — not a reopen of closed build tickets, which would corrupt their build lifecycle (`leaf-only-lifecycle`).
304
+
305
+ Then emit the FAIL output block (below).
306
+
307
+ ## Phase 8 — Idempotency: re-runs produce no duplicates
308
+
309
+ `/lisa:verify-prd` MUST be safe to re-run against the same PRD — after a fix attempt, in a batch sweep, or simply twice. A re-run produces **no duplicate evidence comments, no duplicate fix issues, and no duplicate lifecycle labels/statuses**. This is the same guarantee `prd-backlink` gives for its `## Tickets` section and `github-prd-intake` gives for its rollup; this skill consumes the `prd-lifecycle-rollup` rule's **idempotency dedupe key** (cite by slug — **match by stable ref, never by title**), it does not invent a second one.
310
+
311
+ The guards are woven into Phases 6 and 7 above; this phase collects them as one contract:
312
+
313
+ 1. **Evidence / failure-report comments — regenerate in place, never append.** Each is led by a stable HTML-comment sentinel: `<!-- lisa:verify-prd-evidence -->` (PASS, Phase 6.3) and `<!-- lisa:verify-prd-failure-report -->` (FAIL, Phase 7.3). Before posting, find the existing comment whose body contains the sentinel and **edit it in place**; create a new comment only when none exists. The sentinel is matched literally — never the comment text, author display name, or position. A second run thus refreshes the one canonical comment rather than stacking a duplicate (the regenerate-don't-append discipline from `prd-backlink`).
314
+
315
+ 2. **Fix issues — dedupe by a stable marker, reference don't duplicate.** Each fix issue carries `<!-- lisa:verify-prd-fix prd=<prd-ref> req=<stable-req-id> -->`, keyed by the PRD ref + a stable requirement/AC identity. Before creating a fix issue, search for an **open** issue carrying that exact marker; if found, reference/update it instead of creating a second one (Phase 7.4). The dedupe key is the marker (a stable ref), **never the issue title** — a renamed fix issue is still matched by its marker, and two distinct requirements get two distinct markers even if their titles collide (`prd-lifecycle-rollup`: "Match by stable ref, never by title"). A *closed* prior fix issue does not suppress a new one (a re-failure after a closed fix is a genuine regression).
316
+
317
+ 3. **Lifecycle transition — no-op when already at the target role.** The Phase 6.2 / 7.2 transition is keyed by the PRD's current state: if the PRD already carries `$VERIFIED` (PASS) or `$BLOCKED` (FAIL), the transition is a no-op — no re-label, no second copy of the label/status — mirroring `github-prd-intake` Phase 3f.1's "no-op if already shipped." After any transition, exactly **one** PRD-lifecycle label/status remains (the single-label invariant); a re-run never leaves both `$SHIPPED` and the target role, nor two copies of the target role. For Notion/Confluence/JIRA the single-value status/parent makes re-setting the same value inherently idempotent.
318
+
319
+ Because every Phase 6/7 write is one of these three idempotent operations, the **whole skill is idempotent**: the end state after N runs equals the end state after 1 run — one evidence-or-failure comment, one fix issue per still-failing requirement, one lifecycle label/status. Computing the verdict itself is a pure function of the PRD's current state and its children's current states, so recomputing it on a re-run is safe (`prd-lifecycle-rollup` idempotency rule).
320
+
206
321
  ## Output
207
322
 
208
323
  Emit a single fenced text block so callers can parse it.
@@ -228,28 +343,32 @@ Verdict: <CONFORMS | PARTIAL | DIVERGES>
228
343
  Surface: <browser | api | cli | db | logs | ...> (PRD-dependent)
229
344
  <each check — tool/command → PASS/FAIL → artifact ref; codified test(s)>
230
345
 
231
- ### Lifecycle transition (only on PASS)
232
- shipped → verified (role: <resolved verified role>) evidence posted: <link>
346
+ ### Lifecycle transition (PASS or FAIL)
347
+ shipped → verified (role: <resolved verified role>) evidence posted: <link> # on VERIFIED_PASS (re-run: evidence comment regenerated in place; transition no-op if already verified)
348
+ shipped → blocked (role: <resolved blocked role>) failure report: <link> fix issues: <refs> # on CONFORMANCE_FAILED | EMPIRICAL_FAILED (re-run: failure report regenerated in place; fix issues deduped by marker; transition no-op if already blocked)
233
349
 
234
350
  ### Verdict: VERIFIED_PASS | CONFORMANCE_FAILED | EMPIRICAL_FAILED | GUARD_BLOCKED | NO_CHILDREN
235
351
  ```
236
352
 
237
353
  - `GUARD_BLOCKED` — one or more required top-level children are non-terminal; verification did not run; the PRD was left at `shipped`.
238
354
  - `NO_CHILDREN` — no generated top-level children found; cannot verify; the PRD was left untouched.
239
- - `CONFORMANCE_FAILED` — guard passed but spec conformance returned `PARTIAL`/`DIVERGES`; empirical verification did not run; the PRD was left at `shipped` (the `shipped → blocked` transition + fix issues are the FAIL sibling's job).
240
- - `EMPIRICAL_FAILED` — guard passed and conformance `CONFORMS`, but an applicable empirical check failed or a required surface was unavailable; the PRD was left at `shipped` (FAIL sibling owns the `blocked` path).
241
- - `VERIFIED_PASS` — guard passed, conformance `CONFORMS`, every applicable empirical check passed and was codified; the PRD was transitioned `shipped → verified` and verification evidence was posted.
355
+ - `CONFORMANCE_FAILED` — guard passed but spec conformance returned `PARTIAL`/`DIVERGES`; empirical verification was skipped; the FAIL path ran — the PRD was transitioned `shipped → blocked` (reusing the `blocked` role), a product-readable failure report was posted, and linked fix issues were created (Phase 7).
356
+ - `EMPIRICAL_FAILED` — guard passed and conformance `CONFORMS`, but an applicable empirical check failed or a required surface was unavailable; the FAIL path ran — the PRD was transitioned `shipped → blocked` (reusing the `blocked` role), a product-readable failure report was posted, and linked fix issues were created (Phase 7).
357
+ - `VERIFIED_PASS` — guard passed, conformance `CONFORMS`, every applicable empirical check passed and was codified; the PRD was transitioned `shipped → verified` and verification evidence was posted (Phase 6).
242
358
 
243
359
  ## Rules
244
360
 
245
- - **The only lifecycle write is the PASS hop `shipped → verified`.** The front-half (resolve → read child set → guard) is read-only and never transitions the PRD. The only write this skill performs is the Phase 6 PASS hop and **only** when spec conformance is `CONFORMS` and every applicable empirical check passes. The guard-blocked, no-children, conformance-failed, and empirical-failed paths all leave the PRD at `shipped` untouched. The `shipped blocked` FAIL hop, fix issues, and re-run idempotency are sibling work (out of scope).
361
+ - **The lifecycle writes are the PASS hop `shipped → verified` and the FAIL hop `shipped → blocked`.** The front-half (resolve → read child set → guard) is read-only and never transitions the PRD. After the guard passes and verification runs, this skill writes exactly one of two transitions: the Phase 6 PASS hop `shipped verified` (when spec conformance is `CONFORMS` and every applicable empirical check passes), or the Phase 7 FAIL hop `shipped blocked` (when conformance is `PARTIAL`/`DIVERGES` or any applicable empirical check fails). The FAIL hop **reuses the existing `blocked` role it introduces no new failure state.** The guard-blocked and no-children paths run no verification and leave the PRD at `shipped` untouched.
362
+ - **Every write is idempotent (Phase 8).** Re-running the skill against the same PRD produces no duplicate evidence/failure-report comments, no duplicate fix issues, and no duplicate lifecycle labels/statuses. Evidence and failure-report comments are regenerated in place via a stable sentinel marker (`<!-- lisa:verify-prd-evidence -->` / `<!-- lisa:verify-prd-failure-report -->`); fix issues are deduped by a stable PRD-ref + requirement marker (`<!-- lisa:verify-prd-fix prd=… req=… -->`) and referenced/updated rather than re-created; the lifecycle transition is a no-op when the PRD already carries the target role, leaving exactly one lifecycle label/status. The dedupe key is the `prd-lifecycle-rollup` idempotency dedupe key — **match by stable ref, never by title** — and the no-op-already-at-target-role guard mirrors `github-prd-intake` Phase 3f.1.
363
+ - **The FAIL path opens fix issues via `tracker-write`, never by hand.** Each fix issue is created through the vendor-neutral writer so it passes the same `tracker-validate` quality gate (three-audience description, Gherkin ACs, labels, relationships) every Lisa ticket does. Fix issues are **new** defects against the shipped initiative, back-linked to the PRD and the failure report — never reopens of the already-terminal generated children (`leaf-only-lifecycle`).
246
364
  - **Never reimplement child enumeration.** Consume the recorded PRD→child relationship (`prd-lifecycle-rollup` native linking + machine-readable generated-work section). The two-source read here mirrors `github-prd-intake` Phase 3f.2 — same sources, same dedupe-by-child-ref, same top-level-only boundary.
247
365
  - **Never reimplement spec conformance or verification.** Phase 4 invokes the `spec-conformance` skill (the single source of truth for the coverage matrix and the `CONFORMS`/`PARTIAL`/`DIVERGES` verdict); Phase 5 invokes `verification-lifecycle` (which in turn invokes `codify-verification` and, for UI, `product-walkthrough`). This skill orchestrates those skills against the PRD; it does not duplicate their logic.
248
366
  - **Quality gates are not verification.** Tests, typecheck, and lint are prerequisites enforced by hooks/CI. Phase 5 requires running the actual shipped system and observing results on a surface chosen from what the PRD delivered — never substituting a green test suite for empirical proof (`verification` rule).
249
367
  - **The verification surface is PRD-dependent.** Classify the empirical surface (browser/API/CLI/DB/logs/…) from what the PRD shipped; do not assume a fixed surface. A single-environment project with no deployed app verifies on its CLI/dry-run surface per the PRD's Empirical Verification Plan.
250
368
  - **`verified` is product-owned and terminal.** This skill is the only automated writer of the `verified` role; intake/rollup never set it. The PASS hop does not close or archive the PRD (closure is governed by `prd.rollup.closeOnShipped` at the `shipped` hop).
369
+ - **`blocked` is reused, not invented, and is non-terminal.** The FAIL hop sets the existing `blocked` PRD role (`config-resolution`) — the same role intake uses for failed validation — so the lifecycle stays small (`prd-lifecycle-rollup` "No extra failure states"). `blocked` means "verification failed; human attention required"; the FAIL hop never closes or archives the PRD.
251
370
  - **Top-level only.** Exclude leaf Sub-tasks and Stories nested under a generated Epic. The PRD owns its top-level work; those top-level units own their descendants (`prd-lifecycle-rollup` generated-top-level-work contract).
252
- - **Cite, don't restate.** The generated-top-level-work boundary, the per-vendor terminal predicate, the env-keyed `done` resolution, the dedupe-by-child-ref idempotency key, and the `shipped → verified` PASS hop all come from the `prd-lifecycle-rollup` rule; the `verified`/`shipped` role vocabulary comes from `config-resolution`. This skill is a consumer of those contracts, not a second source of truth.
371
+ - **Cite, don't restate.** The generated-top-level-work boundary, the per-vendor terminal predicate, the env-keyed `done` resolution, the dedupe-by-child-ref idempotency key, and the `shipped → verified | blocked` PRD-level verification hops all come from the `prd-lifecycle-rollup` rule; the `verified`/`shipped`/`blocked` role vocabulary comes from `config-resolution`. This skill is a consumer of those contracts, not a second source of truth.
253
372
 
254
373
  ## Related skills
255
374
 
@@ -257,11 +376,14 @@ shipped → verified (role: <resolved verified role>) evidence posted: <link
257
376
  - `verification-lifecycle` — Phase 5 invokes it to run empirical verification of the shipped surface (classify → check tooling → plan → execute → codify → loop). It in turn invokes `codify-verification` and, for UI surfaces, `product-walkthrough`.
258
377
  - `codify-verification` — turns each passing empirical verification into a regression test so the PRD's verified behavior cannot silently regress; invoked transitively via `verification-lifecycle`.
259
378
  - `product-walkthrough` — drives the live product through a real browser to ground UI-surface verification and the evidence comment in what actually renders.
260
- - `tracker-evidence` — the vendor-neutral evidence poster whose UI Evidence Checklist and `pr-assets` upload mechanics Phase 6.3 follows when posting the verification evidence comment on the PRD.
379
+ - `tracker-evidence` — the vendor-neutral evidence poster whose UI Evidence Checklist and `pr-assets` upload mechanics Phase 6.3 (PASS evidence) and Phase 7.3 (FAIL failure report) follow when commenting on the PRD.
380
+ - `tracker-write` — the vendor-neutral ticket writer Phase 7.4 invokes to create each linked fix issue (dispatching to `github-write-issue` / `jira-write-ticket` / `linear-write-issue` per config), so every fix issue clears the `tracker-validate` quality gate (Gherkin ACs, three-audience description, labels, relationships). This skill never hand-rolls issue creation.
381
+ - `prd-backlink` — the regenerate-in-place-via-marker idempotency pattern Phase 6.3 / 7.3 / 8 follow: it regenerates its `## Tickets` section from the current child set on every run (never appending) and dedupes by child-ref. The evidence/failure-report sentinel comments here apply the same discipline to PRD comments.
382
+ - `github-prd-intake` — the no-op-if-already-at-target-role guard Phase 6.2 / 7.2 / 8 mirror: its Phase 3f.1 rollup is a no-op on a PRD already carrying `$SHIPPED`, and it enforces the single-label invariant after every transition. This skill applies the same guard to the `verified` / `blocked` hops.
261
383
 
262
384
  ## Related rules
263
385
 
264
- - `prd-lifecycle-rollup` — the vendor-neutral source of truth for PRD→generated-top-level-work ownership, the per-vendor terminal predicate, the `shipped` rollup, the `shipped → verified | blocked` PRD-level verification hops, and the child-ref idempotency dedupe key. This skill consumes that contract — including the `shipped → verified` PASS hop it implements — citing the rule by slug rather than restating its taxonomy.
386
+ - `prd-lifecycle-rollup` — the vendor-neutral source of truth for PRD→generated-top-level-work ownership, the per-vendor terminal predicate, the `shipped` rollup, the `shipped → verified | blocked` PRD-level verification hops, the "no extra failure states" rule (the FAIL hop reuses `blocked`), and the **idempotency dedupe key** ("match by stable ref, never by title"; no-op already-shipped rollup). This skill consumes that contract — implementing the `shipped → verified` PASS hop, the `shipped → blocked` FAIL hop, and the Phase 8 idempotency guards (marker-based comment regeneration, marker-based fix-issue dedupe, no-op-already-at-target-role transition) — citing the rule by slug rather than restating its taxonomy.
265
387
  - `verification` — defines what counts as empirical verification (the Verification Types table) and that quality gates (test/typecheck/lint) are prerequisites, not verification. Phase 5 honors it when classifying and running the surface-appropriate checks.
266
388
  - `leaf-only-lifecycle` — governs the build lifecycle of leaf work units and how a generated Epic rolls up from its own children; this skill trusts that bottom-up rollup when reading a top-level child's resolved state.
267
- - `config-resolution` — the PRD-lifecycle role vocabulary (`shipped`, `verified`, `blocked`), the per-vendor `verified` role maps (`prd-verified` label for GitHub/Linear, `Verified` status for Notion, `confluence.parents.verified` parent page) Phase 6.1 resolves, and the env-keyed `done` map the terminal predicate resolves against.
389
+ - `config-resolution` — the PRD-lifecycle role vocabulary (`shipped`, `verified`, `blocked`), the per-vendor `verified` role maps (`prd-verified` label for GitHub/Linear, `Verified` status for Notion, `confluence.parents.verified` parent page) Phase 6.1 resolves, the per-vendor `blocked` role maps (`prd-blocked` label for GitHub/Linear, `Blocked` status for Notion, `confluence.parents.blocked` parent page) Phase 7.1 resolves, and the env-keyed `done` map the terminal predicate resolves against.