@codyswann/lisa 2.126.1 → 2.126.2
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/commands/repair-intake.md +1 -1
- package/plugins/lisa/rules/eager/leaf-only-lifecycle.md +5 -3
- package/plugins/lisa/rules/reference/leaf-only-lifecycle.md +13 -8
- package/plugins/lisa/skills/github-sync/SKILL.md +7 -6
- package/plugins/lisa/skills/jira-sync/SKILL.md +7 -6
- package/plugins/lisa/skills/linear-sync/SKILL.md +6 -5
- package/plugins/lisa/skills/repair-intake/SKILL.md +63 -29
- package/plugins/lisa/skills/tracker-sync/SKILL.md +5 -4
- package/plugins/lisa-agy/commands/repair-intake.md +1 -1
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/github-sync/SKILL.md +7 -6
- package/plugins/lisa-agy/skills/jira-sync/SKILL.md +7 -6
- package/plugins/lisa-agy/skills/linear-sync/SKILL.md +6 -5
- package/plugins/lisa-agy/skills/repair-intake/SKILL.md +63 -29
- package/plugins/lisa-agy/skills/tracker-sync/SKILL.md +5 -4
- 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/commands/repair-intake.md +1 -1
- package/plugins/lisa-copilot/rules/eager/leaf-only-lifecycle.md +5 -3
- package/plugins/lisa-copilot/rules/reference/leaf-only-lifecycle.md +13 -8
- package/plugins/lisa-copilot/skills/github-sync/SKILL.md +7 -6
- package/plugins/lisa-copilot/skills/jira-sync/SKILL.md +7 -6
- package/plugins/lisa-copilot/skills/linear-sync/SKILL.md +6 -5
- package/plugins/lisa-copilot/skills/repair-intake/SKILL.md +63 -29
- package/plugins/lisa-copilot/skills/tracker-sync/SKILL.md +5 -4
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/commands/repair-intake.md +1 -1
- package/plugins/lisa-cursor/rules/leaf-only-lifecycle-reference.mdc +13 -8
- package/plugins/lisa-cursor/rules/leaf-only-lifecycle.mdc +5 -3
- package/plugins/lisa-cursor/skills/github-sync/SKILL.md +7 -6
- package/plugins/lisa-cursor/skills/jira-sync/SKILL.md +7 -6
- package/plugins/lisa-cursor/skills/linear-sync/SKILL.md +6 -5
- package/plugins/lisa-cursor/skills/repair-intake/SKILL.md +63 -29
- package/plugins/lisa-cursor/skills/tracker-sync/SKILL.md +5 -4
- 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/commands/repair-intake.md +1 -1
- package/plugins/src/base/rules/eager/leaf-only-lifecycle.md +5 -3
- package/plugins/src/base/rules/reference/leaf-only-lifecycle.md +13 -8
- package/plugins/src/base/skills/github-sync/SKILL.md +7 -6
- package/plugins/src/base/skills/jira-sync/SKILL.md +7 -6
- package/plugins/src/base/skills/linear-sync/SKILL.md +6 -5
- package/plugins/src/base/skills/repair-intake/SKILL.md +63 -29
- package/plugins/src/base/skills/tracker-sync/SKILL.md +5 -4
|
@@ -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, and closes 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`
|
|
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."
|
|
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
|
|
|
@@ -24,9 +24,16 @@ close-out** roles and moves work *unstuck* or *fully closed*:
|
|
|
24
24
|
research/waiting resolves the ambiguity that stopped it.
|
|
25
25
|
- **Terminal-open drift** — an item already carrying its true terminal lifecycle role (for
|
|
26
26
|
example GitHub `status:done`) but still open/active in the provider's native state.
|
|
27
|
-
- **
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
- **Rollup drift** — a parent/container item (Epic, Story, PRD, Linear Project, or equivalent)
|
|
28
|
+
whose own lifecycle state does not match the roll-up of its children's states per
|
|
29
|
+
`leaf-only-lifecycle`. This covers the *completed* case (all children terminal → close the parent
|
|
30
|
+
out) **and** the *intermediate-env* case (all children shipped to an env like `On Stg`, but the
|
|
31
|
+
parent never advanced — including a parent left stranded in a status it should never carry).
|
|
32
|
+
- **Stale-`ready` container** — a parent/container (open child work, or a childless
|
|
33
|
+
Epic/Story/Spike) wrongly carrying the build-ready role. This is a leaf-only-invariant violation
|
|
34
|
+
the build-intake claim gate deliberately leaves for a human; repair-intake reconciles it by
|
|
35
|
+
rolling the parent up from its children (with an audit note), so a container never sits in `ready`
|
|
36
|
+
indefinitely.
|
|
30
37
|
|
|
31
38
|
This skill is the symmetric counterpart to `lisa:intake`. It reuses the same queue-detection,
|
|
32
39
|
the same agent-team orchestration, the same "don't ask, just run" confirmation policy, and the
|
|
@@ -131,9 +138,9 @@ claim-and-advance). The essentials, inlined here so this skill is self-complete:
|
|
|
131
138
|
| Confluence **parent page** URL/ID | PRD (Confluence, narrowed) | source=confluence | `in_review`, `blocked`, terminal/open PRDs, all-terminal generated-work rollups |
|
|
132
139
|
| Linear **workspace** URL, **team** URL/key, or literal `linear` | PRD (Linear) | source=linear | `in_review`, `blocked`, terminal/open PRDs, all-terminal generated-work rollups |
|
|
133
140
|
| GitHub **repo** URL / `org/repo` (PRD namespace) | PRD (GitHub) | source=github | `in_review`, `blocked`, terminal/open PRDs, all-terminal generated-work rollups |
|
|
134
|
-
| GitHub **repo** URL / `org/repo` with `tracker = github` (build namespace) | Build (GitHub) | tracker=github | `claimed`, `blocked`, terminal/open issues, all-terminal
|
|
141
|
+
| GitHub **repo** URL / `org/repo` with `tracker = github` (build namespace) | Build (GitHub) | tracker=github | `claimed`, `blocked`, terminal/open issues, parent rollups (intermediate-env + all-terminal), stale-`ready` containers |
|
|
135
142
|
| Literal `github` | GitHub; route by `intake_mode` (`prd` / `build` / `both`) | per lifecycle | per lifecycle above |
|
|
136
|
-
| JIRA project key or full JQL | Build (JIRA) | tracker=jira | `claimed`, `blocked`, terminal/closure verification, all-terminal
|
|
143
|
+
| JIRA project key or full JQL | Build (JIRA) | tracker=jira | `claimed`, `blocked`, terminal/closure verification, parent rollups (intermediate-env + all-terminal), stale-`ready` containers |
|
|
137
144
|
|
|
138
145
|
Disambiguation (same as `lisa:intake`): a `notion.so`/`notion.site` URL → Notion; an Atlassian
|
|
139
146
|
`/wiki/spaces/<KEY>` URL → Confluence (with `/pages/<id>` → parent-page narrowing); a
|
|
@@ -355,24 +362,37 @@ native-open / active / unresolved:
|
|
|
355
362
|
4. Post a compact `[lisa-repair-intake]` note only when the native close-out changed state or when
|
|
356
363
|
an actionable setup error must be surfaced. Do not spam already-closed terminal items.
|
|
357
364
|
|
|
358
|
-
### Build rollup
|
|
365
|
+
### Build parent rollup reconciliation (intermediate-env or terminal close-out)
|
|
359
366
|
|
|
360
|
-
For each parent/container item (Epic, Story, Spike, Project, or any item with child work)
|
|
361
|
-
|
|
367
|
+
For each parent/container item (Epic, Story, Spike, Project, or any item with child work),
|
|
368
|
+
reconcile its lifecycle state with the roll-up of its children — **including the intermediate-env
|
|
369
|
+
case**, not only fully-terminal close-out. This is the recovery-side complement to the forward
|
|
370
|
+
rollup the `*-sync --rollup` skills perform; it catches a parent that was never rolled up (or was
|
|
371
|
+
left in a status it should not carry, including a stale build-ready `ready`).
|
|
362
372
|
|
|
363
373
|
1. Read the child set using the vendor-native hierarchy first (GitHub sub-issues, JIRA
|
|
364
374
|
Epic/parent/sub-task hierarchy, Linear project/parent/sub-issues), with the same fallbacks the
|
|
365
375
|
vendor read/sync skills document.
|
|
366
|
-
2.
|
|
376
|
+
2. **Compute the derived parent state** bottom-up per the `leaf-only-lifecycle` **Parent status
|
|
377
|
+
rollup** state machine, evaluated over the env ladder `in-progress < dev < staging <
|
|
378
|
+
production` (the ordered keys of the env-keyed `done` map): any required child blocked →
|
|
379
|
+
`blocked`; else every required child shipped to some env → the **least-advanced** env among
|
|
380
|
+
them (e.g. all `On Stg` → `On Stg`); else any child started → `claimed`; else unchanged.
|
|
367
381
|
Optional / won't-do / not-planned children are terminal-but-dropped and do not hold the parent
|
|
368
382
|
open.
|
|
369
|
-
3.
|
|
370
|
-
lifecycle
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
383
|
+
3. **If the derived state differs from the parent's current state, apply it** via the vendor's
|
|
384
|
+
lifecycle write (JIRA transition, GitHub/Linear label swap keeping exactly one `status:*`),
|
|
385
|
+
removing any conflicting stale build lifecycle role — **including a stale `ready`** the parent
|
|
386
|
+
should never carry. Post an idempotent `[lisa-repair-intake]` rollup note naming the derived
|
|
387
|
+
state and the child tally (honor the backoff window + fingerprint).
|
|
388
|
+
4. **Perform native closure only at the true terminal `done`.** When — and only when — the derived
|
|
389
|
+
env is the production/terminal value, finalize through the provider-native mechanism (GitHub
|
|
390
|
+
`gh issue close --reason completed`, Linear move to Done state, JIRA resolved/closed verified at
|
|
391
|
+
`statusCategory = Done`). An intermediate-env rollup (`On Dev`/`On Stg`) advances the parent's
|
|
392
|
+
status but **must not** close it — it is still open per `leaf-only-lifecycle`.
|
|
393
|
+
5. If the derived state is `unchanged` (children exist but none started) or the required set is
|
|
394
|
+
ambiguous / inaccessible, leave the parent as-is and record it as `active` or `still_blocked`
|
|
395
|
+
with the current child tally; never guess a transition.
|
|
376
396
|
|
|
377
397
|
### PRD `in_review` (stalled in-progress) → re-run validate→route
|
|
378
398
|
|
|
@@ -483,8 +503,9 @@ cron tick.
|
|
|
483
503
|
## Lifecycle ownership guard
|
|
484
504
|
|
|
485
505
|
repair-intake owns the repair surfaces needed to recover stuck work and close-out drift:
|
|
486
|
-
build `claimed` / `blocked`, PRD `in_review` / `blocked`, terminal-labeled native-open items,
|
|
487
|
-
parent/container rollups
|
|
506
|
+
build `claimed` / `blocked`, PRD `in_review` / `blocked`, terminal-labeled native-open items,
|
|
507
|
+
parent/container rollups (intermediate-env *and* fully-terminal), and stale-`ready` containers.
|
|
508
|
+
It MAY:
|
|
488
509
|
|
|
489
510
|
- Apply the build scanner's post-agent `claimed → done` on a successful resume (it is finishing
|
|
490
511
|
the scanner's interrupted job), and move a dependency-cleared build item `blocked → claimed`.
|
|
@@ -492,8 +513,14 @@ parent/container rollups whose child sets are already terminal. It MAY:
|
|
|
492
513
|
as the PRD intake does.
|
|
493
514
|
- Close / complete / resolve build items that already carry the true terminal `done` role but are
|
|
494
515
|
still natively open, per `leaf-only-lifecycle`.
|
|
495
|
-
- Roll up a parent/container to
|
|
496
|
-
all required children
|
|
516
|
+
- Roll up a parent/container to its derived state per the `leaf-only-lifecycle` state machine —
|
|
517
|
+
**including an intermediate env value** (`On Dev`/`On Stg`) when all required children have
|
|
518
|
+
reached that env — and close/complete/resolve it **only** when the derived env is the true
|
|
519
|
+
terminal `done`.
|
|
520
|
+
- Reconcile a **container** wrongly carrying the build-ready `ready` role (a leaf-only-invariant
|
|
521
|
+
violation) by rolling it up from its children and removing the `ready`, with a
|
|
522
|
+
`[lisa-repair-intake]` audit note. This is the one `ready`-touching exception (see MUST NOT) and
|
|
523
|
+
applies only to containers, never to leaves.
|
|
497
524
|
- Move a PRD with fully terminal generated work to `shipped` and close/archive the source artifact
|
|
498
525
|
where the source vendor supports native close-out, per `prd-lifecycle-rollup`.
|
|
499
526
|
|
|
@@ -502,21 +529,27 @@ It MUST NOT:
|
|
|
502
529
|
- Move a PRD out of `draft` or `verified` (those are product-owned), or set `verified` itself.
|
|
503
530
|
- Apply a build `done` value other than via the env-resolution rules, or close a native item at
|
|
504
531
|
any value other than the true terminal `done` (see `leaf-only-lifecycle`).
|
|
505
|
-
- Touch `ready`
|
|
532
|
+
- Touch `ready` **leaves** (that is `lisa:intake`'s lane). A container carrying `ready` is the
|
|
533
|
+
documented exception above — repair-intake reconciles it because `ready` on a parent is an
|
|
534
|
+
invariant violation, not the human "claim this leaf" signal intake owns.
|
|
506
535
|
|
|
507
536
|
## Cycle behavior
|
|
508
537
|
|
|
509
538
|
1. **Resolve the queue** — detect vendor/lifecycle (Source dispatch); resolve stuck role names
|
|
510
539
|
from config. For JIRA, confirm the needed transitions are reachable; stop on misconfig.
|
|
511
540
|
2. **Enumerate repair candidates** — query in-progress role(s), `blocked` role(s), terminal/open
|
|
512
|
-
items,
|
|
541
|
+
items, rollup parents/PRDs with child work, and **containers carrying the `ready` role** (a
|
|
542
|
+
leaf-only-invariant violation to reconcile), for the detected lifecycle(s), up to
|
|
513
543
|
`max_candidates`, via the Access layer reads.
|
|
514
544
|
3. **Order deterministically**, highest repair-confidence first:
|
|
515
545
|
1. terminal-labeled items that only need native close / complete / resolve,
|
|
516
|
-
2. rollup parents/PRDs whose child sets are all terminal,
|
|
517
|
-
3.
|
|
518
|
-
|
|
519
|
-
|
|
546
|
+
2. rollup parents/PRDs whose child sets are all terminal (close-out),
|
|
547
|
+
3. rollup parents whose children have advanced to an intermediate env, or stale-`ready`
|
|
548
|
+
containers, that need their derived state applied (status-only reconciliation, no native
|
|
549
|
+
close),
|
|
550
|
+
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.
|
|
520
553
|
4. **Walk the ordered list**, evaluating each candidate (terminal close-out, rollup child tally,
|
|
521
554
|
staleness, dependency, answer checks), and repair **every** candidate that is actionable inside
|
|
522
555
|
the `max_candidates` cap. Continue after successful writes and after per-item errors.
|
|
@@ -539,8 +572,9 @@ Report outcomes in these buckets:
|
|
|
539
572
|
`ticketed`.
|
|
540
573
|
- `closed_out` — terminal-labeled items whose native open/active state was closed, completed,
|
|
541
574
|
resolved, or archived.
|
|
542
|
-
- `rolled_up` — parent/container/PRD rollups advanced
|
|
543
|
-
terminal
|
|
575
|
+
- `rolled_up` — parent/container/PRD rollups advanced to their derived state: an intermediate env
|
|
576
|
+
(e.g. all children at `On Stg` → parent `On Stg`), a fully-terminal close-out, or a stale-`ready`
|
|
577
|
+
container reconciled from its children.
|
|
544
578
|
- `still_blocked` — examined and intentionally left `blocked`, with the active reason.
|
|
545
579
|
- `active` — skipped because current work is not stale (or within backoff).
|
|
546
580
|
- `errors` — items that failed evaluation, with the error.
|
|
@@ -28,19 +28,20 @@ If `$ARGUMENTS` is empty, all vendor skills auto-detect a ticket reference from
|
|
|
28
28
|
|
|
29
29
|
When the caller passes `--rollup` after the milestone, the dispatch target additionally **derives the parent/container's lifecycle state from its children** instead of acting on the work item directly. This is the vendor-neutral implementation of the **Parent status rollup (the state machine)** section of the `leaf-only-lifecycle` rule — cite that rule, do not restate the policy here. The shim is dispatch only; the rollup mechanics live in the vendor sync skill (`lisa:github-sync`, `lisa:jira-sync`, `lisa:linear-sync`), which resolves child membership via its `*-read-*` skill and evaluates the state machine below.
|
|
30
30
|
|
|
31
|
-
The state machine (first match wins, evaluated over the **required** leaves only):
|
|
31
|
+
The state machine (first match wins, evaluated over the **required** leaves only, on the env ladder `in-progress < dev < staging < production` — the ordered keys of the project's env-keyed `done` map):
|
|
32
32
|
|
|
33
33
|
| If among the required leaves… | …the parent rolls up to | Role |
|
|
34
34
|
|---|---|---|
|
|
35
35
|
| any leaf is **blocked** | blocked / attention-needed | `blocked` |
|
|
36
|
-
| else
|
|
37
|
-
| else **
|
|
36
|
+
| else **every** required leaf has shipped to some env (each at a `done`-map value) | the **least-advanced** env among them | `done[min-env]` (terminal `done` at production) |
|
|
37
|
+
| else any leaf has **started** (claimed or in review, or shipped while a sibling has not) | active / in-progress | `claimed` (or `review` where supported) |
|
|
38
38
|
| else (leaves exist, none started) | unchanged | — |
|
|
39
39
|
|
|
40
40
|
- **Blocked dominates** — one blocked leaf surfaces blocked on the parent even while others progress.
|
|
41
|
+
- **Least-advanced env wins** — a parent reaches an env only once all required leaves have reached at least that env (all `On Stg` → `On Stg`; mixed dev/staging → the dev value). Native terminal closure fires only at the production `done`, never at an intermediate env.
|
|
41
42
|
- **The parent never carries `ready`** — `ready` is a human "claim this leaf" signal; rollup only moves a parent between non-ready container states.
|
|
42
43
|
- **Rollup is recursive** — an Epic rolls up from its Stories, each of which rolls up from its own leaves. Evaluate bottom-up.
|
|
43
|
-
- **The
|
|
44
|
+
- **The env rungs are the configured env-keyed `done`** — multi-env projects roll up to whichever `done` value (including intermediate `On Dev`/`On Stg`) their leaves have collectively reached (see `config-resolution` "Env-keyed `done`"). **Single-environment collapse (this repo):** `deploy.branches` declares only `production: main`, so `done` is a single value, the only env rung is production, and the GitHub build lifecycle collapses to `ready → claimed (in-progress) → done`; the rollup terminal is simply `done` (or the PRD-side `ticketed` for PRD containers), with **no** dev/staging promotion hops and **no** env-keyed multi-entry chain to resolve.
|
|
44
45
|
|
|
45
46
|
**Safe-by-default when not yet supported.** A vendor sync path that has not implemented native rollup MUST be a documented no-op that surfaces the derived state as a suggestion/comment rather than guessing a transition — never an unsafe default. Without `--rollup`, the sync skills behave exactly as before (milestone comment on the work item; no parent derivation).
|
|
46
47
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "Repair counterpart to /lisa:intake. Vendor-agnostic batch scanner that finds stuck or half-closed work — items left in `blocked`, stalled in an in-progress role (build `claimed`, PRD `in_review`), terminal-labeled items still natively open, and rollups whose children are all terminal — across the same queues /lisa:intake serves (Notion / Confluence / Linear / GitHub PRDs; JIRA / GitHub / Linear build issues). Repairs every materially actionable candidate inside the `max_candidates` cap: resumes stalled in-progress work in place — but for a stalled build it first diagnoses the PR/deploy state and, if the PR cannot merge (conflict, rebase, failing checks, unaddressed CodeRabbit/changes-requested) or a deploy failed, files a build-ready fix ticket and moves the item to `blocked` (blocked by it) instead of re-dispatching — re-validates blocked PRDs, re-dispatches blocked build items whose blockers have cleared, performs terminal native closure, and closes out completed rollups. Cron-safe and bounded; default GitHub intake_mode is both and default max_candidates is 100."
|
|
2
|
+
description: "Repair counterpart to /lisa:intake. Vendor-agnostic batch scanner that finds stuck or half-closed work — items left in `blocked`, stalled in an in-progress role (build `claimed`, PRD `in_review`), terminal-labeled items still natively open, and rollups whose children are all terminal — across the same queues /lisa:intake serves (Notion / Confluence / Linear / GitHub PRDs; JIRA / GitHub / Linear build issues). Repairs every materially actionable candidate inside the `max_candidates` cap: resumes stalled in-progress work in place — but for a stalled build it first diagnoses the PR/deploy state and, if the PR cannot merge (conflict, rebase, failing checks, unaddressed CodeRabbit/changes-requested) or a deploy failed, files a build-ready fix ticket and moves the item to `blocked` (blocked by it) instead of re-dispatching — re-validates blocked PRDs, re-dispatches blocked build items whose blockers have cleared, performs terminal native closure, reconciles parent rollups to their derived state (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 completed rollups. Cron-safe and bounded; default GitHub intake_mode is both and default max_candidates is 100."
|
|
3
3
|
argument-hint: "<Notion-PRD-database-URL | Confluence-space-URL | Confluence-parent-page-URL | Linear-workspace-URL | Linear-team-URL | GitHub-repo-URL | org/repo | JIRA-project-key | JQL-filter> [intake_mode=prd|build|both] [stale_after=2h] [max_candidates=100] [force=true]"
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -65,26 +65,31 @@ So the exception is narrow: childlessness *enables* build-ready only for types t
|
|
|
65
65
|
|
|
66
66
|
A parent/container never sets its own lifecycle state; it **derives** it from the roll-up of its children's states. Rollup is evaluated whenever a child transitions (or when intake observes the child set). Using the canonical build-lifecycle roles from `config-resolution` (`ready`, `claimed`, `review`, `blocked`, `done`):
|
|
67
67
|
|
|
68
|
-
Evaluate the
|
|
68
|
+
Evaluate over the **env ladder** `in-progress < dev < staging < production` — the ordered keys of the project's env-keyed `done` map, with `claimed`/`review` as the rung below the first env (a single-environment project has only the `production` rung). Take the **first** match:
|
|
69
69
|
|
|
70
70
|
| If among the required leaves… | …the parent rolls up to | Role |
|
|
71
71
|
|---|---|---|
|
|
72
72
|
| any leaf is **blocked** | blocked / attention-needed | `blocked` |
|
|
73
|
-
| else
|
|
74
|
-
| else
|
|
73
|
+
| else **every** required leaf has shipped to some env (each is at a `done`-map value) | the **least-advanced** env among them on the ladder | env-keyed `done[min-env]` (terminal `done` when that env is production) |
|
|
74
|
+
| else any leaf has **started** (claimed / in review, or shipped to some env while a sibling has not) | active / in-progress | `claimed` (or `review` where supported — see below) |
|
|
75
75
|
| else (leaves exist but none started) | unchanged (parent stays in its non-ready container state) | — |
|
|
76
76
|
|
|
77
|
+
The middle two rungs are the same idea seen at two resolutions: a parent reaches an env only once **all** its required leaves have reached **at least** that env. So all leaves at `On Stg` → parent `On Stg`; a mix of `On Dev` and `On Stg` → parent `On Dev` (the set as a whole has only fully reached dev); any leaf still `claimed`/`review` (not yet shipped anywhere) holds the parent at `claimed`. In a single-environment project the only env rung is production, so this collapses to the familiar "all leaves `done` → parent `done`, else `claimed`."
|
|
78
|
+
|
|
77
79
|
Notes:
|
|
78
80
|
|
|
79
81
|
- **Blocked dominates.** A single blocked leaf surfaces blocked/attention on the parent even if other leaves are progressing, so a human sees the parent needs attention.
|
|
80
|
-
- **"Required" leaves.** Optional or won't-do children do not hold a parent open; only the leaves that must ship for the parent to be complete are counted toward the
|
|
81
|
-
- **
|
|
82
|
+
- **"Required" leaves.** Optional or won't-do children do not hold a parent open; only the leaves that must ship for the parent to be complete are counted toward the env-rollup check.
|
|
83
|
+
- **Least-advanced env wins.** The parent reflects the env the whole required set has collectively reached — never an env ahead of its laggard leaf. Native closure (below) fires only when the resolved env is the production/terminal value, never at an intermediate env (`On Dev`/`On Stg`).
|
|
84
|
+
- **Rollup is recursive.** An Epic rolls up from its Stories, each of which rolls up from its own leaves. Evaluate bottom-up: a Story reaches an env only when its leaves have all reached at least that env; an Epic reaches it only when its Stories have.
|
|
82
85
|
- **Vendor support varies.** Apply the rollup state the vendor can express. Where a vendor has no native intermediate state, use the nearest configured role or a metadata/comment signal rather than forcing a non-existent status (PRD #522 non-goal: vendors need not expose identical states).
|
|
83
|
-
- **The parent never carries `ready`.** `ready` is a *human* "this is buildable, claim it" signal and only ever lives on leaves. Rollup moves a parent between non-ready container states (in-progress / blocked / terminal); it never sets the parent to `ready`.
|
|
86
|
+
- **The parent never carries `ready`.** `ready` is a *human* "this is buildable, claim it" signal and only ever lives on leaves. Rollup moves a parent between non-ready container states (in-progress / per-env / blocked / terminal); it never sets the parent to `ready`. A container found carrying `ready` is a leaf-only-invariant violation — recompute its rolled state from its children and apply that (see `repair-intake`).
|
|
87
|
+
|
|
88
|
+
### The rollup env states are the configured "done" map — multi-env capable
|
|
84
89
|
|
|
85
|
-
|
|
90
|
+
The env rungs are whatever the project configures for `done` — which is **env-keyed** (`config-resolution` "Env-keyed `done`"): a `done` map keyed by environment (`dev`, `staging`, `production`), each leaf's env resolved from its merged PR's base branch. This rule does **not** hardcode a `dev → staging → prod` promotion chain as required — that is a project-specific deploy topology; the ladder is simply the ordered keys of the project's `done` map. A downstream project with dev/staging/prod environments rolls a parent up to the least-advanced env value its required leaves have collectively reached (an intermediate-env parent state, e.g. `On Stg`), and only to the production `done` value once every required leaf is at production. The rule stays generic and multi-env capable.
|
|
86
91
|
|
|
87
|
-
|
|
92
|
+
Intermediate-env rollup and terminal native closure are distinct: a parent **rolls up to** an intermediate env (`On Dev`/`On Stg`) as its required leaves reach it, but native closure (next section) fires **only** at the production/terminal `done` value. A parent sitting at `On Stg` is correctly rolled up *and* still open.
|
|
88
93
|
|
|
89
94
|
**Single-environment collapse (this repo).** Lisa's own deploy has only `main`/`production` (no dev/staging), so `done` is a single value, not a map. For GitHub, the build lifecycle collapses to one chain: `ready → claimed (in-progress) → done`. The rollup terminal state is simply `done`. This is the *collapsed* case of the generic rule, not a different rule — projects with more environments keep the env-keyed map.
|
|
90
95
|
|
|
@@ -24,12 +24,14 @@ A container *type* with no children is structurally a leaf — and may be build-
|
|
|
24
24
|
|
|
25
25
|
## Parent state rollup (priority order, first match wins)
|
|
26
26
|
|
|
27
|
+
Evaluate over the env ladder `in-progress < dev < staging < production` (the ordered keys of the project's env-keyed `done` map; single-env projects have only the production rung):
|
|
28
|
+
|
|
27
29
|
1. Any leaf is **blocked** → parent rolls up to **blocked / attention-needed**.
|
|
28
|
-
2. Else
|
|
29
|
-
3. Else
|
|
30
|
+
2. Else **every** required leaf has shipped to some env → parent rolls up to the **least-advanced** env among them (all `On Stg` → `On Stg`; mixed `On Dev`+`On Stg` → `On Dev`; all production → terminal `done`).
|
|
31
|
+
3. Else any leaf has **started** (claimed/in review, or shipped while a sibling has not) → parent is **in-progress** (`claimed`).
|
|
30
32
|
4. Else (leaves exist but none started) → parent unchanged.
|
|
31
33
|
|
|
32
|
-
**Blocked dominates.** Optional/won't-do children do not hold a parent open. Rollup is recursive — bottom-up. The parent never carries `ready
|
|
34
|
+
**Blocked dominates.** A parent reaches an env only once all required leaves have reached at least that env. Intermediate-env rollup (`On Dev`/`On Stg`) happens, but native closure fires only at production `done`. Optional/won't-do children do not hold a parent open. Rollup is recursive — bottom-up. The parent never carries `ready`; a container found in `ready` is reconciled by rolling it up from its children.
|
|
33
35
|
|
|
34
36
|
## Terminal native closure
|
|
35
37
|
|
|
@@ -82,21 +82,22 @@ gh api graphql -f query='
|
|
|
82
82
|
|
|
83
83
|
If the `subIssues` field is unavailable (older GHES), fall back to body parentage exactly as `lisa:github-read-issue` does. If the issue has **no** children it is a leaf, not a parent — rollup is N/A; behave as a normal milestone sync.
|
|
84
84
|
|
|
85
|
-
**Evaluate the required children in
|
|
85
|
+
**Evaluate the required children over the env ladder `in-progress < dev < staging < production` (the ordered keys of the GitHub env-keyed `done` map, e.g. `status:on-dev < status:on-stg < status:done`) and take the first match** (canonical roles from `config-resolution`; the GitHub label map is `status:blocked`, `status:in-progress`, env-keyed `done`):
|
|
86
86
|
|
|
87
87
|
| If among the required child leaves… | Derived parent role | GitHub label |
|
|
88
88
|
|---|---|---|
|
|
89
89
|
| any child carries `status:blocked` (or is otherwise blocked) | `blocked` | `status:blocked` |
|
|
90
|
-
| else
|
|
91
|
-
| else **
|
|
90
|
+
| else **every** required child has shipped to some env (each at a `done`-map label, e.g. `status:on-dev`/`status:on-stg`/`status:done`) | `done[min-env]` | the **least-advanced** env label among them (all `status:on-stg` → `status:on-stg`; mixed dev+staging → `status:on-dev`; all production → `status:done`) |
|
|
91
|
+
| else any child has **started** (`status:in-progress`, or shipped to an env while a sibling has not) | `claimed` | `status:in-progress` |
|
|
92
92
|
| else (children exist, none started) | — | unchanged — parent keeps its non-ready container label |
|
|
93
93
|
|
|
94
94
|
- **Blocked dominates** — a single blocked child surfaces `status:blocked` on the parent even while siblings progress, so a human sees the parent needs attention.
|
|
95
|
-
- **
|
|
96
|
-
- **
|
|
95
|
+
- **Least-advanced env wins** — the parent reaches an env only when every required child has reached at least that env; it never sits ahead of its laggard child. Native closure (`gh issue close --reason completed`) fires only when the resolved env is the production `status:done`, never at `status:on-dev`/`status:on-stg`.
|
|
96
|
+
- **"Required" children only** — a child labelled won't-do / optional does not hold the parent open; only leaves that must ship count toward the env-rollup check.
|
|
97
|
+
- **Recursive** — a parent reaches an env only when its children have all reached at least that env; an Epic reaches it only when its Stories have themselves rolled up to it. Evaluate bottom-up.
|
|
97
98
|
- **Never set the parent to `status:ready`** — `ready` is leaf-only (the human "claim this" signal). Rollup only moves the parent between non-ready container labels.
|
|
98
99
|
|
|
99
|
-
**Single-environment collapse (this repo).** `.lisa.config.json` `deploy.branches` declares only `production: main`, so the
|
|
100
|
+
**Single-environment collapse (this repo).** `.lisa.config.json` `deploy.branches` declares only `production: main`, so the env-keyed `done` resolves to the single label `status:done` — there is no `status:on-dev` / `status:on-stg` and **no dev → staging → prod promotion chain**. Resolve the env rungs via the env-keyed `done` logic in `config-resolution`, but in the single-environment case the only rung is production and it collapses to the one `status:done` value; the rollup never attempts to resolve a dev or staging `done`. Projects that DO have multiple environments keep the env-keyed map and roll the parent up to whichever `done` (including intermediate `status:on-dev`/`status:on-stg`) its leaves have collectively reached.
|
|
100
101
|
|
|
101
102
|
**Apply the derived label** (only when it differs from the parent's current `status:*`): remove the parent's existing `status:*` label and add the derived one, keeping exactly one `status:*` label so the build-queue invariant holds. Post an idempotent `[claude-sync] rollup` comment naming the derived state and the child tally (e.g. `3/4 leaves terminal, 1 blocked → status:blocked`); skip the comment if an identical one is already the most recent rollup comment.
|
|
102
103
|
|
|
@@ -64,22 +64,23 @@ When invoked with `--rollup`, this skill **derives a parent/container ticket's s
|
|
|
64
64
|
|
|
65
65
|
**Resolve the child set the same way `lisa:jira-read-ticket` does** — the native Epic → Story → Sub-task hierarchy (Epic link / parent field for Stories, the subtask relationship for Sub-tasks), each with its current status. Fetch via `lisa:atlassian-access` (`operation: read-ticket` / `search-issues` with the parent's `"Epic Link" = <KEY>` or `parent = <KEY>` JQL). If the ticket has **no** children it is a leaf — rollup is N/A; behave as a normal milestone sync.
|
|
66
66
|
|
|
67
|
-
**Evaluate the required children in
|
|
67
|
+
**Evaluate the required children over the env ladder `in-progress < dev < staging < production` (the ordered keys of the JIRA env-keyed `done` map, e.g. `On Dev < On Stg < Done`) and take the first match** (canonical roles from `config-resolution`; the JIRA status map defaults to `Blocked`, `In Progress`, `Code Review`, env-keyed `done`):
|
|
68
68
|
|
|
69
69
|
| If among the required child leaves… | Derived parent role | JIRA status |
|
|
70
70
|
|---|---|---|
|
|
71
71
|
| any child is **blocked** | `blocked` | `Blocked` |
|
|
72
|
-
| else
|
|
73
|
-
| else **
|
|
72
|
+
| else **every** required child has shipped to some env (each at a `done`-map value, e.g. `On Dev`/`On Stg`/`Done`) | `done[min-env]` | the **least-advanced** env status among them (all `On Stg` → `On Stg`; mixed `On Dev`+`On Stg` → `On Dev`; all production → `Done`) |
|
|
73
|
+
| else any child has **started** (`In Progress` / `Code Review`, or shipped to an env while a sibling has not) | `claimed` | `In Progress` |
|
|
74
74
|
| else (children exist, none started) | — | unchanged — parent keeps its non-ready container status |
|
|
75
75
|
|
|
76
76
|
- **Blocked dominates** — a single blocked child surfaces `Blocked` on the parent even while siblings progress.
|
|
77
|
+
- **Least-advanced env wins** — the parent reaches an env only when every required child has reached at least that env; it never sits ahead of its laggard child. Apply native terminal resolution (the `leaf-only-lifecycle` Terminal native closure) only when the resolved env is the production `Done`, never at `On Dev`/`On Stg`.
|
|
77
78
|
- **"Required" children only** — won't-do / optional children do not hold the parent open.
|
|
78
|
-
- **Recursive** — an Epic reaches
|
|
79
|
+
- **Recursive** — an Epic reaches an env only when its Stories have themselves rolled up to at least that env; a Story reaches it only when its Sub-tasks have. Evaluate bottom-up.
|
|
79
80
|
- **Never set the parent to the build-ready status** — `ready` is leaf-only. Rollup only moves the parent between non-ready container statuses.
|
|
80
|
-
- **`review` is optional for JIRA** (`config-resolution`) — a project that omits `Code Review` keeps the parent in `In Progress` until
|
|
81
|
+
- **`review` is optional for JIRA** (`config-resolution`) — a project that omits `Code Review` keeps the parent in `In Progress` until it shifts to an env; skip the intermediate review hop rather than forcing a non-existent status (a `leaf-only-lifecycle` "vendor support varies" note).
|
|
81
82
|
|
|
82
|
-
**Single-environment collapse (this repo).** The
|
|
83
|
+
**Single-environment collapse (this repo).** The env rungs resolve via the env-keyed `done` logic in `config-resolution`. In this repo `deploy.branches` declares only `production: main`, so `done` collapses to a single status, the only env rung is production, and the lifecycle is `Ready → In Progress → Code Review → Done` with **no** dev/staging promotion hops; the rollup never resolves a dev or staging `done`. Multi-environment projects keep the env-keyed map and roll a parent up to intermediate env statuses (`On Dev`/`On Stg`).
|
|
83
84
|
|
|
84
85
|
**Apply the derived status** (only when it differs from the parent's current status) via `lisa:atlassian-access` `operation: transition`, and post an idempotent rollup comment naming the derived state and the child tally. **Safe default:** if the derived terminal cannot be resolved (ambiguous required-set or unresolvable env `done`), do not guess — post the derived suggestion as a comment and leave the parent's status untouched.
|
|
85
86
|
|
|
@@ -87,21 +87,22 @@ When the caller passes `--rollup`, this skill **derives a parent/container's `st
|
|
|
87
87
|
|
|
88
88
|
**Resolve the child set the same way `lisa:linear-read-issue` does** — `mcp__linear-server__list_issues({project: <id>})` for a Project's Issues, or `mcp__linear-server__get_issue` per child for an Issue's sub-Issues (via `parentId`). Capture each child's `status:*` label. If the item has **no** children it is a leaf — rollup is N/A; behave as a normal milestone sync.
|
|
89
89
|
|
|
90
|
-
**Evaluate the required children in
|
|
90
|
+
**Evaluate the required children over the env ladder `in-progress < dev < staging < production` (the ordered keys of the Linear env-keyed `done` map, e.g. `status:on-dev < status:on-stg < status:done`) and take the first match** (canonical roles from `config-resolution`; Linear label map is `status:blocked`, `status:in-progress`, `status:code-review`, env-keyed `done`):
|
|
91
91
|
|
|
92
92
|
| If among the required child leaves… | Derived parent role | Linear label |
|
|
93
93
|
|---|---|---|
|
|
94
94
|
| any child carries `status:blocked` | `blocked` | `status:blocked` |
|
|
95
|
-
| else
|
|
96
|
-
| else
|
|
95
|
+
| else **every** required child has shipped to some env (each at a `done`-map label, e.g. `status:on-dev`/`status:on-stg`/`status:done`) | `done[min-env]` | the **least-advanced** env label among them (all `status:on-stg` → `status:on-stg`; mixed dev+staging → `status:on-dev`; all production → `status:done`) |
|
|
96
|
+
| else any child has **started** (`status:in-progress` / `status:code-review`, or shipped to an env while a sibling has not) | `claimed` | `status:in-progress` |
|
|
97
97
|
| else (children exist, none started) | — | unchanged — parent keeps its non-ready container label |
|
|
98
98
|
|
|
99
99
|
- **Blocked dominates** — one blocked child surfaces `status:blocked` on the parent even while siblings progress.
|
|
100
|
+
- **Least-advanced env wins** — the parent reaches an env only when every required child has reached at least that env; it never sits ahead of its laggard child. Native completion (moving the workflow `state` to Done) fires only when the resolved env is the production `status:done`, never at `status:on-dev`/`status:on-stg`.
|
|
100
101
|
- **"Required" children only** — won't-do / optional (e.g. `Canceled`) children do not hold the parent open.
|
|
101
|
-
- **Recursive** — a Project reaches
|
|
102
|
+
- **Recursive** — a Project reaches an env only when its Issues have themselves rolled up to at least that env. Evaluate bottom-up.
|
|
102
103
|
- **Never set the parent to `status:ready`** — `ready` is leaf-only. Rollup only moves the parent between non-ready container labels.
|
|
103
104
|
|
|
104
|
-
**Single-environment collapse (this repo).** The
|
|
105
|
+
**Single-environment collapse (this repo).** The env rungs resolve via the env-keyed `done` logic in `config-resolution`. In this repo `deploy.branches` declares only `production: main`, so `done` collapses to the single `status:done` label, the only env rung is production, and the lifecycle is `status:ready → status:in-progress → status:code-review → status:done` with **no** dev/staging promotion hops; the rollup never resolves a dev or staging `done`. Multi-environment projects keep the env-keyed map and roll a parent up to intermediate env labels (`status:on-dev`/`status:on-stg`).
|
|
105
106
|
|
|
106
107
|
**Apply the derived label** via `mcp__linear-server__save_issue` (Project or Issue), removing the parent's existing `status:*` and adding the derived one so exactly one `status:*` label remains. Post an idempotent rollup comment naming the derived state and the child tally. The native Linear `state` is **not** auto-transitioned — only the `status:*` label, mirroring the `--update-label` rule. **Safe default:** if the derived terminal cannot be resolved (ambiguous required-set or unresolvable env `done`), do not guess — post the derived suggestion as a comment and leave the parent's label untouched.
|
|
107
108
|
|
|
@@ -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, and closes 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`
|
|
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."
|
|
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
|
|
|
@@ -24,9 +24,16 @@ close-out** roles and moves work *unstuck* or *fully closed*:
|
|
|
24
24
|
research/waiting resolves the ambiguity that stopped it.
|
|
25
25
|
- **Terminal-open drift** — an item already carrying its true terminal lifecycle role (for
|
|
26
26
|
example GitHub `status:done`) but still open/active in the provider's native state.
|
|
27
|
-
- **
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
- **Rollup drift** — a parent/container item (Epic, Story, PRD, Linear Project, or equivalent)
|
|
28
|
+
whose own lifecycle state does not match the roll-up of its children's states per
|
|
29
|
+
`leaf-only-lifecycle`. This covers the *completed* case (all children terminal → close the parent
|
|
30
|
+
out) **and** the *intermediate-env* case (all children shipped to an env like `On Stg`, but the
|
|
31
|
+
parent never advanced — including a parent left stranded in a status it should never carry).
|
|
32
|
+
- **Stale-`ready` container** — a parent/container (open child work, or a childless
|
|
33
|
+
Epic/Story/Spike) wrongly carrying the build-ready role. This is a leaf-only-invariant violation
|
|
34
|
+
the build-intake claim gate deliberately leaves for a human; repair-intake reconciles it by
|
|
35
|
+
rolling the parent up from its children (with an audit note), so a container never sits in `ready`
|
|
36
|
+
indefinitely.
|
|
30
37
|
|
|
31
38
|
This skill is the symmetric counterpart to `lisa:intake`. It reuses the same queue-detection,
|
|
32
39
|
the same agent-team orchestration, the same "don't ask, just run" confirmation policy, and the
|
|
@@ -131,9 +138,9 @@ claim-and-advance). The essentials, inlined here so this skill is self-complete:
|
|
|
131
138
|
| Confluence **parent page** URL/ID | PRD (Confluence, narrowed) | source=confluence | `in_review`, `blocked`, terminal/open PRDs, all-terminal generated-work rollups |
|
|
132
139
|
| Linear **workspace** URL, **team** URL/key, or literal `linear` | PRD (Linear) | source=linear | `in_review`, `blocked`, terminal/open PRDs, all-terminal generated-work rollups |
|
|
133
140
|
| GitHub **repo** URL / `org/repo` (PRD namespace) | PRD (GitHub) | source=github | `in_review`, `blocked`, terminal/open PRDs, all-terminal generated-work rollups |
|
|
134
|
-
| GitHub **repo** URL / `org/repo` with `tracker = github` (build namespace) | Build (GitHub) | tracker=github | `claimed`, `blocked`, terminal/open issues, all-terminal
|
|
141
|
+
| GitHub **repo** URL / `org/repo` with `tracker = github` (build namespace) | Build (GitHub) | tracker=github | `claimed`, `blocked`, terminal/open issues, parent rollups (intermediate-env + all-terminal), stale-`ready` containers |
|
|
135
142
|
| Literal `github` | GitHub; route by `intake_mode` (`prd` / `build` / `both`) | per lifecycle | per lifecycle above |
|
|
136
|
-
| JIRA project key or full JQL | Build (JIRA) | tracker=jira | `claimed`, `blocked`, terminal/closure verification, all-terminal
|
|
143
|
+
| JIRA project key or full JQL | Build (JIRA) | tracker=jira | `claimed`, `blocked`, terminal/closure verification, parent rollups (intermediate-env + all-terminal), stale-`ready` containers |
|
|
137
144
|
|
|
138
145
|
Disambiguation (same as `lisa:intake`): a `notion.so`/`notion.site` URL → Notion; an Atlassian
|
|
139
146
|
`/wiki/spaces/<KEY>` URL → Confluence (with `/pages/<id>` → parent-page narrowing); a
|
|
@@ -355,24 +362,37 @@ native-open / active / unresolved:
|
|
|
355
362
|
4. Post a compact `[lisa-repair-intake]` note only when the native close-out changed state or when
|
|
356
363
|
an actionable setup error must be surfaced. Do not spam already-closed terminal items.
|
|
357
364
|
|
|
358
|
-
### Build rollup
|
|
365
|
+
### Build parent rollup reconciliation (intermediate-env or terminal close-out)
|
|
359
366
|
|
|
360
|
-
For each parent/container item (Epic, Story, Spike, Project, or any item with child work)
|
|
361
|
-
|
|
367
|
+
For each parent/container item (Epic, Story, Spike, Project, or any item with child work),
|
|
368
|
+
reconcile its lifecycle state with the roll-up of its children — **including the intermediate-env
|
|
369
|
+
case**, not only fully-terminal close-out. This is the recovery-side complement to the forward
|
|
370
|
+
rollup the `*-sync --rollup` skills perform; it catches a parent that was never rolled up (or was
|
|
371
|
+
left in a status it should not carry, including a stale build-ready `ready`).
|
|
362
372
|
|
|
363
373
|
1. Read the child set using the vendor-native hierarchy first (GitHub sub-issues, JIRA
|
|
364
374
|
Epic/parent/sub-task hierarchy, Linear project/parent/sub-issues), with the same fallbacks the
|
|
365
375
|
vendor read/sync skills document.
|
|
366
|
-
2.
|
|
376
|
+
2. **Compute the derived parent state** bottom-up per the `leaf-only-lifecycle` **Parent status
|
|
377
|
+
rollup** state machine, evaluated over the env ladder `in-progress < dev < staging <
|
|
378
|
+
production` (the ordered keys of the env-keyed `done` map): any required child blocked →
|
|
379
|
+
`blocked`; else every required child shipped to some env → the **least-advanced** env among
|
|
380
|
+
them (e.g. all `On Stg` → `On Stg`); else any child started → `claimed`; else unchanged.
|
|
367
381
|
Optional / won't-do / not-planned children are terminal-but-dropped and do not hold the parent
|
|
368
382
|
open.
|
|
369
|
-
3.
|
|
370
|
-
lifecycle
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
383
|
+
3. **If the derived state differs from the parent's current state, apply it** via the vendor's
|
|
384
|
+
lifecycle write (JIRA transition, GitHub/Linear label swap keeping exactly one `status:*`),
|
|
385
|
+
removing any conflicting stale build lifecycle role — **including a stale `ready`** the parent
|
|
386
|
+
should never carry. Post an idempotent `[lisa-repair-intake]` rollup note naming the derived
|
|
387
|
+
state and the child tally (honor the backoff window + fingerprint).
|
|
388
|
+
4. **Perform native closure only at the true terminal `done`.** When — and only when — the derived
|
|
389
|
+
env is the production/terminal value, finalize through the provider-native mechanism (GitHub
|
|
390
|
+
`gh issue close --reason completed`, Linear move to Done state, JIRA resolved/closed verified at
|
|
391
|
+
`statusCategory = Done`). An intermediate-env rollup (`On Dev`/`On Stg`) advances the parent's
|
|
392
|
+
status but **must not** close it — it is still open per `leaf-only-lifecycle`.
|
|
393
|
+
5. If the derived state is `unchanged` (children exist but none started) or the required set is
|
|
394
|
+
ambiguous / inaccessible, leave the parent as-is and record it as `active` or `still_blocked`
|
|
395
|
+
with the current child tally; never guess a transition.
|
|
376
396
|
|
|
377
397
|
### PRD `in_review` (stalled in-progress) → re-run validate→route
|
|
378
398
|
|
|
@@ -483,8 +503,9 @@ cron tick.
|
|
|
483
503
|
## Lifecycle ownership guard
|
|
484
504
|
|
|
485
505
|
repair-intake owns the repair surfaces needed to recover stuck work and close-out drift:
|
|
486
|
-
build `claimed` / `blocked`, PRD `in_review` / `blocked`, terminal-labeled native-open items,
|
|
487
|
-
parent/container rollups
|
|
506
|
+
build `claimed` / `blocked`, PRD `in_review` / `blocked`, terminal-labeled native-open items,
|
|
507
|
+
parent/container rollups (intermediate-env *and* fully-terminal), and stale-`ready` containers.
|
|
508
|
+
It MAY:
|
|
488
509
|
|
|
489
510
|
- Apply the build scanner's post-agent `claimed → done` on a successful resume (it is finishing
|
|
490
511
|
the scanner's interrupted job), and move a dependency-cleared build item `blocked → claimed`.
|
|
@@ -492,8 +513,14 @@ parent/container rollups whose child sets are already terminal. It MAY:
|
|
|
492
513
|
as the PRD intake does.
|
|
493
514
|
- Close / complete / resolve build items that already carry the true terminal `done` role but are
|
|
494
515
|
still natively open, per `leaf-only-lifecycle`.
|
|
495
|
-
- Roll up a parent/container to
|
|
496
|
-
all required children
|
|
516
|
+
- Roll up a parent/container to its derived state per the `leaf-only-lifecycle` state machine —
|
|
517
|
+
**including an intermediate env value** (`On Dev`/`On Stg`) when all required children have
|
|
518
|
+
reached that env — and close/complete/resolve it **only** when the derived env is the true
|
|
519
|
+
terminal `done`.
|
|
520
|
+
- Reconcile a **container** wrongly carrying the build-ready `ready` role (a leaf-only-invariant
|
|
521
|
+
violation) by rolling it up from its children and removing the `ready`, with a
|
|
522
|
+
`[lisa-repair-intake]` audit note. This is the one `ready`-touching exception (see MUST NOT) and
|
|
523
|
+
applies only to containers, never to leaves.
|
|
497
524
|
- Move a PRD with fully terminal generated work to `shipped` and close/archive the source artifact
|
|
498
525
|
where the source vendor supports native close-out, per `prd-lifecycle-rollup`.
|
|
499
526
|
|
|
@@ -502,21 +529,27 @@ It MUST NOT:
|
|
|
502
529
|
- Move a PRD out of `draft` or `verified` (those are product-owned), or set `verified` itself.
|
|
503
530
|
- Apply a build `done` value other than via the env-resolution rules, or close a native item at
|
|
504
531
|
any value other than the true terminal `done` (see `leaf-only-lifecycle`).
|
|
505
|
-
- Touch `ready`
|
|
532
|
+
- Touch `ready` **leaves** (that is `lisa:intake`'s lane). A container carrying `ready` is the
|
|
533
|
+
documented exception above — repair-intake reconciles it because `ready` on a parent is an
|
|
534
|
+
invariant violation, not the human "claim this leaf" signal intake owns.
|
|
506
535
|
|
|
507
536
|
## Cycle behavior
|
|
508
537
|
|
|
509
538
|
1. **Resolve the queue** — detect vendor/lifecycle (Source dispatch); resolve stuck role names
|
|
510
539
|
from config. For JIRA, confirm the needed transitions are reachable; stop on misconfig.
|
|
511
540
|
2. **Enumerate repair candidates** — query in-progress role(s), `blocked` role(s), terminal/open
|
|
512
|
-
items,
|
|
541
|
+
items, rollup parents/PRDs with child work, and **containers carrying the `ready` role** (a
|
|
542
|
+
leaf-only-invariant violation to reconcile), for the detected lifecycle(s), up to
|
|
513
543
|
`max_candidates`, via the Access layer reads.
|
|
514
544
|
3. **Order deterministically**, highest repair-confidence first:
|
|
515
545
|
1. terminal-labeled items that only need native close / complete / resolve,
|
|
516
|
-
2. rollup parents/PRDs whose child sets are all terminal,
|
|
517
|
-
3.
|
|
518
|
-
|
|
519
|
-
|
|
546
|
+
2. rollup parents/PRDs whose child sets are all terminal (close-out),
|
|
547
|
+
3. rollup parents whose children have advanced to an intermediate env, or stale-`ready`
|
|
548
|
+
containers, that need their derived state applied (status-only reconciliation, no native
|
|
549
|
+
close),
|
|
550
|
+
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.
|
|
520
553
|
4. **Walk the ordered list**, evaluating each candidate (terminal close-out, rollup child tally,
|
|
521
554
|
staleness, dependency, answer checks), and repair **every** candidate that is actionable inside
|
|
522
555
|
the `max_candidates` cap. Continue after successful writes and after per-item errors.
|
|
@@ -539,8 +572,9 @@ Report outcomes in these buckets:
|
|
|
539
572
|
`ticketed`.
|
|
540
573
|
- `closed_out` — terminal-labeled items whose native open/active state was closed, completed,
|
|
541
574
|
resolved, or archived.
|
|
542
|
-
- `rolled_up` — parent/container/PRD rollups advanced
|
|
543
|
-
terminal
|
|
575
|
+
- `rolled_up` — parent/container/PRD rollups advanced to their derived state: an intermediate env
|
|
576
|
+
(e.g. all children at `On Stg` → parent `On Stg`), a fully-terminal close-out, or a stale-`ready`
|
|
577
|
+
container reconciled from its children.
|
|
544
578
|
- `still_blocked` — examined and intentionally left `blocked`, with the active reason.
|
|
545
579
|
- `active` — skipped because current work is not stale (or within backoff).
|
|
546
580
|
- `errors` — items that failed evaluation, with the error.
|