@codyswann/lisa 2.221.4 → 2.221.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/package.json +1 -1
  2. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  3. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  4. package/plugins/lisa/.codex-plugin/skills/lisa-github-validate-issue/SKILL.md +68 -9
  5. package/plugins/lisa/skills/lisa-github-validate-issue/SKILL.md +68 -9
  6. package/plugins/lisa-agy/plugin.json +1 -1
  7. package/plugins/lisa-agy/skills/lisa-github-validate-issue/SKILL.md +68 -9
  8. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  9. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  10. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  11. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  12. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  13. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  14. package/plugins/lisa-copilot/skills/lisa-github-validate-issue/SKILL.md +68 -9
  15. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  16. package/plugins/lisa-cursor/skills/lisa-github-validate-issue/SKILL.md +68 -9
  17. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  18. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  19. package/plugins/lisa-expo-agy/plugin.json +1 -1
  20. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  21. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  22. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  23. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  24. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  25. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  26. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  27. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  28. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  29. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  30. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  31. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  32. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  33. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  34. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  35. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  37. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  38. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  39. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  40. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  44. package/plugins/lisa-rails-agy/plugin.json +1 -1
  45. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  47. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  49. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  50. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  52. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  54. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  55. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  57. package/plugins/src/base/skills/lisa-github-validate-issue/SKILL.md +68 -9
package/package.json CHANGED
@@ -102,7 +102,7 @@
102
102
  "form-data": ">=4.0.6"
103
103
  },
104
104
  "name": "@codyswann/lisa",
105
- "version": "2.221.4",
105
+ "version": "2.221.6",
106
106
  "description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
107
107
  "main": "dist/index.js",
108
108
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.221.4",
3
+ "version": "2.221.6",
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.221.4",
3
+ "version": "2.221.6",
4
4
  "description": "Universal governance: agents, skills, commands, hooks, and rules for all projects.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -25,7 +25,7 @@ org: my-org
25
25
  repo: my-repo
26
26
  summary: "[CU-1.2] Upload contract PDF from settings"
27
27
  priority: medium
28
- parent_ref: "my-org/my-repo#1234" # Parent Epic for non-Bug/non-Epic; Story for Sub-task
28
+ parent_ref: "my-org/my-repo#1234" # Parent Epic for ordinary children; PRD for an Epic only in the same-repo GitHub self-host shape; Story/etc. for Sub-task
29
29
  body: |
30
30
  ## Context / Business Value
31
31
  ...
@@ -63,7 +63,7 @@ artifacts_attached: true # → requires Source Precedence section
63
63
  links: [{ ref: "my-org/my-repo#99", type: "is blocked by" }] # known issue links (may be empty)
64
64
  remote_links: [{ url: "https://github.com/.../pull/42", title: "PR #42" }]
65
65
  journey_followup: auto # auto | none — see S11
66
- build_ready: true # caller asserts the build-ready role (status:ready) is/would be applied — see S15
66
+ build_ready: true # caller asserts the configured build-ready role (github.labels.build.ready, default status:ready) is/would be applied — see S15
67
67
  child_refs: ["my-org/my-repo#601", "my-org/my-repo#602"] # known child work (sub-issues / task-list / "Blocked by" parentage) — see S15
68
68
  prd_source: "https://notion.so/..." # set when the issue was generated from a PRD — requires the Source Requirement section, see S16
69
69
  ```
@@ -213,9 +213,11 @@ This gate depends on S11. It is `N/A` for containers — an **Epic**, or any ite
213
213
 
214
214
  #### S15 — Leaf-only build-ready
215
215
 
216
- Enforces the build-side of the vendor-neutral `leaf-only-lifecycle` rule: **only a leaf work unit may carry the build-ready role.** This is the symmetric write-side guard for the GitHub validator a stale or hand-applied `status:ready` on a container is a lifecycle error and must FAIL here, regardless of how the issue was produced. (Mirrors the "Build-ready label is leaf-only" rule that `lisa-github-write-issue` applies at write time.)
216
+ Enforces the build-side of the vendor-neutral `leaf-only-lifecycle` rule: **only a leaf work unit may carry the build-ready role.** Before evaluating this gate, resolve `READY_ROLE` from merged project config (`.lisa.config.local.json` over `.lisa.config.json`) at `github.labels.build.ready`, defaulting to `status:ready` per `config-resolution`. Use that resolved value everywhere this validator interprets build readiness; a project-specific label is not an alias for the literal default.
217
217
 
218
- **When the gate applies.** Run S15 whenever the issue is build-ready i.e. `build_ready = true`, or the spec/live labels include `status:ready`. If the issue is not build-ready, S15 is `N/A` (nothing claims a non-ready issue, so the invariant is vacuous).
218
+ This is the symmetric write-side guard for the GitHub validatora stale or hand-applied `READY_ROLE` on a container is a lifecycle error and must FAIL here, regardless of how the issue was produced. (Mirrors the "Build-ready label is leaf-only" rule that `lisa-github-write-issue` applies at write time.)
219
+
220
+ **When the gate applies.** Run S15 whenever the issue is build-ready — i.e. `build_ready = true`, or the spec/live labels include the resolved `READY_ROLE`. If the issue is not build-ready, S15 is `N/A` (nothing claims a non-ready issue, so the invariant is vacuous). For example, if `github.labels.build.ready = "queue:approved"`, a container carrying `queue:approved` FAILs S15 even when it does not carry the literal `status:ready` default.
219
221
 
220
222
  **Resolve container vs. leaf — structural first, then nominal.** Per `leaf-only-lifecycle` the classification is structural: an item is a **container** if it has child work, whatever its declared type; otherwise the **type label** decides. Determine child work from (in order) `child_refs`, native sub-issues, body task-list checkboxes, and `Blocked by #<n>` / parent references — the same hierarchy resolution `lisa-github-read-issue` uses. When validating a live ref, query sub-issues alongside the issue fetch.
221
223
 
@@ -233,7 +235,7 @@ PASS (the childless-parent exception) when the issue is build-ready and is a **l
233
235
  | Epic | no | yes | **FAIL** (childless Epic — pure rollup container, exception does not apply) |
234
236
  | any | any | no | **N/A** (not build-ready) |
235
237
 
236
- Remediation: `"Build-ready (status:ready) is leaf-only per leaf-only-lifecycle. Move status:ready off this container onto its leaf children (or, for a childless Epic, decompose it into leaf children or reclassify it to a leaf type); a parent's lifecycle state rolls up from its children and is never set to ready directly."`
238
+ Remediation (render `<READY_ROLE>` as the resolved configured label, never as a hard-coded default): `"Build-ready (<READY_ROLE>; status:ready by default) is leaf-only per leaf-only-lifecycle. Move <READY_ROLE> off this container onto its leaf children (or, for a childless Epic, decompose it into leaf children or reclassify it to a leaf type); a parent's lifecycle state rolls up from its children and is never set to ready directly."`
237
239
 
238
240
  `product_relevant: false` — a build-ready container is a lifecycle/decomposition error for the caller to repair, not a product question.
239
241
 
@@ -284,8 +286,37 @@ gh issue view <number> --repo <org>/<repo> --json number,labels,state
284
286
  ```
285
287
 
286
288
  Confirm the parent issue exists and:
287
- - For non-Sub-task children: parent has `type:Epic` label.
288
- - For Sub-task children: parent has `type:Story`, `type:Task`, `type:Bug`, or `type:Improvement` (anything that can host sub-tasks).
289
+
290
+ - For an `Epic` child, first resolve whether the validator can prove the native PRD-parent shape
291
+ allowed by `prd-lifecycle-rollup`: merged project config has `source = github` and
292
+ `tracker = github`; the spec/live child's `org` and `repo` match configured `github.org` and
293
+ `github.repo`; and `parent_ref` names that same `org/repo`. These facts are available from the
294
+ existing spec/live ref plus project config; do not infer the exception from label spelling alone.
295
+ Only in that proven same-repository GitHub self-host shape may the parent qualify by having one of
296
+ the configured PRD lifecycle labels from
297
+ `github.labels.prd` (`draft`, `ready`, `in_review`, `blocked`, `ticketed`, `shipped`, or
298
+ `verified`; defaults use the `prd-*` namespace). Resolve the configured values from
299
+ `.lisa.config.local.json` over `.lisa.config.json`, using the defaults from `config-resolution`.
300
+ The `sentinel` label is not a lifecycle role and does not qualify. This is the native
301
+ PRD→generated-Epic hierarchy used when GitHub is both source and tracker in one repository; the
302
+ PRD parent does **not** need `type:Epic`. If any self-host/same-repository predicate is false, a
303
+ PRD label does not grant the exception: native hierarchy cannot cross repositories or source
304
+ systems, so a PRD-labelled parent alone FAILs F2.
305
+ - For a `Sub-task` child: the parent has `type:Story`, `type:Task`, `type:Bug`, or
306
+ `type:Improvement` (anything that can host sub-tasks). This allowlist is unchanged; a PRD
307
+ lifecycle label or `type:Epic` alone does not qualify.
308
+ - For every other non-Sub-task child: the parent has `type:Epic`. A PRD lifecycle label alone does
309
+ not qualify, so the Epic→Story (and Epic→ordinary-leaf) hierarchy remains enforced.
310
+
311
+ | child type | relationship shape | qualifying parent label | F2 |
312
+ |---|---|---|---|
313
+ | `Epic` | source GitHub + tracker GitHub + configured child repo = parent repo | configured PRD lifecycle label | **PASS** |
314
+ | `Epic` | cross-repository or source/tracker is not same-repo GitHub | PRD lifecycle label only | **FAIL** |
315
+ | `Epic` | permitted self-host shape | unconfigured `prd-*` lookalike or `prd-intake-feedback` sentinel only | **FAIL** |
316
+ | `Sub-task` | any | `type:Story`, `type:Task`, `type:Bug`, or `type:Improvement` | **PASS** |
317
+ | `Sub-task` | any | PRD lifecycle label or `type:Epic` only | **FAIL** |
318
+ | any other non-Sub-task | any | `type:Epic` | **PASS** |
319
+ | any other non-Sub-task | any | PRD lifecycle label only | **FAIL** |
289
320
 
290
321
  #### F3 — Linked issues exist
291
322
 
@@ -293,7 +324,35 @@ For each entry in `links`, run `gh issue view <number> --repo <link-org>/<link-r
293
324
 
294
325
  #### F4 — Required labels populated
295
326
 
296
- Per `Phase 5` of `lisa-github-write-issue`, every issue MUST carry: `type:<issue_type>`, `status:<status>`, `priority:<priority>`. If any are missing from the spec / live issue, FAIL with the missing label name.
327
+ Per `Phase 5` of `lisa-github-write-issue`, every issue MUST carry
328
+ `type:<issue_type>` and `priority:<priority>`. These two labels are unconditional: if either is
329
+ missing from the proposed spec or live issue, FAIL with the missing label name.
330
+
331
+ The `status:*` requirement uses this validator's S15 leaf/container classification while preserving
332
+ the writer's documented `build_ready` control-input defaults:
333
+
334
+ 1. Classify the issue structurally using the S15 child-resolution rules. A container (any issue
335
+ with child work, plus a childless `Epic`) may omit `status:*`; its state rolls up rather than
336
+ being assigned directly.
337
+ 2. For a proposed leaf spec, normalize omitted `build_ready` to `true`, preserving the writer's
338
+ backward-compatible default-ready behavior. Explicit `build_ready: false` means backlog mode.
339
+ 3. For a live issue ref, derive `build_ready` from the labels (`true` exactly when the S15-resolved
340
+ `READY_ROLE` from `github.labels.build.ready`, default `status:ready`, is present). A live backlog leaf without a status label
341
+ therefore validates as `build_ready: false`; live data cannot distinguish an explicit false from
342
+ a historical write that omitted the label.
343
+ 4. A leaf with normalized `build_ready: true` MUST carry that same resolved `READY_ROLE`. A leaf with `build_ready: false` may omit
344
+ `status:*`.
345
+
346
+ | classification | normalized build_ready | status label | F4 |
347
+ |---|---:|---|---|
348
+ | container | any | omitted | **PASS** |
349
+ | leaf | `false` | omitted | **PASS** |
350
+ | leaf | `true` | configured build-ready role (`status:ready` by default) | **PASS** |
351
+ | leaf | `true` | omitted or a different `status:*` label | **FAIL** |
352
+
353
+ F4 does not make a container build-ready. S15 remains the independent lifecycle prohibition: any
354
+ container carrying the build-ready role still FAILs S15, even though F4's status-presence check is
355
+ not applicable to containers.
297
356
 
298
357
  #### F5 — Required external access provable
299
358
 
@@ -322,7 +381,7 @@ system, and never invent or ask for credentials inline.
322
381
 
323
382
  ## Execution
324
383
 
325
- 1. Parse `$ARGUMENTS`. If it's an issue ref, fetch via `gh issue view --json` and derive the spec fields — including `build_ready` (label set contains `status:ready`) and `child_refs` (native sub-issues plus body task-list / `Blocked by #<n>` parentage, resolved as in `lisa-github-read-issue`) so S15 can classify the issue. Otherwise parse the YAML spec.
384
+ 1. Parse `$ARGUMENTS`. Resolve `READY_ROLE` from merged `github.labels.build.ready` config (default `status:ready`). If the input is an issue ref, fetch via `gh issue view --json` and derive the spec fields — including `build_ready` (label set contains the resolved `READY_ROLE`, not a hard-coded label) and `child_refs` (native sub-issues plus body task-list / `Blocked by #<n>` parentage, resolved as in `lisa-github-read-issue`) so S15 can classify the issue. Otherwise parse the YAML spec and preserve the proposed `build_ready` value for S15/F4 normalization.
326
385
  2. Confirm `gh auth status` succeeds before any feasibility gate runs.
327
386
  3. Run every Specification gate in order. Collect PASS / FAIL / N/A with a one-line reason.
328
387
  4. Unless the caller passed `--spec-only`, run every Feasibility gate.
@@ -25,7 +25,7 @@ org: my-org
25
25
  repo: my-repo
26
26
  summary: "[CU-1.2] Upload contract PDF from settings"
27
27
  priority: medium
28
- parent_ref: "my-org/my-repo#1234" # Parent Epic for non-Bug/non-Epic; Story for Sub-task
28
+ parent_ref: "my-org/my-repo#1234" # Parent Epic for ordinary children; PRD for an Epic only in the same-repo GitHub self-host shape; Story/etc. for Sub-task
29
29
  body: |
30
30
  ## Context / Business Value
31
31
  ...
@@ -63,7 +63,7 @@ artifacts_attached: true # → requires Source Precedence section
63
63
  links: [{ ref: "my-org/my-repo#99", type: "is blocked by" }] # known issue links (may be empty)
64
64
  remote_links: [{ url: "https://github.com/.../pull/42", title: "PR #42" }]
65
65
  journey_followup: auto # auto | none — see S11
66
- build_ready: true # caller asserts the build-ready role (status:ready) is/would be applied — see S15
66
+ build_ready: true # caller asserts the configured build-ready role (github.labels.build.ready, default status:ready) is/would be applied — see S15
67
67
  child_refs: ["my-org/my-repo#601", "my-org/my-repo#602"] # known child work (sub-issues / task-list / "Blocked by" parentage) — see S15
68
68
  prd_source: "https://notion.so/..." # set when the issue was generated from a PRD — requires the Source Requirement section, see S16
69
69
  ```
@@ -213,9 +213,11 @@ This gate depends on S11. It is `N/A` for containers — an **Epic**, or any ite
213
213
 
214
214
  #### S15 — Leaf-only build-ready
215
215
 
216
- Enforces the build-side of the vendor-neutral `leaf-only-lifecycle` rule: **only a leaf work unit may carry the build-ready role.** This is the symmetric write-side guard for the GitHub validator a stale or hand-applied `status:ready` on a container is a lifecycle error and must FAIL here, regardless of how the issue was produced. (Mirrors the "Build-ready label is leaf-only" rule that `lisa-github-write-issue` applies at write time.)
216
+ Enforces the build-side of the vendor-neutral `leaf-only-lifecycle` rule: **only a leaf work unit may carry the build-ready role.** Before evaluating this gate, resolve `READY_ROLE` from merged project config (`.lisa.config.local.json` over `.lisa.config.json`) at `github.labels.build.ready`, defaulting to `status:ready` per `config-resolution`. Use that resolved value everywhere this validator interprets build readiness; a project-specific label is not an alias for the literal default.
217
217
 
218
- **When the gate applies.** Run S15 whenever the issue is build-ready i.e. `build_ready = true`, or the spec/live labels include `status:ready`. If the issue is not build-ready, S15 is `N/A` (nothing claims a non-ready issue, so the invariant is vacuous).
218
+ This is the symmetric write-side guard for the GitHub validatora stale or hand-applied `READY_ROLE` on a container is a lifecycle error and must FAIL here, regardless of how the issue was produced. (Mirrors the "Build-ready label is leaf-only" rule that `lisa-github-write-issue` applies at write time.)
219
+
220
+ **When the gate applies.** Run S15 whenever the issue is build-ready — i.e. `build_ready = true`, or the spec/live labels include the resolved `READY_ROLE`. If the issue is not build-ready, S15 is `N/A` (nothing claims a non-ready issue, so the invariant is vacuous). For example, if `github.labels.build.ready = "queue:approved"`, a container carrying `queue:approved` FAILs S15 even when it does not carry the literal `status:ready` default.
219
221
 
220
222
  **Resolve container vs. leaf — structural first, then nominal.** Per `leaf-only-lifecycle` the classification is structural: an item is a **container** if it has child work, whatever its declared type; otherwise the **type label** decides. Determine child work from (in order) `child_refs`, native sub-issues, body task-list checkboxes, and `Blocked by #<n>` / parent references — the same hierarchy resolution `lisa-github-read-issue` uses. When validating a live ref, query sub-issues alongside the issue fetch.
221
223
 
@@ -233,7 +235,7 @@ PASS (the childless-parent exception) when the issue is build-ready and is a **l
233
235
  | Epic | no | yes | **FAIL** (childless Epic — pure rollup container, exception does not apply) |
234
236
  | any | any | no | **N/A** (not build-ready) |
235
237
 
236
- Remediation: `"Build-ready (status:ready) is leaf-only per leaf-only-lifecycle. Move status:ready off this container onto its leaf children (or, for a childless Epic, decompose it into leaf children or reclassify it to a leaf type); a parent's lifecycle state rolls up from its children and is never set to ready directly."`
238
+ Remediation (render `<READY_ROLE>` as the resolved configured label, never as a hard-coded default): `"Build-ready (<READY_ROLE>; status:ready by default) is leaf-only per leaf-only-lifecycle. Move <READY_ROLE> off this container onto its leaf children (or, for a childless Epic, decompose it into leaf children or reclassify it to a leaf type); a parent's lifecycle state rolls up from its children and is never set to ready directly."`
237
239
 
238
240
  `product_relevant: false` — a build-ready container is a lifecycle/decomposition error for the caller to repair, not a product question.
239
241
 
@@ -284,8 +286,37 @@ gh issue view <number> --repo <org>/<repo> --json number,labels,state
284
286
  ```
285
287
 
286
288
  Confirm the parent issue exists and:
287
- - For non-Sub-task children: parent has `type:Epic` label.
288
- - For Sub-task children: parent has `type:Story`, `type:Task`, `type:Bug`, or `type:Improvement` (anything that can host sub-tasks).
289
+
290
+ - For an `Epic` child, first resolve whether the validator can prove the native PRD-parent shape
291
+ allowed by `prd-lifecycle-rollup`: merged project config has `source = github` and
292
+ `tracker = github`; the spec/live child's `org` and `repo` match configured `github.org` and
293
+ `github.repo`; and `parent_ref` names that same `org/repo`. These facts are available from the
294
+ existing spec/live ref plus project config; do not infer the exception from label spelling alone.
295
+ Only in that proven same-repository GitHub self-host shape may the parent qualify by having one of
296
+ the configured PRD lifecycle labels from
297
+ `github.labels.prd` (`draft`, `ready`, `in_review`, `blocked`, `ticketed`, `shipped`, or
298
+ `verified`; defaults use the `prd-*` namespace). Resolve the configured values from
299
+ `.lisa.config.local.json` over `.lisa.config.json`, using the defaults from `config-resolution`.
300
+ The `sentinel` label is not a lifecycle role and does not qualify. This is the native
301
+ PRD→generated-Epic hierarchy used when GitHub is both source and tracker in one repository; the
302
+ PRD parent does **not** need `type:Epic`. If any self-host/same-repository predicate is false, a
303
+ PRD label does not grant the exception: native hierarchy cannot cross repositories or source
304
+ systems, so a PRD-labelled parent alone FAILs F2.
305
+ - For a `Sub-task` child: the parent has `type:Story`, `type:Task`, `type:Bug`, or
306
+ `type:Improvement` (anything that can host sub-tasks). This allowlist is unchanged; a PRD
307
+ lifecycle label or `type:Epic` alone does not qualify.
308
+ - For every other non-Sub-task child: the parent has `type:Epic`. A PRD lifecycle label alone does
309
+ not qualify, so the Epic→Story (and Epic→ordinary-leaf) hierarchy remains enforced.
310
+
311
+ | child type | relationship shape | qualifying parent label | F2 |
312
+ |---|---|---|---|
313
+ | `Epic` | source GitHub + tracker GitHub + configured child repo = parent repo | configured PRD lifecycle label | **PASS** |
314
+ | `Epic` | cross-repository or source/tracker is not same-repo GitHub | PRD lifecycle label only | **FAIL** |
315
+ | `Epic` | permitted self-host shape | unconfigured `prd-*` lookalike or `prd-intake-feedback` sentinel only | **FAIL** |
316
+ | `Sub-task` | any | `type:Story`, `type:Task`, `type:Bug`, or `type:Improvement` | **PASS** |
317
+ | `Sub-task` | any | PRD lifecycle label or `type:Epic` only | **FAIL** |
318
+ | any other non-Sub-task | any | `type:Epic` | **PASS** |
319
+ | any other non-Sub-task | any | PRD lifecycle label only | **FAIL** |
289
320
 
290
321
  #### F3 — Linked issues exist
291
322
 
@@ -293,7 +324,35 @@ For each entry in `links`, run `gh issue view <number> --repo <link-org>/<link-r
293
324
 
294
325
  #### F4 — Required labels populated
295
326
 
296
- Per `Phase 5` of `lisa-github-write-issue`, every issue MUST carry: `type:<issue_type>`, `status:<status>`, `priority:<priority>`. If any are missing from the spec / live issue, FAIL with the missing label name.
327
+ Per `Phase 5` of `lisa-github-write-issue`, every issue MUST carry
328
+ `type:<issue_type>` and `priority:<priority>`. These two labels are unconditional: if either is
329
+ missing from the proposed spec or live issue, FAIL with the missing label name.
330
+
331
+ The `status:*` requirement uses this validator's S15 leaf/container classification while preserving
332
+ the writer's documented `build_ready` control-input defaults:
333
+
334
+ 1. Classify the issue structurally using the S15 child-resolution rules. A container (any issue
335
+ with child work, plus a childless `Epic`) may omit `status:*`; its state rolls up rather than
336
+ being assigned directly.
337
+ 2. For a proposed leaf spec, normalize omitted `build_ready` to `true`, preserving the writer's
338
+ backward-compatible default-ready behavior. Explicit `build_ready: false` means backlog mode.
339
+ 3. For a live issue ref, derive `build_ready` from the labels (`true` exactly when the S15-resolved
340
+ `READY_ROLE` from `github.labels.build.ready`, default `status:ready`, is present). A live backlog leaf without a status label
341
+ therefore validates as `build_ready: false`; live data cannot distinguish an explicit false from
342
+ a historical write that omitted the label.
343
+ 4. A leaf with normalized `build_ready: true` MUST carry that same resolved `READY_ROLE`. A leaf with `build_ready: false` may omit
344
+ `status:*`.
345
+
346
+ | classification | normalized build_ready | status label | F4 |
347
+ |---|---:|---|---|
348
+ | container | any | omitted | **PASS** |
349
+ | leaf | `false` | omitted | **PASS** |
350
+ | leaf | `true` | configured build-ready role (`status:ready` by default) | **PASS** |
351
+ | leaf | `true` | omitted or a different `status:*` label | **FAIL** |
352
+
353
+ F4 does not make a container build-ready. S15 remains the independent lifecycle prohibition: any
354
+ container carrying the build-ready role still FAILs S15, even though F4's status-presence check is
355
+ not applicable to containers.
297
356
 
298
357
  #### F5 — Required external access provable
299
358
 
@@ -322,7 +381,7 @@ system, and never invent or ask for credentials inline.
322
381
 
323
382
  ## Execution
324
383
 
325
- 1. Parse `$ARGUMENTS`. If it's an issue ref, fetch via `gh issue view --json` and derive the spec fields — including `build_ready` (label set contains `status:ready`) and `child_refs` (native sub-issues plus body task-list / `Blocked by #<n>` parentage, resolved as in `lisa-github-read-issue`) so S15 can classify the issue. Otherwise parse the YAML spec.
384
+ 1. Parse `$ARGUMENTS`. Resolve `READY_ROLE` from merged `github.labels.build.ready` config (default `status:ready`). If the input is an issue ref, fetch via `gh issue view --json` and derive the spec fields — including `build_ready` (label set contains the resolved `READY_ROLE`, not a hard-coded label) and `child_refs` (native sub-issues plus body task-list / `Blocked by #<n>` parentage, resolved as in `lisa-github-read-issue`) so S15 can classify the issue. Otherwise parse the YAML spec and preserve the proposed `build_ready` value for S15/F4 normalization.
326
385
  2. Confirm `gh auth status` succeeds before any feasibility gate runs.
327
386
  3. Run every Specification gate in order. Collect PASS / FAIL / N/A with a one-line reason.
328
387
  4. Unless the caller passed `--spec-only`, run every Feasibility gate.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.221.4",
3
+ "version": "2.221.6",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -25,7 +25,7 @@ org: my-org
25
25
  repo: my-repo
26
26
  summary: "[CU-1.2] Upload contract PDF from settings"
27
27
  priority: medium
28
- parent_ref: "my-org/my-repo#1234" # Parent Epic for non-Bug/non-Epic; Story for Sub-task
28
+ parent_ref: "my-org/my-repo#1234" # Parent Epic for ordinary children; PRD for an Epic only in the same-repo GitHub self-host shape; Story/etc. for Sub-task
29
29
  body: |
30
30
  ## Context / Business Value
31
31
  ...
@@ -63,7 +63,7 @@ artifacts_attached: true # → requires Source Precedence section
63
63
  links: [{ ref: "my-org/my-repo#99", type: "is blocked by" }] # known issue links (may be empty)
64
64
  remote_links: [{ url: "https://github.com/.../pull/42", title: "PR #42" }]
65
65
  journey_followup: auto # auto | none — see S11
66
- build_ready: true # caller asserts the build-ready role (status:ready) is/would be applied — see S15
66
+ build_ready: true # caller asserts the configured build-ready role (github.labels.build.ready, default status:ready) is/would be applied — see S15
67
67
  child_refs: ["my-org/my-repo#601", "my-org/my-repo#602"] # known child work (sub-issues / task-list / "Blocked by" parentage) — see S15
68
68
  prd_source: "https://notion.so/..." # set when the issue was generated from a PRD — requires the Source Requirement section, see S16
69
69
  ```
@@ -213,9 +213,11 @@ This gate depends on S11. It is `N/A` for containers — an **Epic**, or any ite
213
213
 
214
214
  #### S15 — Leaf-only build-ready
215
215
 
216
- Enforces the build-side of the vendor-neutral `leaf-only-lifecycle` rule: **only a leaf work unit may carry the build-ready role.** This is the symmetric write-side guard for the GitHub validator a stale or hand-applied `status:ready` on a container is a lifecycle error and must FAIL here, regardless of how the issue was produced. (Mirrors the "Build-ready label is leaf-only" rule that `lisa-github-write-issue` applies at write time.)
216
+ Enforces the build-side of the vendor-neutral `leaf-only-lifecycle` rule: **only a leaf work unit may carry the build-ready role.** Before evaluating this gate, resolve `READY_ROLE` from merged project config (`.lisa.config.local.json` over `.lisa.config.json`) at `github.labels.build.ready`, defaulting to `status:ready` per `config-resolution`. Use that resolved value everywhere this validator interprets build readiness; a project-specific label is not an alias for the literal default.
217
217
 
218
- **When the gate applies.** Run S15 whenever the issue is build-ready i.e. `build_ready = true`, or the spec/live labels include `status:ready`. If the issue is not build-ready, S15 is `N/A` (nothing claims a non-ready issue, so the invariant is vacuous).
218
+ This is the symmetric write-side guard for the GitHub validatora stale or hand-applied `READY_ROLE` on a container is a lifecycle error and must FAIL here, regardless of how the issue was produced. (Mirrors the "Build-ready label is leaf-only" rule that `lisa-github-write-issue` applies at write time.)
219
+
220
+ **When the gate applies.** Run S15 whenever the issue is build-ready — i.e. `build_ready = true`, or the spec/live labels include the resolved `READY_ROLE`. If the issue is not build-ready, S15 is `N/A` (nothing claims a non-ready issue, so the invariant is vacuous). For example, if `github.labels.build.ready = "queue:approved"`, a container carrying `queue:approved` FAILs S15 even when it does not carry the literal `status:ready` default.
219
221
 
220
222
  **Resolve container vs. leaf — structural first, then nominal.** Per `leaf-only-lifecycle` the classification is structural: an item is a **container** if it has child work, whatever its declared type; otherwise the **type label** decides. Determine child work from (in order) `child_refs`, native sub-issues, body task-list checkboxes, and `Blocked by #<n>` / parent references — the same hierarchy resolution `lisa-github-read-issue` uses. When validating a live ref, query sub-issues alongside the issue fetch.
221
223
 
@@ -233,7 +235,7 @@ PASS (the childless-parent exception) when the issue is build-ready and is a **l
233
235
  | Epic | no | yes | **FAIL** (childless Epic — pure rollup container, exception does not apply) |
234
236
  | any | any | no | **N/A** (not build-ready) |
235
237
 
236
- Remediation: `"Build-ready (status:ready) is leaf-only per leaf-only-lifecycle. Move status:ready off this container onto its leaf children (or, for a childless Epic, decompose it into leaf children or reclassify it to a leaf type); a parent's lifecycle state rolls up from its children and is never set to ready directly."`
238
+ Remediation (render `<READY_ROLE>` as the resolved configured label, never as a hard-coded default): `"Build-ready (<READY_ROLE>; status:ready by default) is leaf-only per leaf-only-lifecycle. Move <READY_ROLE> off this container onto its leaf children (or, for a childless Epic, decompose it into leaf children or reclassify it to a leaf type); a parent's lifecycle state rolls up from its children and is never set to ready directly."`
237
239
 
238
240
  `product_relevant: false` — a build-ready container is a lifecycle/decomposition error for the caller to repair, not a product question.
239
241
 
@@ -284,8 +286,37 @@ gh issue view <number> --repo <org>/<repo> --json number,labels,state
284
286
  ```
285
287
 
286
288
  Confirm the parent issue exists and:
287
- - For non-Sub-task children: parent has `type:Epic` label.
288
- - For Sub-task children: parent has `type:Story`, `type:Task`, `type:Bug`, or `type:Improvement` (anything that can host sub-tasks).
289
+
290
+ - For an `Epic` child, first resolve whether the validator can prove the native PRD-parent shape
291
+ allowed by `prd-lifecycle-rollup`: merged project config has `source = github` and
292
+ `tracker = github`; the spec/live child's `org` and `repo` match configured `github.org` and
293
+ `github.repo`; and `parent_ref` names that same `org/repo`. These facts are available from the
294
+ existing spec/live ref plus project config; do not infer the exception from label spelling alone.
295
+ Only in that proven same-repository GitHub self-host shape may the parent qualify by having one of
296
+ the configured PRD lifecycle labels from
297
+ `github.labels.prd` (`draft`, `ready`, `in_review`, `blocked`, `ticketed`, `shipped`, or
298
+ `verified`; defaults use the `prd-*` namespace). Resolve the configured values from
299
+ `.lisa.config.local.json` over `.lisa.config.json`, using the defaults from `config-resolution`.
300
+ The `sentinel` label is not a lifecycle role and does not qualify. This is the native
301
+ PRD→generated-Epic hierarchy used when GitHub is both source and tracker in one repository; the
302
+ PRD parent does **not** need `type:Epic`. If any self-host/same-repository predicate is false, a
303
+ PRD label does not grant the exception: native hierarchy cannot cross repositories or source
304
+ systems, so a PRD-labelled parent alone FAILs F2.
305
+ - For a `Sub-task` child: the parent has `type:Story`, `type:Task`, `type:Bug`, or
306
+ `type:Improvement` (anything that can host sub-tasks). This allowlist is unchanged; a PRD
307
+ lifecycle label or `type:Epic` alone does not qualify.
308
+ - For every other non-Sub-task child: the parent has `type:Epic`. A PRD lifecycle label alone does
309
+ not qualify, so the Epic→Story (and Epic→ordinary-leaf) hierarchy remains enforced.
310
+
311
+ | child type | relationship shape | qualifying parent label | F2 |
312
+ |---|---|---|---|
313
+ | `Epic` | source GitHub + tracker GitHub + configured child repo = parent repo | configured PRD lifecycle label | **PASS** |
314
+ | `Epic` | cross-repository or source/tracker is not same-repo GitHub | PRD lifecycle label only | **FAIL** |
315
+ | `Epic` | permitted self-host shape | unconfigured `prd-*` lookalike or `prd-intake-feedback` sentinel only | **FAIL** |
316
+ | `Sub-task` | any | `type:Story`, `type:Task`, `type:Bug`, or `type:Improvement` | **PASS** |
317
+ | `Sub-task` | any | PRD lifecycle label or `type:Epic` only | **FAIL** |
318
+ | any other non-Sub-task | any | `type:Epic` | **PASS** |
319
+ | any other non-Sub-task | any | PRD lifecycle label only | **FAIL** |
289
320
 
290
321
  #### F3 — Linked issues exist
291
322
 
@@ -293,7 +324,35 @@ For each entry in `links`, run `gh issue view <number> --repo <link-org>/<link-r
293
324
 
294
325
  #### F4 — Required labels populated
295
326
 
296
- Per `Phase 5` of `lisa-github-write-issue`, every issue MUST carry: `type:<issue_type>`, `status:<status>`, `priority:<priority>`. If any are missing from the spec / live issue, FAIL with the missing label name.
327
+ Per `Phase 5` of `lisa-github-write-issue`, every issue MUST carry
328
+ `type:<issue_type>` and `priority:<priority>`. These two labels are unconditional: if either is
329
+ missing from the proposed spec or live issue, FAIL with the missing label name.
330
+
331
+ The `status:*` requirement uses this validator's S15 leaf/container classification while preserving
332
+ the writer's documented `build_ready` control-input defaults:
333
+
334
+ 1. Classify the issue structurally using the S15 child-resolution rules. A container (any issue
335
+ with child work, plus a childless `Epic`) may omit `status:*`; its state rolls up rather than
336
+ being assigned directly.
337
+ 2. For a proposed leaf spec, normalize omitted `build_ready` to `true`, preserving the writer's
338
+ backward-compatible default-ready behavior. Explicit `build_ready: false` means backlog mode.
339
+ 3. For a live issue ref, derive `build_ready` from the labels (`true` exactly when the S15-resolved
340
+ `READY_ROLE` from `github.labels.build.ready`, default `status:ready`, is present). A live backlog leaf without a status label
341
+ therefore validates as `build_ready: false`; live data cannot distinguish an explicit false from
342
+ a historical write that omitted the label.
343
+ 4. A leaf with normalized `build_ready: true` MUST carry that same resolved `READY_ROLE`. A leaf with `build_ready: false` may omit
344
+ `status:*`.
345
+
346
+ | classification | normalized build_ready | status label | F4 |
347
+ |---|---:|---|---|
348
+ | container | any | omitted | **PASS** |
349
+ | leaf | `false` | omitted | **PASS** |
350
+ | leaf | `true` | configured build-ready role (`status:ready` by default) | **PASS** |
351
+ | leaf | `true` | omitted or a different `status:*` label | **FAIL** |
352
+
353
+ F4 does not make a container build-ready. S15 remains the independent lifecycle prohibition: any
354
+ container carrying the build-ready role still FAILs S15, even though F4's status-presence check is
355
+ not applicable to containers.
297
356
 
298
357
  #### F5 — Required external access provable
299
358
 
@@ -322,7 +381,7 @@ system, and never invent or ask for credentials inline.
322
381
 
323
382
  ## Execution
324
383
 
325
- 1. Parse `$ARGUMENTS`. If it's an issue ref, fetch via `gh issue view --json` and derive the spec fields — including `build_ready` (label set contains `status:ready`) and `child_refs` (native sub-issues plus body task-list / `Blocked by #<n>` parentage, resolved as in `lisa-github-read-issue`) so S15 can classify the issue. Otherwise parse the YAML spec.
384
+ 1. Parse `$ARGUMENTS`. Resolve `READY_ROLE` from merged `github.labels.build.ready` config (default `status:ready`). If the input is an issue ref, fetch via `gh issue view --json` and derive the spec fields — including `build_ready` (label set contains the resolved `READY_ROLE`, not a hard-coded label) and `child_refs` (native sub-issues plus body task-list / `Blocked by #<n>` parentage, resolved as in `lisa-github-read-issue`) so S15 can classify the issue. Otherwise parse the YAML spec and preserve the proposed `build_ready` value for S15/F4 normalization.
326
385
  2. Confirm `gh auth status` succeeds before any feasibility gate runs.
327
386
  3. Run every Specification gate in order. Collect PASS / FAIL / N/A with a one-line reason.
328
387
  4. Unless the caller passed `--spec-only`, run every Feasibility gate.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.221.4",
3
+ "version": "2.221.6",
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.221.4",
3
+ "version": "2.221.6",
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-cdk",
3
- "version": "2.221.4",
3
+ "version": "2.221.6",
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.221.4",
3
+ "version": "2.221.6",
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.221.4",
3
+ "version": "2.221.6",
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",
3
- "version": "2.221.4",
3
+ "version": "2.221.6",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"