@codyswann/lisa 2.129.5 → 2.129.7

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 (111) 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/skills/atlassian-access/SKILL.md +32 -2
  5. package/plugins/lisa/skills/atlassian-access/scripts/markdown-to-adf.mjs +214 -0
  6. package/plugins/lisa/skills/confluence-to-tracker/SKILL.md +5 -3
  7. package/plugins/lisa/skills/github-build-intake/SKILL.md +14 -6
  8. package/plugins/lisa/skills/github-to-tracker/SKILL.md +5 -3
  9. package/plugins/lisa/skills/jira-build-intake/SKILL.md +16 -8
  10. package/plugins/lisa/skills/jira-read-ticket/SKILL.md +1 -1
  11. package/plugins/lisa/skills/jira-validate-ticket/SKILL.md +5 -5
  12. package/plugins/lisa/skills/jira-write-ticket/SKILL.md +9 -7
  13. package/plugins/lisa/skills/linear-build-intake/SKILL.md +16 -8
  14. package/plugins/lisa/skills/linear-to-tracker/SKILL.md +5 -3
  15. package/plugins/lisa/skills/notion-to-tracker/SKILL.md +5 -3
  16. package/plugins/lisa/skills/repair-intake/SKILL.md +147 -31
  17. package/plugins/lisa-agy/plugin.json +1 -1
  18. package/plugins/lisa-agy/skills/atlassian-access/SKILL.md +32 -2
  19. package/plugins/lisa-agy/skills/atlassian-access/scripts/markdown-to-adf.mjs +214 -0
  20. package/plugins/lisa-agy/skills/confluence-to-tracker/SKILL.md +5 -3
  21. package/plugins/lisa-agy/skills/github-build-intake/SKILL.md +14 -6
  22. package/plugins/lisa-agy/skills/github-to-tracker/SKILL.md +5 -3
  23. package/plugins/lisa-agy/skills/jira-build-intake/SKILL.md +16 -8
  24. package/plugins/lisa-agy/skills/jira-read-ticket/SKILL.md +1 -1
  25. package/plugins/lisa-agy/skills/jira-validate-ticket/SKILL.md +5 -5
  26. package/plugins/lisa-agy/skills/jira-write-ticket/SKILL.md +9 -7
  27. package/plugins/lisa-agy/skills/linear-build-intake/SKILL.md +16 -8
  28. package/plugins/lisa-agy/skills/linear-to-tracker/SKILL.md +5 -3
  29. package/plugins/lisa-agy/skills/notion-to-tracker/SKILL.md +5 -3
  30. package/plugins/lisa-agy/skills/repair-intake/SKILL.md +147 -31
  31. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  32. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  33. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  34. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  35. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  37. package/plugins/lisa-copilot/skills/atlassian-access/SKILL.md +32 -2
  38. package/plugins/lisa-copilot/skills/atlassian-access/scripts/markdown-to-adf.mjs +214 -0
  39. package/plugins/lisa-copilot/skills/confluence-to-tracker/SKILL.md +5 -3
  40. package/plugins/lisa-copilot/skills/github-build-intake/SKILL.md +14 -6
  41. package/plugins/lisa-copilot/skills/github-to-tracker/SKILL.md +5 -3
  42. package/plugins/lisa-copilot/skills/jira-build-intake/SKILL.md +16 -8
  43. package/plugins/lisa-copilot/skills/jira-read-ticket/SKILL.md +1 -1
  44. package/plugins/lisa-copilot/skills/jira-validate-ticket/SKILL.md +5 -5
  45. package/plugins/lisa-copilot/skills/jira-write-ticket/SKILL.md +9 -7
  46. package/plugins/lisa-copilot/skills/linear-build-intake/SKILL.md +16 -8
  47. package/plugins/lisa-copilot/skills/linear-to-tracker/SKILL.md +5 -3
  48. package/plugins/lisa-copilot/skills/notion-to-tracker/SKILL.md +5 -3
  49. package/plugins/lisa-copilot/skills/repair-intake/SKILL.md +147 -31
  50. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-cursor/skills/atlassian-access/SKILL.md +32 -2
  52. package/plugins/lisa-cursor/skills/atlassian-access/scripts/markdown-to-adf.mjs +214 -0
  53. package/plugins/lisa-cursor/skills/confluence-to-tracker/SKILL.md +5 -3
  54. package/plugins/lisa-cursor/skills/github-build-intake/SKILL.md +14 -6
  55. package/plugins/lisa-cursor/skills/github-to-tracker/SKILL.md +5 -3
  56. package/plugins/lisa-cursor/skills/jira-build-intake/SKILL.md +16 -8
  57. package/plugins/lisa-cursor/skills/jira-read-ticket/SKILL.md +1 -1
  58. package/plugins/lisa-cursor/skills/jira-validate-ticket/SKILL.md +5 -5
  59. package/plugins/lisa-cursor/skills/jira-write-ticket/SKILL.md +9 -7
  60. package/plugins/lisa-cursor/skills/linear-build-intake/SKILL.md +16 -8
  61. package/plugins/lisa-cursor/skills/linear-to-tracker/SKILL.md +5 -3
  62. package/plugins/lisa-cursor/skills/notion-to-tracker/SKILL.md +5 -3
  63. package/plugins/lisa-cursor/skills/repair-intake/SKILL.md +147 -31
  64. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  65. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  66. package/plugins/lisa-expo-agy/plugin.json +1 -1
  67. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  68. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  69. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  70. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  71. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  72. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  73. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  74. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  75. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  76. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  77. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  78. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  79. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  80. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  81. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  82. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  83. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  84. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  85. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  86. package/plugins/lisa-rails-agy/plugin.json +1 -1
  87. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  88. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  89. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  90. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  91. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  92. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  93. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  94. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  95. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  96. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  97. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  98. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  99. package/plugins/src/base/skills/atlassian-access/SKILL.md +32 -2
  100. package/plugins/src/base/skills/atlassian-access/scripts/markdown-to-adf.mjs +214 -0
  101. package/plugins/src/base/skills/confluence-to-tracker/SKILL.md +5 -3
  102. package/plugins/src/base/skills/github-build-intake/SKILL.md +14 -6
  103. package/plugins/src/base/skills/github-to-tracker/SKILL.md +5 -3
  104. package/plugins/src/base/skills/jira-build-intake/SKILL.md +16 -8
  105. package/plugins/src/base/skills/jira-read-ticket/SKILL.md +1 -1
  106. package/plugins/src/base/skills/jira-validate-ticket/SKILL.md +5 -5
  107. package/plugins/src/base/skills/jira-write-ticket/SKILL.md +9 -7
  108. package/plugins/src/base/skills/linear-build-intake/SKILL.md +16 -8
  109. package/plugins/src/base/skills/linear-to-tracker/SKILL.md +5 -3
  110. package/plugins/src/base/skills/notion-to-tracker/SKILL.md +5 -3
  111. package/plugins/src/base/skills/repair-intake/SKILL.md +147 -31
@@ -203,22 +203,28 @@ Invoke `lisa:linear-agent` (per-Issue lifecycle agent) with the Issue identifier
203
203
  - Posting evidence via `lisa:linear-evidence`
204
204
 
205
205
  Wait for the agent to return. Capture its outcome:
206
- - **Success** — PR is ready (open or merged); evidence posted; ready for next status.
206
+ - **Success** — the build flow completed and a PR exists; evidence posted. The PR may already be **merged** or still **open** (auto-merge enabled, awaiting checks/merge). "Success" means the build work is sound — it does **not** assert the change reached an environment. The env transition in 3d gates on the PR actually being merged; an open PR does not advance the Issue to a `done` env status.
207
207
  - **Blocked by linear-verify pre-flight gate** — `lisa:linear-agent` itself relabels to `status:blocked` and assigns to creator. Let it stand. Record and move on.
208
208
  - **Blocked by ticket-triage ambiguities** — agent posts findings and stops. The Issue stays at `$CLAIMED`. Surface to human; do not auto-transition. Record under "Errors".
209
209
  - **Errored** — exception, missing config, etc. Leave at `$CLAIMED`. Record with exception summary.
210
210
 
211
- #### 3d. Relabel to $DONE (only on Success)
211
+ #### 3d. Relabel to $DONE (only after the PR is merged)
212
+
213
+ A `done` env state (`status:on-dev`, `status:on-stg`, or the terminal value) asserts that the code has actually reached that environment. Never set it for a PR that is merely open: auto-merge can be blocked indefinitely (a required rebase / `BEHIND` branch, failing checks, an unaddressed review), and the change may never land. Relabeling an Issue `status:on-stg` on an open PR makes it *claim* a deploy that never happened. Transition only after confirming the PR merged.
212
214
 
213
215
  If `lisa:linear-agent` returned Success:
214
- 1. Resolve `$DONE` for this issue's PR base branch using the Workflow resolution algorithm above. If env can't be resolved and `done` is env-keyed, record an Error and skip this transition — never guess.
215
- 2. Determine whether `$DONE` is the true terminal done value per the `leaf-only-lifecycle` rule's Terminal native closure section:
216
+ 1. **Confirm the PR merged.** Read the live state of the Issue's PR `gh pr view <pr> --json state,mergedAt,mergeStateStatus,url`:
217
+ - **Merged** (`state == MERGED`) → proceed to resolve and apply `$DONE` below. Where the env deploy is observable (a deploy workflow run / deployment status keyed to the merged-into branch via `deploy.branches`), confirm it did not fail before relabeling; a still-running deploy is treated like an open PR (leave at `$CLAIMED`), a failed deploy is recorded as an Error.
218
+ - **Open / not yet merged** → do **not** transition. The build is sound but the change has reached no environment yet. Record the Issue under **"PR open — awaiting merge"** in the summary (with the PR URL and its `mergeStateStatus`), leave it at `$CLAIMED`, and stop. A later `lisa:repair-intake` cycle drives the open PR to merge — re-syncing a `BEHIND` branch so the already-enabled auto-merge can land, or surfacing a real blocker — and, once merged, applies this same env transition. Do **not** comment "Build complete" or change the native state.
219
+ - **Closed without merging** → record an Error (the PR was abandoned unmerged); leave the Issue at `$CLAIMED`.
220
+ 2. Resolve `$DONE` for this issue's PR base branch using the Workflow resolution algorithm above. If env can't be resolved and `done` is env-keyed, record an Error and skip this transition — never guess.
221
+ 3. Determine whether `$DONE` is the true terminal done value per the `leaf-only-lifecycle` rule's Terminal native closure section:
216
222
  - If `linear.labels.build.done` is a string, that string is terminal.
217
223
  - If `linear.labels.build.done` is an object, only the production/final environment value is terminal (default: `status:done`). Intermediate env values such as `status:on-dev` and `status:on-stg` are not terminal and must keep the native Issue open.
218
224
  - If the project uses a different final environment name, resolve it from the configured deployment topology; if ambiguous, record an Error and do not change the native state.
219
- 3. Update labels via `mcp__linear-server__save_issue`: remove `$CLAIMED` (or `$REVIEW` if `lisa:linear-evidence` already moved it forward), add `$DONE`.
220
- 4. If `$DONE` is terminal, move the native Linear Issue state to the configured Done / Completed state. Resolve that state from project configuration if present; otherwise inspect the team workflow for a terminal state with `state.type = "completed"` and a name such as `Done` or `Completed`. If no terminal state can be resolved, record an Error and leave the labels as the source of truth — do not invent a state name.
221
- 5. Post a `[claude-build-intake]` comment: `"Build complete. PR <URL>. Transitioned to $DONE."` Include whether native closure was applied, already satisfied, skipped for an intermediate env, or unavailable for setup reasons.
225
+ 4. Update labels via `mcp__linear-server__save_issue`: remove `$CLAIMED` (or `$REVIEW` if `lisa:linear-evidence` already moved it forward), add `$DONE`.
226
+ 5. If `$DONE` is terminal, move the native Linear Issue state to the configured Done / Completed state. Resolve that state from project configuration if present; otherwise inspect the team workflow for a terminal state with `state.type = "completed"` and a name such as `Done` or `Completed`. If no terminal state can be resolved, record an Error and leave the labels as the source of truth — do not invent a state name.
227
+ 6. Post a `[claude-build-intake]` comment: `"Build complete. PR <URL> merged. Transitioned to $DONE."` Include whether native closure was applied, already satisfied, skipped for an intermediate env, or unavailable for setup reasons.
222
228
 
223
229
  For any non-Success outcome, do NOT transition. The Issue sits where the agent left it — humans take it from there.
224
230
 
@@ -236,8 +242,10 @@ Cycle started: <ISO timestamp>
236
242
  Cycle completed: <ISO timestamp>
237
243
 
238
244
  Issues processed: <n>
239
- - $DONE (build complete, PR ready): <n>
245
+ - $DONE (build complete, PR merged): <n>
240
246
  - <ID> <title> → PR <URL>
247
+ - PR open — awaiting merge (left at $CLAIMED for repair-intake): <n>
248
+ - <ID> <title> → PR <URL> (mergeStateStatus: <state>)
241
249
  - Skipped (container — leaf-only-lifecycle): <n>
242
250
  - <ID> <title> — build-ready on a parent with open child work; lifecycle-repair comment posted
243
251
  - status:blocked (pre-flight verify failed): <n>
@@ -233,10 +233,12 @@ Capture each returned story key — Phase 5 needs it as the parent for sub-tasks
233
233
 
234
234
  **Auto-split cross-repo work before delegation.** For each candidate sub-task, apply `lisa:task-decomposition` step 1.5: if the work touches more than one repo, split it into one sub-task per repo under the same parent Story (e.g., `[backend-api] Add field` + `[mobile-app] Display field`), and encode the producer-before-consumer ordering via dependencies. Work units that may span repos (Epic, Story, Spike) stay as planned; work units that must be single-repo (Bug, Task, Sub-task, Improvement) are split now. Splitting is this skill's responsibility — the validator's S10 gate is `product_relevant: false` because cross-repo failures are decomposition errors caught here, not product questions sent back to the PRD.
235
235
 
236
+ **S10 hard gate repair loop.** Dry-run validation is not advisory. Before any Phase 5 write, every planned leaf spec MUST pass `lisa:tracker-validate --spec-only` for S10 Single-repo scope. If any Bug / Task / Sub-task / Improvement fails S10 (missing `Repository`, more than one repo, or cross-repo AC), stop the write path, auto-split or restamp the spec using `lisa:task-decomposition` step 1.5, add the repo bracket and `## Repository` / `h2. Repository` section, then re-run `lisa:tracker-validate --spec-only`. If S10 still fails after repair, abort the ticket write and record an internal Error in the dry-run report; do not create the ticket, do not bypass with direct vendor writes, and do not surface the `product_relevant: false` failure as a product clarification.
237
+
236
238
  Delegate sub-task creation to **parallel agents** (one per epic or batch of stories) for efficiency. **Every spawned agent must invoke `lisa:tracker-write` for each sub-task — no agent may call `createJiraIssue` directly.**
237
239
 
238
240
  Each sub-task MUST:
239
- 1. **Be scoped to exactly ONE repo** — indicated in brackets in the summary: `[repo-name]`
241
+ 1. **Be scoped to exactly ONE repo** — indicated in brackets in the summary: `[repo-name]` and in the description's `## Repository` / `h2. Repository` section
240
242
  2. **Include an Empirical Verification Plan** — real user-like verification, NOT unit tests, linting, or typechecking
241
243
 
242
244
  **Leaf-only build-ready (`leaf-only-lifecycle`)**: Sub-tasks are the **leaf work units** of the decomposition — they are the ONLY items in the hierarchy that receive the build-ready label. `lisa:tracker-write` applies `status:ready` here so downstream build intake (`lisa:tracker-build-intake`) claims the leaves and never the Epic or Stories. Apply `status:ready` to each Sub-task; never to its parent Story or Epic (Phases 3–4). `lisa:tracker-write` enforces the same invariant on the write side, so a Sub-task split into per-repo children (the cross-repo case above) carries build-ready on the children, not on any intermediate parent that gains child work.
@@ -308,7 +310,7 @@ For each sub-task, invoke `lisa:tracker-write` with:
308
310
  - parent: the parent story key
309
311
  - project_key: [PROJECT]
310
312
  - summary: prefixed with the repo in brackets, e.g. "[backend-api] Add audit log table"
311
- - description_body: a 3-section draft (Context / Technical Approach / Acceptance Criteria)
313
+ - description_body: a 3-section draft (Context / Technical Approach / Acceptance Criteria) plus `h2. Repository` naming exactly one repo
312
314
  - gherkin_acceptance_criteria: derived from the story's functional requirements
313
315
  - sign_in_account: [test user credentials from config — name + role + how to obtain]
314
316
  - target_environment: "dev"
@@ -317,7 +319,7 @@ For each sub-task, invoke `lisa:tracker-write` with:
317
319
  NOT unit tests, linting, or typechecking.
318
320
 
319
321
  Each sub-task must:
320
- 1. Be scoped to ONE repo only — repo named in brackets in the summary
322
+ 1. Be scoped to ONE repo only — repo named in brackets in the summary and in `h2. Repository`
321
323
  2. Include the Empirical Verification Plan in the description
322
324
  3. Be created via `lisa:tracker-write`, not via direct MCP calls
323
325
 
@@ -237,10 +237,12 @@ When classification is ambiguous, err on the side of inclusion — a developer c
237
237
 
238
238
  **Auto-split cross-repo work before delegation.** For each candidate sub-task, apply `lisa:task-decomposition` step 1.5: if the work touches more than one repo, split it into one sub-task per repo under the same parent Story (e.g., `[backend-api] Add field` + `[mobile-app] Display field`), and encode the producer-before-consumer ordering via dependencies. Work units that may span repos (Epic, Story, Spike) stay as planned; work units that must be single-repo (Bug, Task, Sub-task, Improvement) are split now. Splitting is this skill's responsibility — the validator's S10 gate is `product_relevant: false` because cross-repo failures are decomposition errors caught here, not product questions sent back to the PRD.
239
239
 
240
+ **S10 hard gate repair loop.** Dry-run validation is not advisory. Before any Phase 5 write, every planned leaf spec MUST pass `lisa:tracker-validate --spec-only` for S10 Single-repo scope. If any Bug / Task / Sub-task / Improvement fails S10 (missing `Repository`, more than one repo, or cross-repo AC), stop the write path, auto-split or restamp the spec using `lisa:task-decomposition` step 1.5, add the repo bracket and `## Repository` / `h2. Repository` section, then re-run `lisa:tracker-validate --spec-only`. If S10 still fails after repair, abort the ticket write and record an internal Error in the dry-run report; do not create the ticket, do not bypass with direct vendor writes, and do not surface the `product_relevant: false` failure as a product clarification.
241
+
240
242
  Delegate sub-task creation to **parallel agents** (one per epic or batch of stories) for efficiency. **Every spawned agent must invoke `lisa:tracker-write` for each sub-task — no agent may call `createJiraIssue` directly.** This is non-negotiable; see the Agent Prompt Template at the bottom of this skill for the exact instructions to pass.
241
243
 
242
244
  Each sub-task MUST:
243
- 1. **Be scoped to exactly ONE repo** — indicated in brackets in the summary: `[repo-name]`. `lisa:tracker-write` enforces single-repo scope on Sub-task; cross-repo sub-tasks will be rejected and must be split before delegation.
245
+ 1. **Be scoped to exactly ONE repo** — indicated in brackets in the summary: `[repo-name]` and in the description's `## Repository` / `h2. Repository` section. `lisa:tracker-write` enforces single-repo scope on Sub-task; cross-repo or unscoped sub-tasks will be rejected and must be split/restamped before delegation.
244
246
  2. **Include an Empirical Verification Plan** — real user-like verification, NOT unit tests, linting, or typechecking
245
247
 
246
248
  **Leaf-only build-ready (`leaf-only-lifecycle`)**: Sub-tasks are the **leaf work units** of the decomposition — they are the ONLY items in the hierarchy that receive the build-ready label. `lisa:tracker-write` applies `status:ready` here so downstream build intake (`lisa:tracker-build-intake`) claims the leaves and never the Epic or Stories. Apply `status:ready` to each Sub-task; never to its parent Story or Epic (Phases 3–4). `lisa:tracker-write` enforces the same invariant on the write side, so a Sub-task split into per-repo children (the cross-repo case above) carries build-ready on the children, not on any intermediate parent that gains child work.
@@ -328,7 +330,7 @@ For each sub-task, invoke `lisa:tracker-write` with:
328
330
  - parent: the parent story key
329
331
  - project_key: [PROJECT]
330
332
  - summary: prefixed with the repo in brackets, e.g. "[backend-api] Add audit log table"
331
- - description_body: a 3-section draft (Context / Technical Approach / Acceptance Criteria)
333
+ - description_body: a 3-section draft (Context / Technical Approach / Acceptance Criteria) plus `h2. Repository` naming exactly one repo
332
334
  - gherkin_acceptance_criteria: derived from the story's functional requirements
333
335
  - sign_in_account: [test user credentials from config — name + role + how to obtain]
334
336
  - target_environment: "dev"
@@ -337,7 +339,7 @@ For each sub-task, invoke `lisa:tracker-write` with:
337
339
  NOT unit tests, linting, or typechecking.
338
340
 
339
341
  Each sub-task must:
340
- 1. Be scoped to ONE repo only — repo named in brackets in the summary
342
+ 1. Be scoped to ONE repo only — repo named in brackets in the summary and in `h2. Repository`
341
343
  2. Include the Empirical Verification Plan in the description
342
344
  3. Be created via `lisa:tracker-write`, not via direct MCP calls
343
345
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: repair-intake
3
- description: "Vendor-agnostic repair scanner — the recovery counterpart to lisa:intake. Where intake claims `ready` work, repair-intake finds work that got stuck or was left half-closed: items left in `blocked`, stalled in an in-progress role (build `claimed`, PRD `in_review`), terminal-labeled items that are still natively open, and rollup/container items whose children are all terminal but whose parent is not closed out. Scans the same queues lisa:intake serves (Notion / Confluence / Linear / GitHub PRD databases; JIRA / GitHub / Linear build queues), enumerates candidates up to `max_candidates`, and repairs every materially actionable one in that bounded set: resumes stalled in-progress work IN PLACE (build → the vendor agent + the scanner's post-agent transition; PRD → the source `*-to-tracker` dry-run validate→route pipeline) — but for a stalled build it first diagnoses the PR/deploy state and, if the PR cannot merge (conflict, rebase-required, failing checks, unaddressed CodeRabbit/changes-requested) or a deploy failed, files a build-ready leaf fix ticket and moves the item to `blocked` (blocked by that ticket) rather than re-dispatching, re-validates blocked PRDs when new clarifying answers exist, re-dispatches blocked build items whose `is blocked by` dependencies have since closed, performs terminal native closure for terminal-labeled items, reconciles parent rollups to their derived state per leaf-only-lifecycle — including the intermediate-env case (e.g. all children at `On Stg` → parent `On Stg`) and a container wrongly stuck in `ready` — and closes out rollups whose associated child work is fully terminal. Idempotent, loop-protected via a [lisa-repair-intake] marker + state fingerprint + backoff. Never mutates product-owned states (`draft`, `verified`) and never touches `ready` leaves (a container wrongly carrying `ready` is the one exception — it is rolled up from its children, since `ready` on a parent is an invariant violation, not intake's claim signal). Designed as a /schedule cron target running alongside lisa:intake."
3
+ description: "Vendor-agnostic repair scanner — the recovery counterpart to lisa:intake. Where intake claims `ready` work, repair-intake finds work that got stuck or was left half-closed: items left in `blocked`, stalled in an in-progress role (build `claimed`, PRD `in_review`), terminal-labeled items that are still natively open, and rollup/container items whose children are all terminal but whose parent is not closed out. Scans the same queues lisa:intake serves (Notion / Confluence / Linear / GitHub PRD databases; JIRA / GitHub / Linear build queues), enumerates candidates up to `max_candidates`, and repairs every materially actionable one in that bounded set: resumes stalled in-progress work IN PLACE (build → the vendor agent + the scanner's post-agent transition; PRD → the source `*-to-tracker` dry-run validate→route pipeline) — but for a stalled build it first diagnoses the PR/deploy state: a PR that already merged is recovered by applying the env transition build-intake never got to (no re-dispatch); a PR that is merely behind its base is re-synced in place via `gh pr update-branch` so the already-enabled auto-merge can land (a clean rebase needs no human); and only a PR that cannot merge for a non-mechanical reason (true conflict, failing checks, unaddressed CodeRabbit/changes-requested) or a failed deploy gets a build-ready leaf fix ticket with the item moved to `blocked` (blocked by that ticket) rather than re-dispatching, re-validates blocked PRDs when new clarifying answers exist, re-dispatches blocked build items whose `is blocked by` dependencies have since closed OR whose validation/quality-gate self-block now re-validates PASS (re-running `lisa:tracker-validate` against current content — the build mirror of PRD re-validation), performs terminal native closure for terminal-labeled items, reconciles parent rollups to their derived state per leaf-only-lifecycle — including the intermediate-env case (e.g. all children at `On Stg` → parent `On Stg`) and a container wrongly stuck in `ready` — and closes out rollups whose associated child work is fully terminal. Idempotent, loop-protected via a [lisa-repair-intake] marker + state fingerprint + backoff. Never mutates product-owned states (`draft`, `verified`) and never touches `ready` leaves (a container wrongly carrying `ready` is the one exception — it is rolled up from its children, since `ready` on a parent is an invariant violation, not intake's claim signal). Designed as a /schedule cron target running alongside lisa:intake."
4
4
  allowed-tools: ["Skill", "Bash", "Read", "Write", "Edit", "mcp__linear-server__list_teams", "mcp__linear-server__list_projects", "mcp__linear-server__get_project", "mcp__linear-server__save_project", "mcp__linear-server__list_project_labels", "mcp__linear-server__list_issues", "mcp__linear-server__get_issue", "mcp__linear-server__save_issue", "mcp__linear-server__list_comments", "mcp__linear-server__save_comment", "mcp__linear-server__list_issue_labels", "mcp__linear-server__create_issue_label"]
5
5
  ---
6
6
 
@@ -15,13 +15,24 @@ close-out** roles and moves work *unstuck* or *fully closed*:
15
15
  happening, so it sits ignored forever. (The vendor PRD intakes explicitly leave an errored PRD
16
16
  in `in_review` "for the human to investigate from there" — that orphan is exactly what this
17
17
  skill recovers.) For a stalled **build**, repair-intake first diagnoses *why* it stalled by
18
- inspecting its PRs and deploys: if the PR cannot merge (conflict / rebase-required / failing
19
- checks / unaddressed CodeRabbit or `CHANGES_REQUESTED` review) or a deploy failed, it files a
20
- build-ready leaf fix ticket and moves the item to `blocked` (blocked by that ticket) instead of
21
- blindly re-dispatching the agent which would just churn against an unmergeable PR.
22
- - **Recoverable blocked** an item in `blocked` whose blocker may now be gone: an
23
- `is blocked by` dependency has since closed, clarifying questions have been answered, or
24
- research/waiting resolves the ambiguity that stopped it.
18
+ inspecting its PRs and deploys. A PR that **already merged** is recovered by applying the env
19
+ transition build-intake never got to (its merge gate left the item `claimed` when the merge landed
20
+ after its agent returned) no re-dispatch. A PR that is merely **behind its base** (`BEHIND`, no
21
+ conflict) is **re-synced in place** with `gh pr update-branch` so the already-enabled auto-merge can
22
+ finally landa clean rebase needs no human, and leaving it stranded is the exact gap that lets an
23
+ auto-merge PR sit unmerged forever. Only a PR that cannot merge for a non-mechanical reason (true
24
+ conflict / failing checks / unaddressed CodeRabbit or `CHANGES_REQUESTED` review) or a failed deploy
25
+ gets a build-ready leaf fix ticket with the item moved to `blocked` (blocked by that ticket) instead
26
+ of blindly re-dispatching the agent — which would just churn against an unmergeable PR.
27
+ - **Recoverable blocked** — an item in `blocked` whose blocker may now be gone. The blocker is
28
+ one of three classes, and repair re-checks **all** of them, not just dependencies: (a) an
29
+ `is blocked by` **dependency** has since closed; (b) a **validation / quality-gate self-block** —
30
+ the item was bounced to `blocked` by its own pre-flight `verify`/`validate` gate (missing
31
+ Validation Journey, Sign-in Required, Acceptance Criteria, etc.) with **no dependency at all**,
32
+ and a human has since edited the item to add what the gate demanded; or (c) **clarifying
33
+ questions answered** / an **ambiguity** research can now settle. A self-block (b) is the common
34
+ one missed by dependency-only re-checks: nothing else is blocking it, so re-running the same gate
35
+ against its current content is the only way to know it is now passable.
25
36
  - **Terminal-open drift** — an item already carrying its true terminal lifecycle role (for
26
37
  example GitHub `status:done`) but still open/active in the provider's native state.
27
38
  - **Rollup drift** — a parent/container item (Epic, Story, PRD, Linear Project, or equivalent)
@@ -251,14 +262,24 @@ deploys (see "Stuck-cause diagnosis" below). A stalled build usually stalled for
251
262
  reason, and re-dispatching the agent at it will not fix a PR that cannot merge or a deploy that
252
263
  failed — it just churns.
253
264
 
254
- 0. **Diagnose PR & deploy blockers.** If a real external blocker is found (PR cannot merge — merge
255
- conflict / rebase-required / failing checks / `CHANGES_REQUESTED` / unaddressed CodeRabbit; or a
256
- failed deploy), **do not dispatch the agent**. Instead file a build-ready leaf fix ticket for the
257
- blocker, move this item `claimed blocked` with an `is blocked by` link to that ticket, and
258
- record it. The existing "Build `blocked` unblock if cleared" path resumes this item on a later
259
- cycle once the fix ticket is terminal — a self-healing loop. Skip the resume steps below.
260
-
261
- If no external blocker is found, the work simply died mid-flight run the **same per-item sequence
265
+ 0. **Diagnose PR & deploy state.** Run "Stuck-cause diagnosis" below. It resolves, in order:
266
+ - **PR already merged** the build effectively completed; the vendor build-intake's merge gate
267
+ left the item `claimed` because the merge landed after its agent returned. Do **not** re-dispatch
268
+ or file anything apply the scanner's post-agent env-resolved `claimed done` transition
269
+ directly (step 2 below, env-resolved), and record it. This is the recovery arm for build-intake
270
+ leaving merged-but-unadvanced items in `claimed`.
271
+ - **PR only behind its base (a needed rebase)** → mechanically resolvable, **not** a human blocker.
272
+ Re-sync the branch in place so the already-enabled auto-merge can land (see diagnosis step 3).
273
+ Keep the item `claimed`; a later cycle confirms the merge and transitions. Do **not** file a fix
274
+ ticket for a clean rebase.
275
+ - **A real external blocker** (PR cannot merge for a non-mechanical reason — true merge conflict /
276
+ failing checks / `CHANGES_REQUESTED` / unaddressed CodeRabbit; or a failed deploy) → **do not
277
+ dispatch the agent**. File a build-ready leaf fix ticket for the blocker, move this item
278
+ `claimed → blocked` with an `is blocked by` link to that ticket, and record it. The existing
279
+ "Build `blocked` → unblock if cleared" path resumes this item on a later cycle once the fix
280
+ ticket is terminal — a self-healing loop. Skip the resume steps below.
281
+
282
+ If the PR is healthy in-flight and no blocker is found, the work simply died mid-flight — run the **same per-item sequence
262
283
  the vendor build-intake runs**, skipping the claim transition (the item is already `claimed`):
263
284
 
264
285
  1. Dispatch the item to the vendor agent — `lisa:jira-agent` / `lisa:github-agent` /
@@ -287,12 +308,38 @@ external state that resuming the agent cannot fix."
287
308
  links and `gh pr list --search <issue-ref>`; JIRA: dev-status / remote links; Linear: attachments
288
309
  and git-branch links) and the deploy(s) for the resulting merge (the env-keyed `deploy.branches`
289
310
  mapping from `config-resolution`). Read each PR with the vendor's native state, e.g. GitHub
290
- `gh pr view <n> --json mergeable,mergeStateStatus,reviewDecision,statusCheckRollup,comments,reviews`.
311
+ `gh pr view <n> --json state,mergedAt,mergeable,mergeStateStatus,reviewDecision,statusCheckRollup,comments,reviews`.
312
+
313
+ **2. PR already merged → recover, don't re-dispatch.** If `state == MERGED`, the build is effectively
314
+ complete and the only thing missing is the env transition the build-intake never applied (its merge
315
+ gate left the item `claimed` because the merge landed after its agent returned). Do **not** re-dispatch
316
+ or file anything: apply the scanner's post-agent env-resolved `claimed → done` transition (the
317
+ resume-sequence step 2, env-resolved from the merged PR's base branch) and record it as a repair
318
+ write. Where the env deploy is observable, confirm it did not fail first; a failed post-merge deploy
319
+ falls through to the blocker path (step 4).
320
+
321
+ **3. PR only behind its base → re-sync in place (mechanical, not a blocker).** If the PR is clean but
322
+ behind its base — `mergeStateStatus == BEHIND` while `mergeable != CONFLICTING` and no required check
323
+ is failing — it does **not** need a human. This is exactly the case that strands a PR forever: GitHub
324
+ auto-merge will not advance a `BEHIND` branch on its own, so a PR opened with `--auto` sits unmerged
325
+ until something rebases it. Re-sync it in place and let the existing auto-merge land it:
326
+
327
+ ```bash
328
+ gh pr update-branch <n> # rebase/merge the base into the PR head; reruns required checks
329
+ ```
291
330
 
292
- **2. Classify as a blocker.** Treat any of these as a real external blocker:
331
+ Record this as a repair write (`resynced`), keep the item `claimed`, and move on — a later cycle sees
332
+ the now-`CLEAN` (or merged) PR and either lets auto-merge finish or applies the merged-PR recovery in
333
+ step 2. Only if `gh pr update-branch` itself reports a conflict it cannot apply does the PR become a
334
+ true conflict (step 4). Honor the backoff window so repeated cycles don't re-issue `update-branch` on
335
+ an unchanged head (Loop prevention). For JIRA/Linear items the PR is still the GitHub PR backing the
336
+ branch — operate on it the same way.
293
337
 
294
- - **Merge conflict / rebase required** `mergeable = CONFLICTING`, or `mergeStateStatus` in
295
- `DIRTY` / `BEHIND`.
338
+ **4. Classify as a blocker.** Treat any of these as a real external blocker:
339
+
340
+ - **True merge conflict** — `mergeable = CONFLICTING` or `mergeStateStatus = DIRTY` (overlapping
341
+ changes a plain rebase cannot resolve), or `gh pr update-branch` (step 3) reported a conflict. A
342
+ merely `BEHIND` branch is **not** here — it was re-synced in step 3.
296
343
  - **Failing required checks** — `statusCheckRollup` has a `FAILURE`/`ERROR`/`TIMED_OUT` conclusion,
297
344
  or `mergeStateStatus = UNSTABLE`/`BLOCKED` due to checks.
298
345
  - **Change requests outstanding** — `reviewDecision = CHANGES_REQUESTED`, or unresolved CodeRabbit
@@ -306,7 +353,7 @@ A check that is still **queued/in progress**, or a `CLEAN`/`HAS_HOOKS` mergeable
306
353
  outstanding change request, is **not** a blocker — that is normal in-flight state. (Such a PR with
307
354
  recent check/commit activity would already have been caught as `active` by the staleness gate.)
308
355
 
309
- **3. On a blocker found → file a leaf fix ticket + block the item.**
356
+ **5. On a blocker found → file a leaf fix ticket + block the item.**
310
357
 
311
358
  1. **File one build-ready leaf fix ticket** per distinct blocker via `lisa:tracker-write` (the
312
359
  vendor-neutral leaf writer + validation gate; never a vendor `*-write-*` skill directly),
@@ -332,14 +379,31 @@ window and state fingerprint (Loop prevention) so re-runs over the same unchange
332
379
 
333
380
  ### Build `blocked` → re-evaluate, unblock if cleared
334
381
 
335
- 1. Read the block reason and dependencies (see Dependency clearing).
336
- 2. If every parsed blocker is **cleared** move `blocked claimed`, then run the same
337
- agent-dispatch + post-agent `claimed done` sequence as the stalled-`claimed` path above
338
- (one-cycle recovery). If the agent re-blocks, move back to `blocked` a valid outcome.
339
- 3. If the block was an **ambiguity** research can settle and no dependency remains → run the
382
+ 1. Read the block reason and classify the blocker (see Blocker classification & clearing). An item
383
+ may be held by a **dependency**, by a **validation / quality-gate self-block**, by an
384
+ **ambiguity**, or by more than one at once. Re-check **every** class present do not stop at
385
+ "no `is blocked by` links, therefore nothing to do." A self-block has zero dependencies by
386
+ definition, yet is fully re-checkable.
387
+ 2. **Dependency cleared** — if every parsed `is blocked by` dependency is **cleared** → move
388
+ `blocked → claimed`, then run the same agent-dispatch + post-agent `claimed → done` sequence as
389
+ the stalled-`claimed` path above (one-cycle recovery). If the agent re-blocks, move back to
390
+ `blocked` — a valid outcome.
391
+ 3. **Validation / quality-gate self-block re-check** — if the block reason is a pre-flight
392
+ `verify`/`validate` gate failure (its `[lisa-*]` block note carries a gate marker + a "Missing
393
+ requirements" list and there is **no** open `is blocked by` dependency), re-run the **same gate**
394
+ against the item's **current** content via `lisa:tracker-validate` (read-only; the vendor-neutral
395
+ gate `lisa:<tracker>-build-intake` and `lisa:<tracker>-write-*` already use). This is the build
396
+ mirror of the PRD `blocked → re-validate` path below.
397
+ - **PASS now** (the human added what was missing) → move `blocked → claimed` and resume exactly
398
+ as in (2): agent-dispatch + post-agent `claimed → done`.
399
+ - **Still FAIL** → stay `blocked`, but refresh the note with the **current** (usually smaller)
400
+ missing-requirement set so the human sees what remains. Because the fingerprint includes the
401
+ gate verdict + missing-requirement set (Loop prevention), a partial human fix changes the
402
+ fingerprint and re-checks next cycle, while a truly-unchanged gate result stays in backoff.
403
+ 4. If the block was an **ambiguity** research can settle and no dependency remains → run the
340
404
  research needed (`lisa:codebase-research` / `lisa:product-walkthrough`); if resolved, proceed
341
405
  as in (2).
342
- 4. Else → still blocked. Refresh the note with the current reason (Loop prevention) and leave it
406
+ 5. Else → still blocked. Refresh the note with the current reason (Loop prevention) and leave it
343
407
  `blocked`.
344
408
 
345
409
  ### Build terminal-open → native close / complete / resolve
@@ -460,7 +524,13 @@ work is fully terminal:
460
524
  5. If generated work is missing, ambiguous, or partially incomplete, leave the PRD open and report
461
525
  the incomplete child set. Never close a PRD on partial completion.
462
526
 
463
- ## Dependency clearing (conservative, vendor-specific extraction)
527
+ ## Blocker classification & clearing (conservative, vendor-specific extraction)
528
+
529
+ A `blocked` build item is held by one or more of three blocker classes. Identify which are present
530
+ from the item's block note(s) and links, then clear-check **each present class** — an item with no
531
+ dependency is not automatically un-actionable; it may be a self-block that now passes.
532
+
533
+ ### Class A — dependency blockers
464
534
 
465
535
  `lisa:tracker-read` is a thin dispatcher that returns each vendor's bundle **verbatim** — there
466
536
  is no normalized `is blocked by` field. Read the bundle, then extract blockers per vendor:
@@ -485,6 +555,38 @@ Only re-dispatch when **every** parsed blocker is cleared. When in doubt, stay b
485
555
  false-negative (left blocked) is cheap; a false-positive (re-dispatched into a real blocker)
486
556
  wastes a build cycle.
487
557
 
558
+ ### Class B — validation / quality-gate self-block
559
+
560
+ A self-block has **no** `is blocked by` dependency: the build-intake/agent flow claimed the item,
561
+ its pre-flight `verify`/`validate` gate failed (missing Validation Journey, Sign-in Required,
562
+ Target Backend Environment, Repository, Out of Scope, Evidence manifest, weak Acceptance Criteria,
563
+ etc.), and the item was bounced to `blocked` carrying that gate's `[lisa-*]` note + "Missing
564
+ requirements" list. Detect it by: (1) the block note bears a known gate marker (e.g.
565
+ `Pre-flight verify gate: BLOCKED`, `jira-verify` / `*-validate-*`), **and** (2) there is no open
566
+ `is blocked by` dependency. (If both a dependency and a self-block are present, clear the
567
+ dependency via Class A first; the self-block re-check still gates the eventual re-dispatch.)
568
+
569
+ Clear-check by **re-running the same gate against current content** — `lisa:tracker-validate`
570
+ (read-only; never writes), which dispatches to `lisa:<tracker>-validate-*` exactly as the write
571
+ path and build-intake do, so the bar cannot drift:
572
+
573
+ - **PASS** → cleared. Proceed to re-dispatch (decision tree step 2).
574
+ - **FAIL** → still self-blocked. Refresh the note with the current missing set (Loop prevention).
575
+
576
+ Conservative, same as Class A: a still-failing gate is a real blocker — never re-dispatch a build
577
+ whose own gate has not yet passed. This is intentionally symmetric with the PRD `blocked →
578
+ re-validate` path: PRDs re-run their dry-run `validate→route` when source content changes; builds
579
+ re-run `tracker-validate` when item content changes. The asymmetry where build `blocked` checked
580
+ only dependencies — leaving verify-gate self-blocks stranded forever after a human filled in the
581
+ missing sections — is the gap this class closes.
582
+
583
+ ### Class C — ambiguity / clarifying answers
584
+
585
+ A block that research or a human answer can settle (no dependency, no failing gate). Re-check by
586
+ running the needed research (`lisa:codebase-research` / `lisa:product-walkthrough`) or detecting a
587
+ human comment/edit newer than the last `[lisa-repair-intake]` note. Resolved → proceed to
588
+ re-dispatch; else stay blocked.
589
+
488
590
  ## Loop prevention
489
591
 
490
592
  A `blocked` item with a permanently unresolved problem must not be "repaired" and re-noted every
@@ -492,7 +594,10 @@ cron tick.
492
594
 
493
595
  - Every note this skill writes is prefixed `[lisa-repair-intake]` and carries a compact **state
494
596
  fingerprint**: the lifecycle role, the set of blocker refs + their observed states, the
495
- validation verdict (PASS/FAIL), terminal/open state, rollup child tally, and a timestamp.
597
+ validation verdict (PASS/FAIL) **plus the current missing-requirement set for a Class-B
598
+ self-block** (so a human filling in one of several missing sections changes the fingerprint and
599
+ triggers a re-check next cycle, rather than being suppressed as a no-op), terminal/open state,
600
+ rollup child tally, and a timestamp.
496
601
  - Before writing a note or re-attempting a `blocked` item, compute the current fingerprint. If
497
602
  an identical fingerprint was already posted within the **backoff window**, skip the item
498
603
  silently (record as `still_blocked` / `active`, no write).
@@ -548,8 +653,10 @@ It MUST NOT:
548
653
  containers, that need their derived state applied (status-only reconciliation, no native
549
654
  close),
550
655
  4. `blocked` items whose dependencies are now **cleared** (safe, high-value, one-cycle wins),
551
- 5. `blocked` items with **new clarifying answers**,
552
- 6. **stalled** in-progress items, oldest activity first.
656
+ 5. `blocked` items whose **validation / quality-gate self-block now re-validates PASS** —
657
+ a human filled in the missing sections (Class B; equally safe and high-value),
658
+ 6. `blocked` items with **new clarifying answers**,
659
+ 7. **stalled** in-progress items, oldest activity first.
553
660
  4. **Walk the ordered list**, evaluating each candidate (terminal close-out, rollup child tally,
554
661
  staleness, dependency, answer checks), and repair **every** candidate that is actionable inside
555
662
  the `max_candidates` cap. Continue after successful writes and after per-item errors.
@@ -568,6 +675,11 @@ often consists of cheap close-out reconciliation that should drain in one cron p
568
675
  Report outcomes in these buckets:
569
676
 
570
677
  - `resumed` — stalled in-progress work re-dispatched in place.
678
+ - `resynced` — a stalled build whose PR was merely behind its base, re-synced via
679
+ `gh pr update-branch` so the already-enabled auto-merge can land; the item stays `claimed` for a
680
+ later cycle to confirm the merge and transition.
681
+ - `recovered` — a stalled build whose PR had already merged, advanced by applying the env-resolved
682
+ `claimed → done` transition build-intake never got to (no re-dispatch).
571
683
  - `unblocked` — blocker cleared (or answers resolved); re-dispatched or transitioned to
572
684
  `ticketed`.
573
685
  - `closed_out` — terminal-labeled items whose native open/active state was closed, completed,
@@ -606,6 +718,10 @@ stuck work accumulates), or interleaved on a longer cadence.
606
718
  child work is terminal.
607
719
  - Apply build `done` ONLY via the env-resolution rules, and trigger native closure only at the
608
720
  true terminal `done` value (`leaf-only-lifecycle`).
721
+ - A `blocked` build item's blocker may be a dependency, a validation/quality-gate self-block (no
722
+ dependency — re-check by re-running `lisa:tracker-validate` against current content), or an
723
+ ambiguity. Re-check every class present; do not treat "no `is blocked by` links" as "nothing to
724
+ do."
609
725
  - Never re-dispatch a `blocked` build item unless every parsed blocker is cleared (conservative
610
726
  dependency clearing).
611
727
  - Repair every materially actionable candidate inside the `max_candidates` cap; default cap is 100.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.129.5",
3
+ "version": "2.129.7",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -217,6 +217,36 @@ fi
217
217
 
218
218
  If validation fails, never silently proceed — abort and instruct the user to fix env.
219
219
 
220
+ ### Step 2.5 — JIRA description normalization
221
+
222
+ For `write-ticket` create/edit operations, normalize any Lisa-authored JIRA description before dispatching to a substrate. JIRA Cloud stores descriptions as Atlassian Document Format (ADF). `acli` does not convert Markdown or JIRA wiki markup to ADF; if plain text is passed to `--description` / `--description-file`, JIRA stores one literal paragraph containing strings like `## Repository` or `h2. Repository`. That breaks `jira-validate-ticket` heading checks and renders poorly for humans.
223
+
224
+ Use the shared converter at `scripts/markdown-to-adf.mjs` from this skill for every write path that carries a string description:
225
+
226
+ ```bash
227
+ normalize_jira_description_payload() {
228
+ local payload_file="$1"
229
+ local converter="$(dirname "$0")/scripts/markdown-to-adf.mjs"
230
+
231
+ jq -e '.fields.description | type == "string"' "$payload_file" >/dev/null 2>&1 || return 0
232
+
233
+ local markdown_file adf_file
234
+ markdown_file=$(mktemp)
235
+ adf_file=$(mktemp)
236
+ jq -r '.fields.description' "$payload_file" > "$markdown_file"
237
+ node "$converter" < "$markdown_file" > "$adf_file"
238
+ jq --slurpfile adf "$adf_file" '.fields.description = $adf[0]' "$payload_file" > "$payload_file.tmp"
239
+ mv "$payload_file.tmp" "$payload_file"
240
+ }
241
+ ```
242
+
243
+ Rules:
244
+
245
+ - Convert Markdown headings (`#` / `##` / `###`) and JIRA wiki headings (`h1.` / `h2.` / `h3.`) to ADF `heading` nodes.
246
+ - Convert fenced code blocks, bullet lists, numbered lists, paragraphs, inline code, and bold text to their ADF equivalents.
247
+ - Run this for acli, curl, and MCP writes unless the caller already supplied an ADF object (`description.type == "doc"`). Do not double-convert existing ADF.
248
+ - For acli, pass the normalized JSON through `--from-json`; do not use `--description` or `--description-file` with raw Markdown/wiki text.
249
+
220
250
  ### Step 3 — Operation dispatch
221
251
 
222
252
  Substrate column meanings:
@@ -232,7 +262,7 @@ Substrate column meanings:
232
262
  | Operation | acli adapter | MCP adapter | curl adapter |
233
263
  |---|---|---|---|
234
264
  | **JIRA ops** | | | |
235
- | `read-ticket key:<K>` | `acli jira workitem view <K> --json` | `mcp__plugin_atlassian_atlassian__getJiraIssue` | `GET https://<SITE>/rest/api/3/issue/<K>` |
265
+ | `read-ticket key:<K>` | `acli jira workitem view <K> --fields '*all' --json` | `mcp__plugin_atlassian_atlassian__getJiraIssue` | `GET https://<SITE>/rest/api/3/issue/<K>?fields=*all` |
236
266
  | `write-ticket payload:<P>` (create) | `acli jira workitem create --from-json <P>` | `mcp__plugin_atlassian_atlassian__createJiraIssue` | `POST https://<SITE>/rest/api/3/issue` body=`<P>` |
237
267
  | `write-ticket payload:<P>` (edit) | `acli jira workitem edit <K> --from-json <P>` | `mcp__plugin_atlassian_atlassian__editJiraIssue` | `PUT https://<SITE>/rest/api/3/issue/<K>` body=`<P>` |
238
268
  | `transition key:<K> to:<S>` | `acli jira workitem transition --key <K> --status "<S>" --yes` | `mcp__plugin_atlassian_atlassian__transitionJiraIssue` | resolve transition id then `POST .../issue/<K>/transitions` |
@@ -259,7 +289,7 @@ Substrate column meanings:
259
289
 
260
290
  **Confluence v1 vs v2:** every Confluence curl path above uses **v1** (`/wiki/rest/api/...`). v1 is deprecated by Atlassian but as of writing remains functional for API-token Basic auth. The v2 API (`/api/v2/...`) requires *granular* OAuth scopes that aren't issued to Basic-auth API tokens consistently — so v1 is the safer path for now. When Atlassian fully retires v1, this table must move to v2 (the dispatch is the only thing that changes; the substrate-selection logic is unaffected).
261
291
 
262
- **acli flag note:** acli's `--output` flag does not exist; the correct flag is `--json`. List commands require `--paginate` or `--limit` (no implicit fetch-all). Several documented adapters are nominal — verify against `acli <subcmd> --help` before relying on them. When acli's adapter is broken or missing for a specific op, fall through to MCP (if identity-matched) then curl per the tier ordering.
292
+ **acli flag note:** acli's `--output` flag does not exist; the correct flag is `--json`. List commands require `--paginate` or `--limit` (no implicit fetch-all). `acli jira workitem view` defaults to a restricted field set (`key,issuetype,summary,status,assignee,description`), so `read-ticket` MUST pass `--fields '*all'` or an explicit equivalent that includes every downstream dependency: parent, subtasks, issue links, components, labels, priority, status, issue type, summary, description, fix versions, affected versions, attachments, comments, estimates, sprint/story-point fields, and project-required custom fields. Never rely on the default view fields; they hide parent/components/labels and corrupt leaf-only, relationship-search, build-ready, and required-custom-field gates. Several documented adapters are nominal — verify against `acli <subcmd> --help` before relying on them. When acli's adapter is broken or missing for a specific op, fall through to MCP (if identity-matched) then curl per the tier ordering.
263
293
 
264
294
  **JIRA terminal-resolution note:** when a caller marks a transition as terminal per `leaf-only-lifecycle`, the substrate must not treat a Done-named status as sufficient by name alone. After `transition key:<K> to:<S>`, re-read the issue and verify `statusCategory = Done`; if the workflow requires a resolution, verify `resolution` is set. If the transition screen requires a resolution value, pass the configured default resolution when available; otherwise return a setup error so the build-intake skill can report the workflow gap instead of silently leaving an unresolved ticket in a Done-looking status.
265
295