@codyswann/lisa 2.127.0 → 2.128.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/package.json +1 -1
  2. package/plugins/lisa/.claude-plugin/plugin.json +5 -1
  3. package/plugins/lisa/.codex-plugin/hooks.json +4 -0
  4. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  5. package/plugins/lisa/commands/parity-code-review.md +6 -0
  6. package/plugins/lisa/commands/parity-code-simplifier.md +6 -0
  7. package/plugins/lisa/commands/parity-coderabbit.md +6 -0
  8. package/plugins/lisa/commands/parity-safety-net-rules.md +6 -0
  9. package/plugins/lisa/commands/parity-sentry-sdk-setup.md +6 -0
  10. package/plugins/lisa/commands/parity-sentry-seer.md +6 -0
  11. package/plugins/lisa/commands/parity-skill-creator.md +6 -0
  12. package/plugins/lisa/hooks/parity-safety-net.sh +102 -0
  13. package/plugins/lisa/rules/eager/base-rules.md +1 -1
  14. package/plugins/lisa/rules/eager/leaf-only-lifecycle.md +4 -4
  15. package/plugins/lisa/rules/eager/repo-scope-split.md +1 -1
  16. package/plugins/lisa/rules/reference/config-resolution.md +1 -1
  17. package/plugins/lisa/rules/reference/leaf-only-lifecycle.md +9 -9
  18. package/plugins/lisa/rules/reference/repo-scope-split.md +2 -2
  19. package/plugins/lisa/skills/github-build-intake/SKILL.md +7 -7
  20. package/plugins/lisa/skills/github-validate-issue/SKILL.md +10 -11
  21. package/plugins/lisa/skills/intake-explain/SKILL.md +3 -3
  22. package/plugins/lisa/skills/jira-build-intake/SKILL.md +7 -7
  23. package/plugins/lisa/skills/jira-validate-ticket/SKILL.md +10 -11
  24. package/plugins/lisa/skills/linear-build-intake/SKILL.md +7 -7
  25. package/plugins/lisa/skills/linear-validate-issue/SKILL.md +10 -11
  26. package/plugins/lisa/skills/parity-code-review/SKILL.md +83 -0
  27. package/plugins/lisa/skills/parity-code-review/agents/openai.yaml +4 -0
  28. package/plugins/lisa/skills/parity-code-simplifier/SKILL.md +76 -0
  29. package/plugins/lisa/skills/parity-code-simplifier/agents/openai.yaml +4 -0
  30. package/plugins/lisa/skills/parity-coderabbit/SKILL.md +77 -0
  31. package/plugins/lisa/skills/parity-coderabbit/agents/openai.yaml +4 -0
  32. package/plugins/lisa/skills/parity-safety-net-rules/SKILL.md +144 -0
  33. package/plugins/lisa/skills/parity-safety-net-rules/agents/openai.yaml +4 -0
  34. package/plugins/lisa/skills/parity-sentry-sdk-setup/SKILL.md +211 -0
  35. package/plugins/lisa/skills/parity-sentry-sdk-setup/agents/openai.yaml +4 -0
  36. package/plugins/lisa/skills/parity-sentry-seer/SKILL.md +135 -0
  37. package/plugins/lisa/skills/parity-sentry-seer/agents/openai.yaml +4 -0
  38. package/plugins/lisa/skills/parity-skill-creator/SKILL.md +149 -0
  39. package/plugins/lisa/skills/parity-skill-creator/agents/openai.yaml +4 -0
  40. package/plugins/lisa/skills/repair-intake/SKILL.md +2 -2
  41. package/plugins/lisa/skills/tracker-build-intake/SKILL.md +4 -4
  42. package/plugins/lisa-agy/commands/parity-code-review.md +6 -0
  43. package/plugins/lisa-agy/commands/parity-code-simplifier.md +6 -0
  44. package/plugins/lisa-agy/commands/parity-coderabbit.md +6 -0
  45. package/plugins/lisa-agy/commands/parity-safety-net-rules.md +6 -0
  46. package/plugins/lisa-agy/commands/parity-sentry-sdk-setup.md +6 -0
  47. package/plugins/lisa-agy/commands/parity-sentry-seer.md +6 -0
  48. package/plugins/lisa-agy/commands/parity-skill-creator.md +6 -0
  49. package/plugins/lisa-agy/plugin.json +1 -1
  50. package/plugins/lisa-agy/skills/github-build-intake/SKILL.md +7 -7
  51. package/plugins/lisa-agy/skills/github-validate-issue/SKILL.md +10 -11
  52. package/plugins/lisa-agy/skills/intake-explain/SKILL.md +3 -3
  53. package/plugins/lisa-agy/skills/jira-build-intake/SKILL.md +7 -7
  54. package/plugins/lisa-agy/skills/jira-validate-ticket/SKILL.md +10 -11
  55. package/plugins/lisa-agy/skills/linear-build-intake/SKILL.md +7 -7
  56. package/plugins/lisa-agy/skills/linear-validate-issue/SKILL.md +10 -11
  57. package/plugins/lisa-agy/skills/parity-code-review/SKILL.md +83 -0
  58. package/plugins/lisa-agy/skills/parity-code-simplifier/SKILL.md +76 -0
  59. package/plugins/lisa-agy/skills/parity-coderabbit/SKILL.md +77 -0
  60. package/plugins/lisa-agy/skills/parity-safety-net-rules/SKILL.md +144 -0
  61. package/plugins/lisa-agy/skills/parity-sentry-sdk-setup/SKILL.md +211 -0
  62. package/plugins/lisa-agy/skills/parity-sentry-seer/SKILL.md +135 -0
  63. package/plugins/lisa-agy/skills/parity-skill-creator/SKILL.md +149 -0
  64. package/plugins/lisa-agy/skills/repair-intake/SKILL.md +2 -2
  65. package/plugins/lisa-agy/skills/tracker-build-intake/SKILL.md +4 -4
  66. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  67. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  68. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  69. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  70. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  71. package/plugins/lisa-copilot/.claude-plugin/plugin.json +5 -1
  72. package/plugins/lisa-copilot/commands/parity-code-review.md +6 -0
  73. package/plugins/lisa-copilot/commands/parity-code-simplifier.md +6 -0
  74. package/plugins/lisa-copilot/commands/parity-coderabbit.md +6 -0
  75. package/plugins/lisa-copilot/commands/parity-safety-net-rules.md +6 -0
  76. package/plugins/lisa-copilot/commands/parity-sentry-sdk-setup.md +6 -0
  77. package/plugins/lisa-copilot/commands/parity-sentry-seer.md +6 -0
  78. package/plugins/lisa-copilot/commands/parity-skill-creator.md +6 -0
  79. package/plugins/lisa-copilot/hooks/parity-safety-net.sh +102 -0
  80. package/plugins/lisa-copilot/rules/eager/base-rules.md +1 -1
  81. package/plugins/lisa-copilot/rules/eager/leaf-only-lifecycle.md +4 -4
  82. package/plugins/lisa-copilot/rules/eager/repo-scope-split.md +1 -1
  83. package/plugins/lisa-copilot/rules/reference/config-resolution.md +1 -1
  84. package/plugins/lisa-copilot/rules/reference/leaf-only-lifecycle.md +9 -9
  85. package/plugins/lisa-copilot/rules/reference/repo-scope-split.md +2 -2
  86. package/plugins/lisa-copilot/skills/github-build-intake/SKILL.md +7 -7
  87. package/plugins/lisa-copilot/skills/github-validate-issue/SKILL.md +10 -11
  88. package/plugins/lisa-copilot/skills/intake-explain/SKILL.md +3 -3
  89. package/plugins/lisa-copilot/skills/jira-build-intake/SKILL.md +7 -7
  90. package/plugins/lisa-copilot/skills/jira-validate-ticket/SKILL.md +10 -11
  91. package/plugins/lisa-copilot/skills/linear-build-intake/SKILL.md +7 -7
  92. package/plugins/lisa-copilot/skills/linear-validate-issue/SKILL.md +10 -11
  93. package/plugins/lisa-copilot/skills/parity-code-review/SKILL.md +83 -0
  94. package/plugins/lisa-copilot/skills/parity-code-simplifier/SKILL.md +76 -0
  95. package/plugins/lisa-copilot/skills/parity-coderabbit/SKILL.md +77 -0
  96. package/plugins/lisa-copilot/skills/parity-safety-net-rules/SKILL.md +144 -0
  97. package/plugins/lisa-copilot/skills/parity-sentry-sdk-setup/SKILL.md +211 -0
  98. package/plugins/lisa-copilot/skills/parity-sentry-seer/SKILL.md +135 -0
  99. package/plugins/lisa-copilot/skills/parity-skill-creator/SKILL.md +149 -0
  100. package/plugins/lisa-copilot/skills/repair-intake/SKILL.md +2 -2
  101. package/plugins/lisa-copilot/skills/tracker-build-intake/SKILL.md +4 -4
  102. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  103. package/plugins/lisa-cursor/commands/parity-code-review.md +6 -0
  104. package/plugins/lisa-cursor/commands/parity-code-simplifier.md +6 -0
  105. package/plugins/lisa-cursor/commands/parity-coderabbit.md +6 -0
  106. package/plugins/lisa-cursor/commands/parity-safety-net-rules.md +6 -0
  107. package/plugins/lisa-cursor/commands/parity-sentry-sdk-setup.md +6 -0
  108. package/plugins/lisa-cursor/commands/parity-sentry-seer.md +6 -0
  109. package/plugins/lisa-cursor/commands/parity-skill-creator.md +6 -0
  110. package/plugins/lisa-cursor/hooks/hooks.json +4 -0
  111. package/plugins/lisa-cursor/hooks/parity-safety-net.sh +102 -0
  112. package/plugins/lisa-cursor/rules/base-rules.mdc +1 -1
  113. package/plugins/lisa-cursor/rules/config-resolution-reference.mdc +1 -1
  114. package/plugins/lisa-cursor/rules/leaf-only-lifecycle-reference.mdc +9 -9
  115. package/plugins/lisa-cursor/rules/leaf-only-lifecycle.mdc +4 -4
  116. package/plugins/lisa-cursor/rules/repo-scope-split-reference.mdc +2 -2
  117. package/plugins/lisa-cursor/rules/repo-scope-split.mdc +1 -1
  118. package/plugins/lisa-cursor/skills/github-build-intake/SKILL.md +7 -7
  119. package/plugins/lisa-cursor/skills/github-validate-issue/SKILL.md +10 -11
  120. package/plugins/lisa-cursor/skills/intake-explain/SKILL.md +3 -3
  121. package/plugins/lisa-cursor/skills/jira-build-intake/SKILL.md +7 -7
  122. package/plugins/lisa-cursor/skills/jira-validate-ticket/SKILL.md +10 -11
  123. package/plugins/lisa-cursor/skills/linear-build-intake/SKILL.md +7 -7
  124. package/plugins/lisa-cursor/skills/linear-validate-issue/SKILL.md +10 -11
  125. package/plugins/lisa-cursor/skills/parity-code-review/SKILL.md +83 -0
  126. package/plugins/lisa-cursor/skills/parity-code-simplifier/SKILL.md +76 -0
  127. package/plugins/lisa-cursor/skills/parity-coderabbit/SKILL.md +77 -0
  128. package/plugins/lisa-cursor/skills/parity-safety-net-rules/SKILL.md +144 -0
  129. package/plugins/lisa-cursor/skills/parity-sentry-sdk-setup/SKILL.md +211 -0
  130. package/plugins/lisa-cursor/skills/parity-sentry-seer/SKILL.md +135 -0
  131. package/plugins/lisa-cursor/skills/parity-skill-creator/SKILL.md +149 -0
  132. package/plugins/lisa-cursor/skills/repair-intake/SKILL.md +2 -2
  133. package/plugins/lisa-cursor/skills/tracker-build-intake/SKILL.md +4 -4
  134. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  135. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  136. package/plugins/lisa-expo-agy/plugin.json +1 -1
  137. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  138. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  139. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  140. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  141. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  142. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  143. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  144. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  145. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  146. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  147. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  148. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  149. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  150. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  151. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  152. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  153. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  154. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  155. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  156. package/plugins/lisa-rails-agy/plugin.json +1 -1
  157. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  158. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  159. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  160. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  161. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  162. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  163. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  164. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  165. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  166. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  167. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  168. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  169. package/plugins/src/base/.claude-plugin/plugin.json +2 -1
  170. package/plugins/src/base/commands/parity-code-review.md +6 -0
  171. package/plugins/src/base/commands/parity-code-simplifier.md +6 -0
  172. package/plugins/src/base/commands/parity-coderabbit.md +6 -0
  173. package/plugins/src/base/commands/parity-safety-net-rules.md +6 -0
  174. package/plugins/src/base/commands/parity-sentry-sdk-setup.md +6 -0
  175. package/plugins/src/base/commands/parity-sentry-seer.md +6 -0
  176. package/plugins/src/base/commands/parity-skill-creator.md +6 -0
  177. package/plugins/src/base/hooks/parity-safety-net.sh +102 -0
  178. package/plugins/src/base/rules/eager/base-rules.md +1 -1
  179. package/plugins/src/base/rules/eager/leaf-only-lifecycle.md +4 -4
  180. package/plugins/src/base/rules/eager/repo-scope-split.md +1 -1
  181. package/plugins/src/base/rules/reference/config-resolution.md +1 -1
  182. package/plugins/src/base/rules/reference/leaf-only-lifecycle.md +9 -9
  183. package/plugins/src/base/rules/reference/repo-scope-split.md +2 -2
  184. package/plugins/src/base/skills/github-build-intake/SKILL.md +7 -7
  185. package/plugins/src/base/skills/github-validate-issue/SKILL.md +10 -11
  186. package/plugins/src/base/skills/intake-explain/SKILL.md +3 -3
  187. package/plugins/src/base/skills/jira-build-intake/SKILL.md +7 -7
  188. package/plugins/src/base/skills/jira-validate-ticket/SKILL.md +10 -11
  189. package/plugins/src/base/skills/linear-build-intake/SKILL.md +7 -7
  190. package/plugins/src/base/skills/linear-validate-issue/SKILL.md +10 -11
  191. package/plugins/src/base/skills/parity-code-review/SKILL.md +83 -0
  192. package/plugins/src/base/skills/parity-code-simplifier/SKILL.md +76 -0
  193. package/plugins/src/base/skills/parity-coderabbit/SKILL.md +77 -0
  194. package/plugins/src/base/skills/parity-safety-net-rules/SKILL.md +144 -0
  195. package/plugins/src/base/skills/parity-sentry-sdk-setup/SKILL.md +211 -0
  196. package/plugins/src/base/skills/parity-sentry-seer/SKILL.md +135 -0
  197. package/plugins/src/base/skills/parity-skill-creator/SKILL.md +149 -0
  198. package/plugins/src/base/skills/repair-intake/SKILL.md +2 -2
  199. package/plugins/src/base/skills/tracker-build-intake/SKILL.md +4 -4
  200. package/scripts/plugin-parity-drift.mjs +9 -1
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: github-build-intake
3
- description: "GitHub counterpart to lisa:jira-build-intake. Scans a GitHub repository for issues carrying the configured `ready` build label, processes the first eligible issue, runs leaf work via lisa:github-agent, relabels to the configured `done` label on completion, then exits. Enforces the claim-time arm of the `leaf-only-lifecycle` rule: a parent/container with open child work (or a childless Epic/Story/Spike) that still carries a stale build-ready label is moved out of the ready pickup queue into the configured `claimed` label with a lifecycle-repair comment, never dispatched to lisa:github-agent. The `ready` label is the human-flipped signal that an issue is truly ready for direct development pickup — mirroring how Notion PRDs work product Draft → Ready → (us) In Review → Blocked|Ticketed."
3
+ description: "GitHub counterpart to lisa:jira-build-intake. Scans a GitHub repository for issues carrying the configured `ready` build label, processes the first eligible issue, runs leaf work via lisa:github-agent, relabels to the configured `done` label on completion, then exits. Enforces the claim-time arm of the `leaf-only-lifecycle` rule: a parent/container with open child work (or a childless Epic) that still carries a stale build-ready label is moved out of the ready pickup queue into the configured `claimed` label with a lifecycle-repair comment, never dispatched to lisa:github-agent. The `ready` label is the human-flipped signal that an issue is truly ready for direct development pickup — mirroring how Notion PRDs work product Draft → Ready → (us) In Review → Blocked|Ticketed."
4
4
  allowed-tools: ["Skill", "Bash"]
5
5
  ---
6
6
 
@@ -209,16 +209,16 @@ Classify and act (first match wins). `type:` is read from the issue's labels (`t
209
209
  | Condition | Class | Action |
210
210
  |---|---|---|
211
211
  | `OPEN_CHILDREN > 0` (open child work, any type) | **Container** | **Move to `$CLAIMED` as lifecycle repair — do NOT dispatch** |
212
- | no open children AND `type {Epic, Story, Spike}` | **Childless container-type** | **Move to `$CLAIMED` as lifecycle repair — do NOT dispatch** |
213
- | no open children AND `type {Bug, Task, Sub-task, Improvement}` (or no `type:` label) | **Leaf work unit** | **Proceed to 3b claim** |
212
+ | no open children AND `type = Epic` | **Childless Epic (pure rollup container)** | **Move to `$CLAIMED` as lifecycle repair — do NOT dispatch** |
213
+ | no open children AND `type Epic` (Bug, Task, Sub-task, Improvement, Story, Spike, or no `type:` label) | **Leaf work unit** | **Proceed to 3b claim** |
214
214
 
215
- The childless-parent exception is narrow: childlessness enables direct build-agent dispatch **only** for types that are leaf work units to begin with. A childless Epic/Story/Spike is an incomplete decomposition, not an implementable unit it is moved out of the ready pickup queue for repair/rollup and never dispatched.
215
+ The childless-parent exception promotes every childless type **except Epic** to a dispatchable leaf: a childless Story is a directly shippable increment and a childless Spike *is* the investigation unit, so neither is stranded. Only a childless **Epic** is held back — an Epic is a pure rollup container by design, and a childless one is an incomplete decomposition or a mis-applied role, moved out of the ready pickup queue for repair/rollup and never dispatched.
216
216
 
217
217
  **Lifecycle repair (default action for a flagged container).** Move the issue out of the pickup queue by removing `$READY` and adding `$CLAIMED`, post a single lifecycle-repair comment, and record the issue under "Repaired (container)" in the summary. Do NOT invoke `lisa:github-agent`. Keep the comment idempotent — skip posting if an identical `[claude-build-intake]` lifecycle-repair comment already exists on the issue, so a re-entrant cycle doesn't spam it.
218
218
 
219
219
  ```bash
220
220
  gh issue edit <number> --repo <org>/<repo> --remove-label "$READY" --add-label "$CLAIMED"
221
- gh issue comment <number> --repo <org>/<repo> --body "[claude-build-intake] Lifecycle repair: this issue carried the build-ready role ($READY) but is a parent/container with open child work (or a childless Epic/Story/Spike). I moved it to $CLAIMED without invoking the build agent. For parent/container issues, $CLAIMED means rollup/build-lane progress through child/leaf work; direct implementation must happen on leaf issues. Build-ready is leaf-only per leaf-only-lifecycle — move $READY onto its leaf children, or decompose/reclassify a childless Epic/Story/Spike."
221
+ gh issue comment <number> --repo <org>/<repo> --body "[claude-build-intake] Lifecycle repair: this issue carried the build-ready role ($READY) but is a parent/container with open child work (or a childless Epic). I moved it to $CLAIMED without invoking the build agent. For parent/container issues, $CLAIMED means rollup/build-lane progress through child/leaf work; direct implementation must happen on leaf issues. Build-ready is leaf-only per leaf-only-lifecycle — move $READY onto its leaf children, or decompose/reclassify a childless Epic."
222
222
  ```
223
223
 
224
224
  This gate never blocks a legitimate flat Task/Bug: those have no open children and a leaf `type:`, so they fall straight through to the claim in 3b.
@@ -326,7 +326,7 @@ Total PRs opened: <n>
326
326
 
327
327
  ## Idempotency & safety
328
328
 
329
- - **Leaf-only claim gate runs first**: Phase 3a classifies each candidate before any leaf claim; a container with open child work (or a childless Epic/Story/Spike) is moved `$READY` → `$CLAIMED` as lifecycle repair and never dispatched. The lifecycle-repair comment is idempotent — a re-entrant cycle does not re-post it.
329
+ - **Leaf-only claim gate runs first**: Phase 3a classifies each candidate before any leaf claim; a container with open child work (or a childless Epic) is moved `$READY` → `$CLAIMED` as lifecycle repair and never dispatched. The lifecycle-repair comment is idempotent — a re-entrant cycle does not re-post it.
330
330
  - **Dependency hold runs before leaf claim**: explicit `Blocked by:` relationships are resolved after container repair is ruled out but before `$READY → $CLAIMED`; active blockers leave the leaf candidate in `$READY` and are reported as skipped, not blocked.
331
331
  - **Claim-first ordering**: `$CLAIMED` set BEFORE `lisa:github-agent` invocation for leaves; containers are also moved to `$CLAIMED` to leave the ready pickup queue, but are not dispatched.
332
332
  - **No writes outside the lifecycle**: this skill only relabels `$READY → $CLAIMED` and `$CLAIMED → $DONE`. For containers, `$READY → $CLAIMED` is a lifecycle repair, not a direct build claim. Every other label change is owned by `lisa:github-agent`.
@@ -351,7 +351,7 @@ If the repo has not adopted the `status:*` label namespace, this skill cannot ru
351
351
 
352
352
  ## Rules
353
353
 
354
- - **Dispatch leaves only.** Per the `leaf-only-lifecycle` rule, never dispatch a container — an issue with open child work, or a childless Epic/Story/Spike — even if it carries the build-ready role. Move it `$READY → $CLAIMED` as lifecycle repair (Phase 3a); never silently implement a container.
354
+ - **Dispatch leaves only.** Per the `leaf-only-lifecycle` rule, never dispatch a container — an issue with open child work, or a childless Epic — even if it carries the build-ready role. Move it `$READY → $CLAIMED` as lifecycle repair (Phase 3a); never silently implement a container.
355
355
  - Never relabel an issue outside the cycle's allowed transitions. The `$CLAIMED` label is the signature of cycle ownership for leaves, and the parent/container progress state for lifecycle repairs.
356
356
  - Never bypass `lisa:github-agent` to do build work directly. `lisa:github-agent` owns the per-issue lifecycle.
357
357
  - Never auto-transition past `$DONE`. Downstream labels (terminal `status:done`, etc.) are owned by QA / PM / merge automation.
@@ -161,11 +161,11 @@ If the spec doesn't set `authenticated_surface`, infer it: scan the body and AC
161
161
 
162
162
  #### S10 — Repository section, single-repo scope
163
163
 
164
- When `issue_type ∈ {Bug, Task, Sub-task, Improvement}`, body must contain `## Repository` naming exactly one repo. Multiple repos OR cross-repo references in AC: FAIL with recommendation `"Split into per-repo work units under a shared parent Story (see lisa:task-decomposition step 1.5)"`.
164
+ When `issue_type ∈ {Bug, Task, Sub-task, Improvement}` — or a **build-ready childless Story/Spike** (a claimable leaf per `leaf-only-lifecycle`) — body must contain `## Repository` naming exactly one repo. Multiple repos OR cross-repo references in AC: FAIL with recommendation `"Split into per-repo work units under a shared parent Story (see lisa:task-decomposition step 1.5)"`.
165
165
 
166
166
  (GitHub Issues live in one repo by definition, so the `## Repository` section is technically redundant — keep it for parity with the JIRA path so downstream tooling sees the same shape. Cross-repo references in AC are still possible and still fail this gate.)
167
167
 
168
- Story / Epic / Spike: skipped (may span repos — these are coordination containers, not work units).
168
+ An **Epic**, or a **Story/Spike that still holds child work** (or is not build-ready): skipped (may span repos — coordination containers, not claimable leaf work units).
169
169
 
170
170
  This gate is `product_relevant: false` because cross-repo work units are not a product question — they are a decomposition error. Callers (`lisa:github-to-tracker`, `lisa:notion-to-tracker`, etc.) MUST pre-split cross-repo work into per-repo work units during the decomposition phase per `lisa:task-decomposition` step 1.5; an S10 failure here indicates the agent skipped that step and must auto-split + revalidate before writing, not surface a clarifying comment to product.
171
171
 
@@ -199,7 +199,7 @@ When `issue_type ∈ {Bug, Task, Sub-task, Improvement}` AND `runtime_behavior_c
199
199
 
200
200
  FAIL when the Validation Journey is present but declares zero `[EVIDENCE: name]` markers, or when any marker name is empty, duplicated, or not kebab-case. A behavior-changing work unit SHOULD declare both a success marker and an error/edge marker; a journey with only one marker passes but the remediation should recommend adding the error/edge case.
201
201
 
202
- This gate depends on S11. It is `N/A` for Epic / Story / Spike (coordination containers, not work units) and for leaf units with `runtime_behavior_change = false` (doc-only / config-only / type-only). If S11 fails because the Validation Journey is absent, S14 also FAILs (there is no manifest to bind) with remediation pointing back to `lisa:github-add-journey`.
202
+ This gate depends on S11. It is `N/A` for containers — an **Epic**, or any item with open child work (coordination containers, not work units) and for leaf units with `runtime_behavior_change = false` (doc-only / config-only / type-only). If S11 fails because the Validation Journey is absent, S14 also FAILs (there is no manifest to bind) with remediation pointing back to `lisa:github-add-journey`.
203
203
 
204
204
  #### S15 — Leaf-only build-ready
205
205
 
@@ -211,20 +211,19 @@ Enforces the build-side of the vendor-neutral `leaf-only-lifecycle` rule: **only
211
211
 
212
212
  Apply this decision and FAIL the two invariant-violating cases:
213
213
 
214
- 1. **Container with child work + build-ready** — `issue_type ∈ {Epic, Story, Spike}` OR child work is present (any type that has children), AND build-ready. FAIL. A parent organizes work; it is never claimed and implemented directly. Its lifecycle state rolls up from its children.
215
- 2. **Childless container-type + build-ready** — `issue_type {Epic, Story, Spike}` with **no** child work, AND build-ready. Still FAIL: these types are coordination containers by design, and an empty one is an incomplete decomposition, not an implementable unit (the childless-parent exception in `leaf-only-lifecycle` does **not** promote an Epic/Story/Spike to build-ready).
214
+ 1. **Container with child work + build-ready** — child work is present (any type that has open children), AND build-ready. FAIL. A parent organizes work; it is never claimed and implemented directly. Its lifecycle state rolls up from its children.
215
+ 2. **Childless Epic + build-ready** — `issue_type = Epic` with **no** child work, AND build-ready. Still FAIL: an Epic is a pure rollup container by design, and a childless one is an incomplete decomposition or a mis-applied role, not an implementable unit. (A childless Story or Spike is **not** failed here — the childless-parent exception in `leaf-only-lifecycle` promotes every childless non-Epic type to a build-ready leaf.)
216
216
 
217
- PASS (the childless-parent exception) when the issue is build-ready and is a **leaf work unit**: `issue_type {Bug, Task, Sub-task, Improvement}` AND has **no** child work. A flat Task or Bug with no sub-issues is a valid build-ready leaf and must not be stranded.
217
+ PASS (the childless-parent exception) when the issue is build-ready and is a **leaf work unit**: it has **no** open child work and `issue_type Epic` (i.e. `Bug, Task, Sub-task, Improvement`, or a childless `Story` / `Spike`). A flat Task/Bug, or a childless Story/Spike with no sub-issues, is a valid build-ready leaf and must not be stranded.
218
218
 
219
219
  | issue_type | has child work | build-ready | S15 |
220
220
  |---|---|---|---|
221
- | Bug / Task / Sub-task / Improvement | no | yes | **PASS** (leaf) |
222
- | Bug / Task / Sub-task / Improvement | yes | yes | **FAIL** (structurally a container) |
223
- | Epic / Story / Spike | yes | yes | **FAIL** (container with children) |
224
- | Epic / Story / Spike | no | yes | **FAIL** (childless container-type, exception does not apply) |
221
+ | Bug / Task / Sub-task / Improvement / Story / Spike | no | yes | **PASS** (leaf) |
222
+ | any type | yes | yes | **FAIL** (structurally a container) |
223
+ | Epic | no | yes | **FAIL** (childless Epic — pure rollup container, exception does not apply) |
225
224
  | any | any | no | **N/A** (not build-ready) |
226
225
 
227
- 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/Story/Spike, 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."`
226
+ 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."`
228
227
 
229
228
  `product_relevant: false` — a build-ready container is a lifecycle/decomposition error for the caller to repair, not a product question.
230
229
 
@@ -90,7 +90,7 @@ Use verdicts as stable operator language, not as an excuse to dump raw tracker s
90
90
  - `ELIGIBLE_FOR_REPAIR`: the item is Lisa-owned, stale or stuck enough to qualify for `/lisa:repair-intake`, and repair suppression rules are not currently preventing action.
91
91
  - `WAITING_ON_STALENESS`: the item is Lisa-owned but too fresh to repair yet; explain which activity signal or freshness window is still protecting it from a repair loop.
92
92
  - `HELD_BY_BLOCKERS`: the item is otherwise actionable, but explicit blockers or dependency holds mean Lisa would wait rather than claim it.
93
- - `NON_LEAF_CONTAINER`: the item is structurally a container, childless Epic/Story/Spike, or otherwise not directly buildable; explain that direct build pickup is disallowed until decomposition or reclassification happens.
93
+ - `NON_LEAF_CONTAINER`: the item is structurally a container, childless Epic, or otherwise not directly buildable; explain that direct build pickup is disallowed until decomposition or reclassification happens.
94
94
  - `PRODUCT_OWNED_STATE`: the item is currently in a product-owned role or pre-intake lane, so Lisa should not mutate it yet.
95
95
  - `MISCONFIGURED`: Lisa could not resolve the item's queue, lifecycle namespace, repo scope, or another required contract signal confidently enough to explain actionability.
96
96
 
@@ -137,7 +137,7 @@ Report repair readiness in this order:
137
137
 
138
138
  The explanation must stay aligned with existing Lisa rules:
139
139
 
140
- - If a build item is a parent/container or a childless Epic/Story/Spike, explain the leaf-only gate and say direct build pickup is not allowed.
140
+ - If a build item is a parent/container or a childless Epic, explain the leaf-only gate and say direct build pickup is not allowed.
141
141
  - If a build item has active blockers, list the blocker refs and explain that intake would hold or skip it until they clear.
142
142
  - If a PRD is in a product-owned role such as `draft`, `shipped`, or `verified`, explain why intake or repair will not mutate it.
143
143
  - If a claimed, in-review, or blocked item is not yet repairable, explain the relevant staleness or backoff condition at a human-readable level.
@@ -189,7 +189,7 @@ For GitHub build items, collect these reader signals before choosing a verdict:
189
189
  Apply gate verdicts in the same order as build intake:
190
190
 
191
191
  1. **Repo-scope gate.** A build item carrying `repo:<other>` and not `repo:<current>` is outside this repo's pickup lane. Return `MISCONFIGURED` when repo scope is absent or contradictory enough that the current repo cannot be determined confidently; otherwise explain the repo-scope mismatch and recommend running intake in the target repo or fixing the `repo:<name>` label. For an unlabeled item whose target repo is obvious from the item body, report the inferred repo signal but stay read-only: execution intake would stamp `repo:<name>`, while intake-explain only says it would do so. A multi-repo leaf is not directly buildable; explain that execution intake would split it per `repo-scope-split`, but this read-only diagnosis does not split.
192
- 2. **Leaf-only gate.** If the item has open child work from native GitHub sub-issues or body parentage, return `NON_LEAF_CONTAINER` and explain that direct build pickup is leaf-only per `leaf-only-lifecycle`. If it has no open children but carries a container type (`type:Epic`, `type:Story`, or `type:Spike`), also return `NON_LEAF_CONTAINER` because a childless container type still needs decomposition or reclassification. The next action is decomposition, moving `status:ready` to leaf children, or correcting the issue type. Execution build intake would move such a stale ready container out of the pickup queue; this read-only diagnosis must not perform that repair.
192
+ 2. **Leaf-only gate.** If the item has open child work from native GitHub sub-issues or body parentage, return `NON_LEAF_CONTAINER` and explain that direct build pickup is leaf-only per `leaf-only-lifecycle`. If it has no open children but carries `type:Epic`, also return `NON_LEAF_CONTAINER` because a childless Epic is a pure rollup container that still needs decomposition or reclassification. (A childless `type:Story` or `type:Spike` is a valid leaf per `leaf-only-lifecycle` and is NOT a `NON_LEAF_CONTAINER` it is directly buildable.) The next action for a childless Epic is decomposition, moving `status:ready` to leaf children, or correcting the issue type. Execution build intake would move such a stale ready container out of the pickup queue; this read-only diagnosis must not perform that repair.
193
193
  3. **Dependency hold gate.** If a single-repo leaf for the current repo has explicit blockers, read each blocker. Closed blockers are clear. Open blockers are clear only when they carry a cleared build status such as `status:code-review`, `status:on-dev`, `status:on-stg`, `status:done`, or the configured done-equivalent labels. Open blockers with `status:ready`, `status:in-progress`, no cleared status label, or inaccessible state are active. Return `HELD_BY_BLOCKERS`, list the active blocker refs, and make the next action blocker resolution rather than `/lisa:intake`.
194
194
  4. **Ready leaf.** A build item in the configured ready role, scoped to the current repo, with no open child work and no active blockers returns `ELIGIBLE_FOR_INTAKE`. The `Why:` line should say it is a single-repo leaf for the current repo and that leaf-only, repo-scope, and dependency gates all pass.
195
195
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jira-build-intake
3
- description: "Symmetric counterpart to notion-prd-intake on the JIRA side. Scans a JIRA project (or JQL filter) for tickets in the configured `ready` status, claims the first eligible ticket by transitioning to the configured `claimed` status, runs the implementation/build flow via jira-agent, transitions to the configured `done` status on completion, then exits. Enforces the claim-time arm of the `leaf-only-lifecycle` rule: a parent/container with open child work (or a childless Epic/Story/Spike) that still carries a stale build-ready status is skipped or safe-blocked with a lifecycle-repair comment, never claimed. The `ready` status is the human-flipped signal that a TODO ticket is truly ready for development — mirroring how Notion PRDs work product Draft → Ready → (us) In Review → Blocked|Ticketed."
3
+ description: "Symmetric counterpart to notion-prd-intake on the JIRA side. Scans a JIRA project (or JQL filter) for tickets in the configured `ready` status, claims the first eligible ticket by transitioning to the configured `claimed` status, runs the implementation/build flow via jira-agent, transitions to the configured `done` status on completion, then exits. Enforces the claim-time arm of the `leaf-only-lifecycle` rule: a parent/container with open child work (or a childless Epic) that still carries a stale build-ready status is skipped or safe-blocked with a lifecycle-repair comment, never claimed. The `ready` status is the human-flipped signal that a TODO ticket is truly ready for development — mirroring how Notion PRDs work product Draft → Ready → (us) In Review → Blocked|Ticketed."
4
4
  allowed-tools: ["Skill", "Bash"]
5
5
  ---
6
6
 
@@ -159,17 +159,17 @@ Classify and act (first match wins). The issue type comes from the ticket's `iss
159
159
  | Condition | Class | Action |
160
160
  |---|---|---|
161
161
  | `OPEN_CHILDREN > 0` (open child work, any type) | **Container** | **Skip / safe-block — do NOT claim** |
162
- | no open children AND type {Epic, Story, Spike} | **Childless container-type** | **Skip / safe-block — do NOT claim** |
163
- | no open children AND type {Bug, Task, Sub-task, Improvement} (or no recognized type) | **Leaf work unit** | **Proceed to 3b claim** |
162
+ | no open children AND type = Epic | **Childless Epic (pure rollup container)** | **Skip / safe-block — do NOT claim** |
163
+ | no open children AND type Epic (Bug, Task, Sub-task, Improvement, Story, Spike, or no recognized type) | **Leaf work unit** | **Proceed to 3b claim** |
164
164
 
165
- The childless-parent exception is narrow: childlessness enables a claim **only** for types that are leaf work units to begin with. A childless Epic/Story/Spike is an incomplete decomposition, not an implementable unit it is never claimed.
165
+ The childless-parent exception promotes every childless type **except Epic** to a claimable leaf: a childless Story is a directly shippable increment and a childless Spike *is* the investigation unit, so neither is stranded. Only a childless **Epic** stays unclaimed — an Epic is a pure rollup container by design, and a childless one is an incomplete decomposition or a mis-applied role, never an implementable unit.
166
166
 
167
167
  **Safe-block (default action for a flagged container).** Leave the build-ready status in place (don't silently transition it away — that hides the lifecycle error), post a single lifecycle-repair comment, record the ticket under "Skipped (container)" in the summary, and end the cycle. Do NOT transition to `$CLAIMED`. Keep the comment idempotent — skip posting if an identical `[claude-build-intake]` lifecycle-repair comment already exists on the ticket, so a re-entrant cycle doesn't spam it.
168
168
 
169
169
  Post via `lisa:atlassian-access` `operation: comment key: <TICKET> body: "<message>"` with:
170
170
 
171
171
  ```text
172
- [claude-build-intake] Not claimed: this ticket carries the build-ready status ($READY) but is a container with open child work (or a childless Epic/Story/Spike), which violates the leaf-only-lifecycle rule. Build-ready (status:ready) is leaf-only per leaf-only-lifecycle — an agent claims and implements leaves, never a container. Repair: move $READY off this parent onto its leaf children (or, for a childless Epic/Story/Spike, 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.
172
+ [claude-build-intake] Not claimed: this ticket carries the build-ready status ($READY) but is a container with open child work (or a childless Epic), which violates the leaf-only-lifecycle rule. Build-ready (status:ready) is leaf-only per leaf-only-lifecycle — an agent claims and implements leaves, never a container. Repair: move $READY off this parent 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.
173
173
  ```
174
174
 
175
175
  This gate never blocks a legitimate flat Task/Bug: those have no open children and a leaf type, so they fall straight through to the claim in 3b.
@@ -242,7 +242,7 @@ Total PRs opened: <n>
242
242
 
243
243
  ## Idempotency & safety
244
244
 
245
- - **Leaf-only claim gate runs first**: Phase 3a classifies each candidate before any claim; a container with open child work (or a childless Epic/Story/Spike) is skipped/safe-blocked, never claimed (the `leaf-only-lifecycle` rule's claim-time arm). The safe-block comment is idempotent — a re-entrant cycle does not re-post it.
245
+ - **Leaf-only claim gate runs first**: Phase 3a classifies each candidate before any claim; a container with open child work (or a childless Epic) is skipped/safe-blocked, never claimed (the `leaf-only-lifecycle` rule's claim-time arm). The safe-block comment is idempotent — a re-entrant cycle does not re-post it.
246
246
  - **Claim-first ordering**: `$CLAIMED` set BEFORE `lisa:jira-agent` invocation — no double-pickup.
247
247
  - **No writes outside the lifecycle**: this skill only transitions `$READY → $CLAIMED` and `$CLAIMED → $DONE`, then verifies terminal native resolution when `$DONE` is the true terminal state per `leaf-only-lifecycle`. Every other status change is owned by `lisa:jira-agent` (which suggests transitions but only auto-transitions on the verify-FAIL path).
248
248
  - **Terminal native closure**: for terminal `$DONE`, the resulting JIRA issue must be in a resolved / closed state (`statusCategory = Done` and resolution set when required). Intermediate env statuses stay unresolved / open.
@@ -276,7 +276,7 @@ If a ready-equivalent status does not exist in the JIRA project's workflow, this
276
276
 
277
277
  ## Rules
278
278
 
279
- - **Claim leaves only.** Per the `leaf-only-lifecycle` rule, never claim a container — a ticket with open child work, or a childless Epic/Story/Spike — even if it carries the build-ready status. Skip or safe-block it (Phase 3a); never silently implement a container.
279
+ - **Claim leaves only.** Per the `leaf-only-lifecycle` rule, never claim a container — a ticket with open child work, or a childless Epic — even if it carries the build-ready status. Skip or safe-block it (Phase 3a); never silently implement a container.
280
280
  - Never transition a ticket the cycle didn't claim. The `$CLAIMED` transition is the signature of cycle ownership.
281
281
  - Never bypass `lisa:jira-agent` to do build work directly. `lisa:jira-agent` owns the per-ticket lifecycle (read, verify, triage, route, sync, evidence). This skill is the dispatcher, not the builder.
282
282
  - Never auto-transition past `$DONE`. Downstream statuses are owned by QA / product / a future verification-intake skill — not this one.
@@ -162,9 +162,9 @@ If the spec doesn't set `authenticated_surface`, infer it: scan the description
162
162
 
163
163
  #### S10 — Repository section, single-repo scope
164
164
 
165
- When `issue_type ∈ {Bug, Task, Sub-task, Improvement}`, description must contain `h2. Repository` naming exactly one repo. Multiple repos OR cross-repo references in AC: FAIL with recommendation `"Split into per-repo work units under a shared parent Story (see lisa:task-decomposition step 1.5)"`.
165
+ When `issue_type ∈ {Bug, Task, Sub-task, Improvement}` — or a **build-ready childless Story/Spike** (a claimable leaf per `leaf-only-lifecycle`) — description must contain `h2. Repository` naming exactly one repo. Multiple repos OR cross-repo references in AC: FAIL with recommendation `"Split into per-repo work units under a shared parent Story (see lisa:task-decomposition step 1.5)"`.
166
166
 
167
- Story / Epic / Spike: skipped (may span repos — these are coordination containers, not work units).
167
+ An **Epic**, or a **Story/Spike that still holds child work** (or is not build-ready): skipped (may span repos — coordination containers, not claimable leaf work units).
168
168
 
169
169
  This gate is `product_relevant: false` because cross-repo work units are not a product question — they are a decomposition error. Callers (`lisa:notion-to-tracker`, `lisa:confluence-to-tracker`, `lisa:linear-to-tracker`, `lisa:github-to-tracker`) MUST pre-split cross-repo work into per-repo work units during the decomposition phase per `lisa:task-decomposition` step 1.5; an S10 failure here indicates the agent skipped that step and must auto-split + revalidate before writing, not surface a clarifying comment to product.
170
170
 
@@ -200,7 +200,7 @@ When `issue_type ∈ {Bug, Task, Sub-task, Improvement}` AND `runtime_behavior_c
200
200
 
201
201
  FAIL when the Validation Journey is present but declares zero `[EVIDENCE: name]` markers, or when any marker name is empty, duplicated, or not kebab-case. A behavior-changing work unit SHOULD declare both a success marker and an error/edge marker; a journey with only one marker passes but the remediation should recommend adding the error/edge case.
202
202
 
203
- This gate depends on S11. It is `N/A` for Epic / Story / Spike (coordination containers, not work units) and for leaf units with `runtime_behavior_change = false` (doc-only / config-only / type-only). If S11 fails because the Validation Journey is absent, S14 also FAILs (there is no manifest to bind) with remediation pointing back to `lisa:jira-add-journey`.
203
+ This gate depends on S11. It is `N/A` for containers — an **Epic**, or any item with open child work (coordination containers, not work units) and for leaf units with `runtime_behavior_change = false` (doc-only / config-only / type-only). If S11 fails because the Validation Journey is absent, S14 also FAILs (there is no manifest to bind) with remediation pointing back to `lisa:jira-add-journey`.
204
204
 
205
205
  #### S15 — Leaf-only build-ready
206
206
 
@@ -212,20 +212,19 @@ Enforces the build-side of the vendor-neutral `leaf-only-lifecycle` rule: **only
212
212
 
213
213
  Apply this decision and FAIL the two invariant-violating cases:
214
214
 
215
- 1. **Container with child work + build-ready** — `issue_type ∈ {Epic, Story, Spike}` OR child work is present (any type that has children), AND build-ready. FAIL. A parent organizes work; it is never claimed and implemented directly. Its lifecycle state rolls up from its children.
216
- 2. **Childless container-type + build-ready** — `issue_type {Epic, Story, Spike}` with **no** child work, AND build-ready. Still FAIL: these types are coordination containers by design, and an empty one is an incomplete decomposition, not an implementable unit (the childless-parent exception in `leaf-only-lifecycle` does **not** promote an Epic/Story/Spike to build-ready).
215
+ 1. **Container with child work + build-ready** — child work is present (any type that has open children), AND build-ready. FAIL. A parent organizes work; it is never claimed and implemented directly. Its lifecycle state rolls up from its children.
216
+ 2. **Childless Epic + build-ready** — `issue_type = Epic` with **no** child work, AND build-ready. Still FAIL: an Epic is a pure rollup container by design, and a childless one is an incomplete decomposition or a mis-applied role, not an implementable unit. (A childless Story or Spike is **not** failed here — the childless-parent exception in `leaf-only-lifecycle` promotes every childless non-Epic type to a build-ready leaf.)
217
217
 
218
- PASS (the childless-parent exception) when the ticket is build-ready and is a **leaf work unit**: `issue_type {Bug, Task, Sub-task, Improvement}` AND has **no** child work. A flat Task or Bug with no sub-tasks is a valid build-ready leaf and must not be stranded.
218
+ PASS (the childless-parent exception) when the ticket is build-ready and is a **leaf work unit**: it has **no** open child work and `issue_type Epic` (i.e. `Bug, Task, Sub-task, Improvement`, or a childless `Story` / `Spike`). A flat Task/Bug, or a childless Story/Spike with no sub-tasks, is a valid build-ready leaf and must not be stranded.
219
219
 
220
220
  | issue_type | has child work | build-ready | S15 |
221
221
  |---|---|---|---|
222
- | Bug / Task / Sub-task / Improvement | no | yes | **PASS** (leaf) |
223
- | Bug / Task / Sub-task / Improvement | yes | yes | **FAIL** (structurally a container) |
224
- | Epic / Story / Spike | yes | yes | **FAIL** (container with children) |
225
- | Epic / Story / Spike | no | yes | **FAIL** (childless container-type, exception does not apply) |
222
+ | Bug / Task / Sub-task / Improvement / Story / Spike | no | yes | **PASS** (leaf) |
223
+ | any type | yes | yes | **FAIL** (structurally a container) |
224
+ | Epic | no | yes | **FAIL** (childless Epic — pure rollup container, exception does not apply) |
226
225
  | any | any | no | **N/A** (not build-ready) |
227
226
 
228
- 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/Story/Spike, 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."`
227
+ 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."`
229
228
 
230
229
  `product_relevant: false` — a build-ready container is a lifecycle/decomposition error for the caller to repair, not a product question.
231
230
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: linear-build-intake
3
- description: "Symmetric counterpart to lisa:jira-build-intake on the Linear side. Scans a Linear team for Issues carrying the configured `ready` build label, claims the first eligible Issue by relabeling to the configured `claimed` label, runs the implementation/build flow via lisa:linear-agent, relabels to the configured `done` label on completion, then exits. Enforces the claim-time arm of the `leaf-only-lifecycle` rule: a parent/container with open child work (or a childless Epic/Story/Spike) that still carries a stale build-ready label is skipped or safe-blocked with a lifecycle-repair comment, never claimed. The `ready` label is the human-flipped signal that an Issue is truly ready for development — mirroring how Notion PRDs work Draft → Ready → (us) In Review → Blocked|Ticketed."
3
+ description: "Symmetric counterpart to lisa:jira-build-intake on the Linear side. Scans a Linear team for Issues carrying the configured `ready` build label, claims the first eligible Issue by relabeling to the configured `claimed` label, runs the implementation/build flow via lisa:linear-agent, relabels to the configured `done` label on completion, then exits. Enforces the claim-time arm of the `leaf-only-lifecycle` rule: a parent/container with open child work (or a childless Epic) that still carries a stale build-ready label is skipped or safe-blocked with a lifecycle-repair comment, never claimed. The `ready` label is the human-flipped signal that an Issue is truly ready for development — mirroring how Notion PRDs work Draft → Ready → (us) In Review → Blocked|Ticketed."
4
4
  allowed-tools: ["Skill", "Bash", "mcp__linear-server__list_teams", "mcp__linear-server__list_issues", "mcp__linear-server__get_issue", "mcp__linear-server__save_issue", "mcp__linear-server__save_comment", "mcp__linear-server__list_issue_labels", "mcp__linear-server__create_issue_label"]
5
5
  ---
6
6
 
@@ -167,17 +167,17 @@ Classify and act (first match wins). The type comes from the Issue's `type:` lab
167
167
  | Condition | Class | Action |
168
168
  |---|---|---|
169
169
  | `OPEN_CHILDREN > 0` (open child work, any type) | **Container** | **Skip / safe-block — do NOT claim** |
170
- | no open children AND type {Epic, Story, Spike} | **Childless container-type** | **Skip / safe-block — do NOT claim** |
171
- | no open children AND type {Bug, Task, Sub-task, Improvement} (or no `type:` label) | **Leaf work unit** | **Proceed to 3b claim** |
170
+ | no open children AND type = Epic (a Linear Project) | **Childless Epic/Project (pure rollup container)** | **Skip / safe-block — do NOT claim** |
171
+ | no open children AND type Epic (Bug, Task, Sub-task, Improvement, Story, Spike, or no `type:` label) | **Leaf work unit** | **Proceed to 3b claim** |
172
172
 
173
- The childless-parent exception is narrow: childlessness enables a claim **only** for types that are leaf work units to begin with. A childless Epic/Story/Spike is an incomplete decomposition, not an implementable unit it is never claimed.
173
+ The childless-parent exception promotes every childless type **except Epic** to a claimable leaf: a childless Story is a directly shippable increment and a childless Spike *is* the investigation unit, so neither is stranded. Only a childless **Epic** (a Linear Project) stays unclaimed — it is a pure rollup container by design, and a childless one is an incomplete decomposition or a mis-applied role, never an implementable unit.
174
174
 
175
175
  **Safe-block (default action for a flagged container).** Leave the build-ready label in place (don't silently strip it — that hides the lifecycle error), post a single lifecycle-repair comment, record the Issue under "Skipped (container)" in the summary, and end the cycle. Do NOT relabel to `$CLAIMED`. Keep the comment idempotent — skip posting if an identical `[claude-build-intake]` lifecycle-repair comment already exists on the Issue, so a re-entrant cycle doesn't spam it.
176
176
 
177
177
  Post via `mcp__linear-server__save_comment` with:
178
178
 
179
179
  ```text
180
- [claude-build-intake] Not claimed: this Issue carries the build-ready label ($READY) but is a container with open child work (or a childless Epic/Story/Spike), which violates the leaf-only-lifecycle rule. Build-ready (status:ready) is leaf-only per leaf-only-lifecycle — an agent claims and implements leaves, never a container. Repair: move $READY off this parent onto its leaf children (or, for a childless Epic/Story/Spike, 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.
180
+ [claude-build-intake] Not claimed: this Issue carries the build-ready label ($READY) but is a container with open child work (or a childless Epic), which violates the leaf-only-lifecycle rule. Build-ready (status:ready) is leaf-only per leaf-only-lifecycle — an agent claims and implements leaves, never a container. Repair: move $READY off this parent 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.
181
181
  ```
182
182
 
183
183
  This gate never blocks a legitimate flat Task/Bug: those have no open children and a leaf `type:`, so they fall straight through to the claim in 3b.
@@ -252,7 +252,7 @@ Total PRs opened: <n>
252
252
 
253
253
  ## Idempotency & safety
254
254
 
255
- - **Leaf-only claim gate runs first**: Phase 3a classifies each candidate before any claim; a container with open child work (or a childless Epic/Story/Spike) is skipped/safe-blocked, never claimed (the `leaf-only-lifecycle` rule's claim-time arm). The safe-block comment is idempotent — a re-entrant cycle does not re-post it.
255
+ - **Leaf-only claim gate runs first**: Phase 3a classifies each candidate before any claim; a container with open child work (or a childless Epic) is skipped/safe-blocked, never claimed (the `leaf-only-lifecycle` rule's claim-time arm). The safe-block comment is idempotent — a re-entrant cycle does not re-post it.
256
256
  - **Claim-first ordering**: `$CLAIMED` set BEFORE agent invocation — no double-pickup.
257
257
  - **No writes outside the lifecycle**: this skill only adds/removes `$READY`, `$CLAIMED`, `$DONE`, plus terminal-only native state completion required by `leaf-only-lifecycle`. Every other label change (and non-terminal native state change) is owned by the agent or `lisa:linear-evidence`.
258
258
  - **Terminal native closure**: after the `$DONE` label is applied, move the Linear Issue to a native completed state only when `$DONE` is the true terminal done value; intermediate env labels stay open / active.
@@ -273,7 +273,7 @@ If the team hasn't adopted these labels, the first run exits with an adoption hi
273
273
 
274
274
  ## Rules
275
275
 
276
- - **Claim leaves only.** Per the `leaf-only-lifecycle` rule, never claim a container — an Issue with open child work, or a childless Epic/Story/Spike — even if it carries the build-ready label. Skip or safe-block it (Phase 3a); never silently implement a container.
276
+ - **Claim leaves only.** Per the `leaf-only-lifecycle` rule, never claim a container — an Issue with open child work, or a childless Epic — even if it carries the build-ready label. Skip or safe-block it (Phase 3a); never silently implement a container.
277
277
  - Never relabel an Issue the cycle didn't claim. The `$CLAIMED` transition is the signature of cycle ownership.
278
278
  - Never bypass `lisa:linear-agent` to do build work directly. The agent owns the per-Issue lifecycle.
279
279
  - Never auto-transition past `$DONE`. Downstream labels are owned by QA / product / a future verification-intake skill.
@@ -165,9 +165,9 @@ If the spec doesn't set `authenticated_surface`, infer it: scan the description
165
165
 
166
166
  #### S10 — Repository section, single-repo scope
167
167
 
168
- When `issue_type ∈ {Bug, Task, Sub-task, Improvement}`, description must contain `## Repository` naming exactly one repo. Multiple repos OR cross-repo references in AC: FAIL with recommendation `"Split into per-repo work units under a shared parent Story (see lisa:task-decomposition step 1.5)"`.
168
+ When `issue_type ∈ {Bug, Task, Sub-task, Improvement}` — or a **build-ready childless Story/Spike** (a claimable leaf per `leaf-only-lifecycle`) — description must contain `## Repository` naming exactly one repo. Multiple repos OR cross-repo references in AC: FAIL with recommendation `"Split into per-repo work units under a shared parent Story (see lisa:task-decomposition step 1.5)"`.
169
169
 
170
- Story / Epic / Spike: skipped (may span repos — these are coordination containers, not work units).
170
+ An **Epic** (a Linear Project), or a **Story/Spike that still holds child work** (or is not build-ready): skipped (may span repos — coordination containers, not claimable leaf work units).
171
171
 
172
172
  This gate is `product_relevant: false` because cross-repo work units are not a product question — they are a decomposition error. Callers (`lisa:linear-to-tracker`, `lisa:notion-to-tracker`, etc.) MUST pre-split cross-repo work into per-repo work units during the decomposition phase per `lisa:task-decomposition` step 1.5; an S10 failure here indicates the agent skipped that step and must auto-split + revalidate before writing, not surface a clarifying comment to product.
173
173
 
@@ -201,7 +201,7 @@ When `issue_type ∈ {Bug, Task, Sub-task, Improvement}` AND `runtime_behavior_c
201
201
 
202
202
  FAIL when the Validation Journey is present but declares zero `[EVIDENCE: name]` markers, or when any marker name is empty, duplicated, or not kebab-case. A behavior-changing work unit SHOULD declare both a success marker and an error/edge marker; a journey with only one marker passes but the remediation should recommend adding the error/edge case.
203
203
 
204
- This gate depends on S11. It is `N/A` for Project / Story / Spike (coordination containers, not work units) and for leaf units with `runtime_behavior_change = false` (doc-only / config-only / type-only). If S11 fails because the Validation Journey is absent, S14 also FAILs (there is no manifest to bind) with remediation pointing back to `lisa:linear-add-journey`.
204
+ This gate depends on S11. It is `N/A` for containers — a **Project** (the Epic equivalent), or any item with open child work (coordination containers, not work units) and for leaf units with `runtime_behavior_change = false` (doc-only / config-only / type-only). If S11 fails because the Validation Journey is absent, S14 also FAILs (there is no manifest to bind) with remediation pointing back to `lisa:linear-add-journey`.
205
205
 
206
206
  #### S15 — Leaf-only build-ready
207
207
 
@@ -213,20 +213,19 @@ Enforces the build-side of the vendor-neutral `leaf-only-lifecycle` rule: **only
213
213
 
214
214
  Apply this decision and FAIL the two invariant-violating cases:
215
215
 
216
- 1. **Container with child work + build-ready** — `issue_type ∈ {Epic, Story, Spike}` OR child work is present (any type that has children), AND build-ready. FAIL. A parent organizes work; it is never claimed and implemented directly. Its lifecycle state rolls up from its children.
217
- 2. **Childless container-type + build-ready** — `issue_type {Epic, Story, Spike}` with **no** child work, AND build-ready. Still FAIL: these types are coordination containers by design, and an empty one is an incomplete decomposition, not an implementable unit (the childless-parent exception in `leaf-only-lifecycle` does **not** promote an Epic/Story/Spike to build-ready).
216
+ 1. **Container with child work + build-ready** — child work is present (any type that has open children), AND build-ready. FAIL. A parent organizes work; it is never claimed and implemented directly. Its lifecycle state rolls up from its children.
217
+ 2. **Childless Epic/Project + build-ready** — `issue_type = Epic` (a Linear Project) with **no** child work, AND build-ready. Still FAIL: an Epic/Project is a pure rollup container by design, and a childless one is an incomplete decomposition or a mis-applied role, not an implementable unit. (A childless Story or Spike is **not** failed here — the childless-parent exception in `leaf-only-lifecycle` promotes every childless non-Epic type to a build-ready leaf.)
218
218
 
219
- PASS (the childless-parent exception) when the item is build-ready and is a **leaf work unit**: `issue_type {Bug, Task, Sub-task, Improvement}` AND has **no** child work. A flat Task or Bug with no sub-issues is a valid build-ready leaf and must not be stranded.
219
+ PASS (the childless-parent exception) when the item is build-ready and is a **leaf work unit**: it has **no** open child work and `issue_type Epic` (i.e. `Bug, Task, Sub-task, Improvement`, or a childless `Story` / `Spike`). A flat Task/Bug, or a childless Story/Spike with no sub-issues, is a valid build-ready leaf and must not be stranded.
220
220
 
221
221
  | issue_type | has child work | build-ready | S15 |
222
222
  |---|---|---|---|
223
- | Bug / Task / Sub-task / Improvement | no | yes | **PASS** (leaf) |
224
- | Bug / Task / Sub-task / Improvement | yes | yes | **FAIL** (structurally a container) |
225
- | Epic / Story / Spike | yes | yes | **FAIL** (container with children) |
226
- | Epic / Story / Spike | no | yes | **FAIL** (childless container-type, exception does not apply) |
223
+ | Bug / Task / Sub-task / Improvement / Story / Spike | no | yes | **PASS** (leaf) |
224
+ | any type | yes | yes | **FAIL** (structurally a container) |
225
+ | Epic (Project) | no | yes | **FAIL** (childless Epic/Project — pure rollup container, exception does not apply) |
227
226
  | any | any | no | **N/A** (not build-ready) |
228
227
 
229
- 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/Story/Spike, 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."`
228
+ 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."`
230
229
 
231
230
  `product_relevant: false` — a build-ready container is a lifecycle/decomposition error for the caller to repair, not a product question.
232
231
 
@@ -0,0 +1,83 @@
1
+ ---
2
+ name: parity-code-review
3
+ description: "Lisa-native code review of the current git diff. Walks every changed hunk and reports correctness bugs, security issues, and obvious defects as severity-ranked findings with file:line references. Vendor-neutral — the cross-agent equivalent of the upstream code-review command, runnable on Codex, agy, Copilot, Cursor, and Claude."
4
+ allowed-tools: ["Read", "Bash", "Grep", "Glob"]
5
+ ---
6
+
7
+ # Parity Code Review
8
+
9
+ Review the code that is *about to ship* — the current uncommitted/branch diff — for defects a reviewer would block on. This is a focused **defect hunt**: correctness, security, and obvious mistakes. It is not a style audit and not a refactor pass (use `parity-code-simplifier` for quality-only cleanup).
10
+
11
+ > **Not drift-trackable.** This skill intentionally carries **no `synced-from` pin**. The upstream `code-review@claude-plugins-official` plugin publishes **no semver** (its cache version resolves to `unknown`), so a pin would be unparseable and meaningless to `scripts/plugin-parity-drift.mjs`. Drift is tracked **manually** — re-review the upstream command by hand when the curated plugin set is refreshed. This is a Lisa-native reimplementation, **not** a port of upstream code.
12
+
13
+ ## Step 1: Establish the diff
14
+
15
+ Determine exactly what changed. Prefer the broadest accurate view of the work-in-progress:
16
+
17
+ ```bash
18
+ # Branch changes vs the merge base (preferred for a PR-style review)
19
+ git merge-base HEAD origin/main 2>/dev/null && \
20
+ git diff "$(git merge-base HEAD origin/main)"...HEAD
21
+
22
+ # Plus anything still uncommitted in the working tree
23
+ git diff HEAD
24
+ git status --short
25
+ ```
26
+
27
+ If there is no diff at all, say so plainly and stop — do not invent findings. If the diff is enormous, review in full but prioritize the files with the most logic changes; never silently skip files (note any you deprioritized).
28
+
29
+ ## Step 2: Read for real context
30
+
31
+ Do **not** review hunks in isolation. For each changed file, open enough surrounding code to understand:
32
+
33
+ - What the function/module is supposed to do and who calls it.
34
+ - Invariants and preconditions the change might violate.
35
+ - Error/edge paths touched by the change.
36
+
37
+ Use `Read`, `Grep`, and `Glob` to follow call sites and trace data flow. A finding you can't ground in the actual code is a guess — drop it.
38
+
39
+ ## Step 3: Hunt for defects
40
+
41
+ For every changed hunk, evaluate against these lenses:
42
+
43
+ 1. **Correctness** — Off-by-one errors, inverted conditions, wrong operator, missing `await`, unhandled `null`/`undefined`, incorrect default, broken control flow, type coercion bugs, mutation of shared state, race conditions.
44
+ 2. **Security** — Unsanitized input at trust boundaries; injection (SQL/shell/template); secrets, tokens, or keys committed or logged; missing authn/authz on new endpoints; unsafe deserialization; path traversal; overly broad permissions; SSRF.
45
+ 3. **Edge cases & failure modes** — Empty collections, zero, negative numbers, very large input, concurrent calls, partial failures, timeouts, retries that aren't idempotent.
46
+ 4. **Obvious defects** — Dead code paths, unreachable branches, swallowed errors, resource leaks (unclosed handles/connections), `TODO`/`FIXME` left in shipping code, debug logging left on, broken or missing tests for the new behavior.
47
+ 5. **Contract & API** — Breaking changes to public signatures, changed return shapes, altered error semantics callers depend on.
48
+
49
+ ## Step 4: Output — severity-ranked findings
50
+
51
+ Group findings by severity. Within each group, list the most impactful first. Every finding **must** carry a `file:line` reference.
52
+
53
+ ### Critical (must fix before merge)
54
+ Bugs that break correctness, leak/expose data, or introduce a security hole.
55
+
56
+ ### Warning (should fix)
57
+ Likely to cause problems later, or a real defect with limited blast radius.
58
+
59
+ ### Suggestion (nice to have)
60
+ Minor correctness nits or defensive improvements.
61
+
62
+ ### Finding format
63
+
64
+ For each finding:
65
+
66
+ - **What** — precise description of the defect.
67
+ - **Where** — `path/to/file.ts:42` (and a span if it covers multiple lines).
68
+ - **Why** — the concrete failure it causes, with an example input or sequence that triggers it.
69
+ - **Fix** — a specific, actionable suggestion (or a short code sketch).
70
+
71
+ Example:
72
+
73
+ > **Critical — Unhandled null dereference**
74
+ > **Where:** `src/auth/session.ts:88`
75
+ > **Why:** `findUser()` returns `null` when the id is unknown, but line 88 reads `user.roles` directly. An unknown session id (expired token replay) throws and 500s instead of returning 401.
76
+ > **Fix:** Guard `if (!user) return unauthorized()` before reading `user.roles`.
77
+
78
+ ## Rules
79
+
80
+ - **Ground every finding in the diff.** No speculative findings, no generic best-practice lectures unrelated to the change.
81
+ - **Be honest about coverage.** If you deprioritized files or couldn't fully trace a path, say so.
82
+ - **If the diff is clean, say so clearly** — "No blocking issues found across N changed files" — do not manufacture problems.
83
+ - This is review-only: report findings, do **not** edit files. Apply fixes via the normal implementation flow or `parity-code-simplifier` (quality) after triage.
@@ -0,0 +1,76 @@
1
+ ---
2
+ name: parity-code-simplifier
3
+ description: "Lisa-native, behavior-preserving simplification of recently-changed code. Removes duplication and dead code, reuses existing utilities, and improves readability without altering behavior — quality only, never a bug hunt. Vendor-neutral cross-agent equivalent of the upstream code-simplifier agent, runnable on Codex, agy, Copilot, Cursor, and Claude."
4
+ allowed-tools: ["Read", "Bash", "Grep", "Glob", "Edit", "Write"]
5
+ synced-from: code-simplifier@claude-plugins-official@1.0.0
6
+ ---
7
+
8
+ # Parity Code Simplifier
9
+
10
+ Make the **recently-changed** code simpler and easier to maintain **without changing what it does**. This is a quality pass: deduplication, reuse, readability, and dead-code removal. It is explicitly **not** a bug hunt — if you spot a likely defect, note it for a reviewer (or `parity-code-review`) and leave the behavior intact.
11
+
12
+ > **Drift tracking.** Pinned to `code-simplifier@claude-plugins-official@1.0.0`. `scripts/plugin-parity-drift.mjs` compares this pin against the upstream version in the plugin cache and flags staleness. This is a Lisa-native reimplementation written from scratch — **do not port or copy upstream plugin code.**
13
+
14
+ ## Scope: recently-changed code only
15
+
16
+ Default to the current diff, not the whole repository. Establish scope first:
17
+
18
+ ```bash
19
+ git merge-base HEAD origin/main 2>/dev/null && \
20
+ git diff --stat "$(git merge-base HEAD origin/main)"...HEAD
21
+ git diff HEAD --stat
22
+ git status --short
23
+ ```
24
+
25
+ Simplify the files that changed and the immediate code they touch. Do not embark on a repo-wide refactor unless explicitly asked.
26
+
27
+ ## The prime directive: preserve behavior
28
+
29
+ Every edit must be behavior-preserving. Before changing anything, understand the current contract — inputs, outputs, side effects, error paths, public signatures. After changing it, the observable behavior must be identical. When in doubt, **don't** — leave a note instead of risking a semantic change.
30
+
31
+ ## What to simplify
32
+
33
+ 1. **Duplication (DRY)** — Collapse copy-pasted blocks into a single function or shared helper. Prefer delegating to an existing canonical implementation over re-deriving logic (see the repo's DRY rule: a function that reproduces a sequence should call the shared generator, not reimplement it).
34
+ 2. **Reuse over reinvention** — Search for existing utilities (`Grep`/`Glob`) before introducing new code. If the project already has a helper for what the change hand-rolls, use it.
35
+ 3. **Readability** — Clearer names; flatten needless nesting with early returns/guard clauses; replace clever one-liners with obvious code; split overly long functions along natural seams.
36
+ 4. **Dead code** — Remove unreachable branches, unused variables/imports/exports, and commented-out blocks introduced or exposed by the change.
37
+ 5. **Idiomatic constructs** — Prefer immutable transformations (`map`/`filter`/`reduce`) over mutable accumulation where it's clearer; remove redundant intermediate state.
38
+
39
+ ## Respect project conventions
40
+
41
+ This repo enforces specific patterns — honor them so your simplification doesn't trip the linter or hooks:
42
+
43
+ - **Immutability / functional style** — avoid `let` and in-place mutation; prefer `const` and pure transformations.
44
+ - **Statement order** — do not place expression-statement helper calls before `const` definitions; inline validation as `if` guard clauses (exempt from `enforce-statement-order`).
45
+ - **eslint-disable directives** must include a `-- description`.
46
+ - **Barrel-export constraint** — if you delete a file referenced by an `index.ts`, update the barrel in the same change so lint/typecheck stays green.
47
+ - **Never edit generated plugin artifacts** (`plugins/lisa`, `plugins/lisa-*`); the source of truth is `plugins/src/`.
48
+
49
+ ## Workflow
50
+
51
+ 1. Read each changed file and enough of its callers to know the contract.
52
+ 2. Identify simplification opportunities; rank by value-to-risk. Skip anything that risks behavior.
53
+ 3. Apply edits with `Edit`/`Write`, one coherent change at a time.
54
+ 4. **Verify behavior is unchanged** — run the project's checks:
55
+ ```bash
56
+ bun run test
57
+ bun run typecheck 2>/dev/null || true
58
+ bun run lint 2>/dev/null || true
59
+ ```
60
+ If any check fails, fix or revert the offending edit before continuing. Never leave the tree worse than you found it.
61
+
62
+ ## Output
63
+
64
+ Summarize what you changed and why, grouped by file with `file:line` anchors:
65
+
66
+ - **Simplified** — the edits applied (dedup / reuse / readability / dead-code), each with a one-line rationale.
67
+ - **Left alone** — opportunities you deliberately skipped because they risked behavior, with the reason.
68
+ - **Flagged for review** — any suspected bugs noticed in passing (not fixed here — quality pass only).
69
+ - **Verification** — which checks you ran and that they pass.
70
+
71
+ ## Rules
72
+
73
+ - **Behavior-preserving only.** No bug fixes, no feature changes, no API changes disguised as cleanup.
74
+ - **Quality only** — if the only "simplification" would change behavior, don't make it.
75
+ - **Tests must stay green.** A simplification that breaks a test is a behavior change — revert it.
76
+ - If there is nothing worth simplifying, say so clearly rather than churning the code.