@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.
- package/package.json +1 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/skills/atlassian-access/SKILL.md +32 -2
- package/plugins/lisa/skills/atlassian-access/scripts/markdown-to-adf.mjs +214 -0
- package/plugins/lisa/skills/confluence-to-tracker/SKILL.md +5 -3
- package/plugins/lisa/skills/github-build-intake/SKILL.md +14 -6
- package/plugins/lisa/skills/github-to-tracker/SKILL.md +5 -3
- package/plugins/lisa/skills/jira-build-intake/SKILL.md +16 -8
- package/plugins/lisa/skills/jira-read-ticket/SKILL.md +1 -1
- package/plugins/lisa/skills/jira-validate-ticket/SKILL.md +5 -5
- package/plugins/lisa/skills/jira-write-ticket/SKILL.md +9 -7
- package/plugins/lisa/skills/linear-build-intake/SKILL.md +16 -8
- package/plugins/lisa/skills/linear-to-tracker/SKILL.md +5 -3
- package/plugins/lisa/skills/notion-to-tracker/SKILL.md +5 -3
- package/plugins/lisa/skills/repair-intake/SKILL.md +147 -31
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/atlassian-access/SKILL.md +32 -2
- package/plugins/lisa-agy/skills/atlassian-access/scripts/markdown-to-adf.mjs +214 -0
- package/plugins/lisa-agy/skills/confluence-to-tracker/SKILL.md +5 -3
- package/plugins/lisa-agy/skills/github-build-intake/SKILL.md +14 -6
- package/plugins/lisa-agy/skills/github-to-tracker/SKILL.md +5 -3
- package/plugins/lisa-agy/skills/jira-build-intake/SKILL.md +16 -8
- package/plugins/lisa-agy/skills/jira-read-ticket/SKILL.md +1 -1
- package/plugins/lisa-agy/skills/jira-validate-ticket/SKILL.md +5 -5
- package/plugins/lisa-agy/skills/jira-write-ticket/SKILL.md +9 -7
- package/plugins/lisa-agy/skills/linear-build-intake/SKILL.md +16 -8
- package/plugins/lisa-agy/skills/linear-to-tracker/SKILL.md +5 -3
- package/plugins/lisa-agy/skills/notion-to-tracker/SKILL.md +5 -3
- package/plugins/lisa-agy/skills/repair-intake/SKILL.md +147 -31
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/skills/atlassian-access/SKILL.md +32 -2
- package/plugins/lisa-copilot/skills/atlassian-access/scripts/markdown-to-adf.mjs +214 -0
- package/plugins/lisa-copilot/skills/confluence-to-tracker/SKILL.md +5 -3
- package/plugins/lisa-copilot/skills/github-build-intake/SKILL.md +14 -6
- package/plugins/lisa-copilot/skills/github-to-tracker/SKILL.md +5 -3
- package/plugins/lisa-copilot/skills/jira-build-intake/SKILL.md +16 -8
- package/plugins/lisa-copilot/skills/jira-read-ticket/SKILL.md +1 -1
- package/plugins/lisa-copilot/skills/jira-validate-ticket/SKILL.md +5 -5
- package/plugins/lisa-copilot/skills/jira-write-ticket/SKILL.md +9 -7
- package/plugins/lisa-copilot/skills/linear-build-intake/SKILL.md +16 -8
- package/plugins/lisa-copilot/skills/linear-to-tracker/SKILL.md +5 -3
- package/plugins/lisa-copilot/skills/notion-to-tracker/SKILL.md +5 -3
- package/plugins/lisa-copilot/skills/repair-intake/SKILL.md +147 -31
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/skills/atlassian-access/SKILL.md +32 -2
- package/plugins/lisa-cursor/skills/atlassian-access/scripts/markdown-to-adf.mjs +214 -0
- package/plugins/lisa-cursor/skills/confluence-to-tracker/SKILL.md +5 -3
- package/plugins/lisa-cursor/skills/github-build-intake/SKILL.md +14 -6
- package/plugins/lisa-cursor/skills/github-to-tracker/SKILL.md +5 -3
- package/plugins/lisa-cursor/skills/jira-build-intake/SKILL.md +16 -8
- package/plugins/lisa-cursor/skills/jira-read-ticket/SKILL.md +1 -1
- package/plugins/lisa-cursor/skills/jira-validate-ticket/SKILL.md +5 -5
- package/plugins/lisa-cursor/skills/jira-write-ticket/SKILL.md +9 -7
- package/plugins/lisa-cursor/skills/linear-build-intake/SKILL.md +16 -8
- package/plugins/lisa-cursor/skills/linear-to-tracker/SKILL.md +5 -3
- package/plugins/lisa-cursor/skills/notion-to-tracker/SKILL.md +5 -3
- package/plugins/lisa-cursor/skills/repair-intake/SKILL.md +147 -31
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/src/base/skills/atlassian-access/SKILL.md +32 -2
- package/plugins/src/base/skills/atlassian-access/scripts/markdown-to-adf.mjs +214 -0
- package/plugins/src/base/skills/confluence-to-tracker/SKILL.md +5 -3
- package/plugins/src/base/skills/github-build-intake/SKILL.md +14 -6
- package/plugins/src/base/skills/github-to-tracker/SKILL.md +5 -3
- package/plugins/src/base/skills/jira-build-intake/SKILL.md +16 -8
- package/plugins/src/base/skills/jira-read-ticket/SKILL.md +1 -1
- package/plugins/src/base/skills/jira-validate-ticket/SKILL.md +5 -5
- package/plugins/src/base/skills/jira-write-ticket/SKILL.md +9 -7
- package/plugins/src/base/skills/linear-build-intake/SKILL.md +16 -8
- package/plugins/src/base/skills/linear-to-tracker/SKILL.md +5 -3
- package/plugins/src/base/skills/notion-to-tracker/SKILL.md +5 -3
- 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
|
|
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
|
|
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.
|
|
215
|
-
|
|
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
|
-
|
|
220
|
-
|
|
221
|
-
|
|
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
|
|
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]
|
|
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
|
|
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
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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 land — a 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
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
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
|
-
|
|
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
|
-
|
|
295
|
-
|
|
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
|
-
**
|
|
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
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
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)
|
|
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
|
|
552
|
-
|
|
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.
|
|
@@ -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
|
|