@codyswann/lisa 2.61.0 → 2.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/agents/confluence-prd-intake.md +1 -1
- package/plugins/lisa/agents/github-agent.md +4 -5
- package/plugins/lisa/agents/github-build-intake.md +1 -1
- package/plugins/lisa/agents/github-prd-intake.md +1 -1
- package/plugins/lisa/agents/linear-prd-intake.md +1 -1
- package/plugins/lisa/agents/notion-prd-intake.md +1 -1
- package/plugins/lisa/commands/intake.md +1 -1
- package/plugins/lisa/commands/project-ideation.md +3 -3
- package/plugins/lisa/commands/repair-intake.md +6 -0
- package/plugins/lisa/commands/research.md +3 -3
- package/plugins/lisa/commands/setup-automations.md +6 -0
- package/plugins/lisa/commands/tear-down-automations.md +6 -0
- package/plugins/lisa/commands/verify-prd.md +2 -2
- package/plugins/lisa/rules/config-resolution.md +63 -4
- package/plugins/lisa/rules/intent-routing.md +4 -3
- package/plugins/lisa/rules/leaf-only-lifecycle.md +1 -1
- package/plugins/lisa/rules/prd-lifecycle-rollup.md +10 -2
- package/plugins/lisa/rules/repo-scope-split.md +18 -1
- package/plugins/lisa/skills/confluence-prd-intake/SKILL.md +24 -14
- package/plugins/lisa/skills/confluence-prd-intake/agents/openai.yaml +2 -2
- package/plugins/lisa/skills/confluence-write-prd/SKILL.md +103 -0
- package/plugins/lisa/skills/confluence-write-prd/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/github-build-intake/SKILL.md +32 -21
- package/plugins/lisa/skills/github-evidence/SKILL.md +3 -26
- package/plugins/lisa/skills/github-evidence/agents/openai.yaml +2 -2
- package/plugins/lisa/skills/github-journey/SKILL.md +2 -2
- package/plugins/lisa/skills/github-prd-intake/SKILL.md +25 -11
- package/plugins/lisa/skills/github-prd-intake/agents/openai.yaml +2 -2
- package/plugins/lisa/skills/github-sync/SKILL.md +5 -5
- package/plugins/lisa/skills/github-write-issue/SKILL.md +15 -6
- package/plugins/lisa/skills/github-write-prd/SKILL.md +100 -0
- package/plugins/lisa/skills/github-write-prd/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/implement/SKILL.md +13 -6
- package/plugins/lisa/skills/intake/SKILL.md +13 -12
- package/plugins/lisa/skills/intake/agents/openai.yaml +2 -2
- package/plugins/lisa/skills/jira-build-intake/SKILL.md +24 -11
- package/plugins/lisa/skills/jira-write-ticket/SKILL.md +8 -0
- package/plugins/lisa/skills/linear-build-intake/SKILL.md +22 -9
- package/plugins/lisa/skills/linear-prd-intake/SKILL.md +23 -13
- package/plugins/lisa/skills/linear-prd-intake/agents/openai.yaml +2 -2
- package/plugins/lisa/skills/linear-write-issue/SKILL.md +10 -2
- package/plugins/lisa/skills/linear-write-prd/SKILL.md +90 -0
- package/plugins/lisa/skills/linear-write-prd/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/notion-access/SKILL.md +2 -0
- package/plugins/lisa/skills/notion-prd-intake/SKILL.md +22 -12
- package/plugins/lisa/skills/notion-prd-intake/agents/openai.yaml +2 -2
- package/plugins/lisa/skills/notion-write-prd/SKILL.md +107 -0
- package/plugins/lisa/skills/notion-write-prd/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/prd-source-write/SKILL.md +80 -0
- package/plugins/lisa/skills/prd-source-write/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/project-ideation/SKILL.md +183 -80
- package/plugins/lisa/skills/repair-intake/SKILL.md +403 -0
- package/plugins/lisa/skills/repair-intake/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/research/SKILL.md +19 -3
- package/plugins/lisa/skills/research/agents/openai.yaml +2 -2
- package/plugins/lisa/skills/setup-automations/SKILL.md +78 -0
- package/plugins/lisa/skills/setup-automations/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/setup-github/SKILL.md +0 -1
- package/plugins/lisa/skills/tear-down-automations/SKILL.md +34 -0
- package/plugins/lisa/skills/tear-down-automations/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/tracker-build-intake/SKILL.md +6 -2
- package/plugins/lisa/skills/tracker-build-intake/agents/openai.yaml +2 -2
- package/plugins/lisa/skills/tracker-evidence/SKILL.md +2 -2
- package/plugins/lisa/skills/tracker-sync/SKILL.md +1 -1
- package/plugins/lisa/skills/verify-prd/SKILL.md +41 -38
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/commands/exploratory-qa.md +3 -3
- package/plugins/lisa-expo/skills/exploratory-qa/SKILL.md +48 -18
- package/plugins/lisa-expo/skills/exploratory-qa/agents/openai.yaml +2 -2
- 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/commands/exploratory-qa.md +3 -3
- package/plugins/lisa-harper-fabric/skills/exploratory-qa/SKILL.md +48 -18
- package/plugins/lisa-harper-fabric/skills/exploratory-qa/agents/openai.yaml +2 -2
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-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-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/commands/exploratory-qa.md +3 -3
- package/plugins/lisa-rails/skills/exploratory-qa/SKILL.md +48 -18
- package/plugins/lisa-rails/skills/exploratory-qa/agents/openai.yaml +2 -2
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-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/skills/lisa-wiki-ingest/SKILL.md +30 -1
- package/plugins/src/base/agents/confluence-prd-intake.md +1 -1
- package/plugins/src/base/agents/github-agent.md +4 -5
- package/plugins/src/base/agents/github-build-intake.md +1 -1
- package/plugins/src/base/agents/github-prd-intake.md +1 -1
- package/plugins/src/base/agents/linear-prd-intake.md +1 -1
- package/plugins/src/base/agents/notion-prd-intake.md +1 -1
- package/plugins/src/base/commands/intake.md +1 -1
- package/plugins/src/base/commands/project-ideation.md +3 -3
- package/plugins/src/base/commands/repair-intake.md +6 -0
- package/plugins/src/base/commands/research.md +3 -3
- package/plugins/src/base/commands/setup-automations.md +6 -0
- package/plugins/src/base/commands/tear-down-automations.md +6 -0
- package/plugins/src/base/commands/verify-prd.md +2 -2
- package/plugins/src/base/rules/config-resolution.md +63 -4
- package/plugins/src/base/rules/intent-routing.md +4 -3
- package/plugins/src/base/rules/leaf-only-lifecycle.md +1 -1
- package/plugins/src/base/rules/prd-lifecycle-rollup.md +10 -2
- package/plugins/src/base/rules/repo-scope-split.md +18 -1
- package/plugins/src/base/skills/confluence-prd-intake/SKILL.md +24 -14
- package/plugins/src/base/skills/confluence-write-prd/SKILL.md +103 -0
- package/plugins/src/base/skills/github-build-intake/SKILL.md +32 -21
- package/plugins/src/base/skills/github-evidence/SKILL.md +3 -26
- package/plugins/src/base/skills/github-journey/SKILL.md +2 -2
- package/plugins/src/base/skills/github-prd-intake/SKILL.md +25 -11
- package/plugins/src/base/skills/github-sync/SKILL.md +5 -5
- package/plugins/src/base/skills/github-write-issue/SKILL.md +15 -6
- package/plugins/src/base/skills/github-write-prd/SKILL.md +100 -0
- package/plugins/src/base/skills/implement/SKILL.md +13 -6
- package/plugins/src/base/skills/intake/SKILL.md +13 -12
- package/plugins/src/base/skills/jira-build-intake/SKILL.md +24 -11
- package/plugins/src/base/skills/jira-write-ticket/SKILL.md +8 -0
- package/plugins/src/base/skills/linear-build-intake/SKILL.md +22 -9
- package/plugins/src/base/skills/linear-prd-intake/SKILL.md +23 -13
- package/plugins/src/base/skills/linear-write-issue/SKILL.md +10 -2
- package/plugins/src/base/skills/linear-write-prd/SKILL.md +90 -0
- package/plugins/src/base/skills/notion-access/SKILL.md +2 -0
- package/plugins/src/base/skills/notion-prd-intake/SKILL.md +22 -12
- package/plugins/src/base/skills/notion-write-prd/SKILL.md +107 -0
- package/plugins/src/base/skills/prd-source-write/SKILL.md +80 -0
- package/plugins/src/base/skills/project-ideation/SKILL.md +183 -80
- package/plugins/src/base/skills/repair-intake/SKILL.md +403 -0
- package/plugins/src/base/skills/research/SKILL.md +19 -3
- package/plugins/src/base/skills/setup-automations/SKILL.md +78 -0
- package/plugins/src/base/skills/setup-github/SKILL.md +0 -1
- package/plugins/src/base/skills/tear-down-automations/SKILL.md +34 -0
- package/plugins/src/base/skills/tracker-build-intake/SKILL.md +6 -2
- package/plugins/src/base/skills/tracker-evidence/SKILL.md +2 -2
- package/plugins/src/base/skills/tracker-sync/SKILL.md +1 -1
- package/plugins/src/base/skills/verify-prd/SKILL.md +41 -38
- package/plugins/src/expo/commands/exploratory-qa.md +3 -3
- package/plugins/src/expo/skills/exploratory-qa/SKILL.md +48 -18
- package/plugins/src/harper-fabric/commands/exploratory-qa.md +3 -3
- package/plugins/src/harper-fabric/skills/exploratory-qa/SKILL.md +48 -18
- package/plugins/src/rails/commands/exploratory-qa.md +3 -3
- package/plugins/src/rails/skills/exploratory-qa/SKILL.md +48 -18
- package/plugins/src/wiki/skills/lisa-wiki-ingest/SKILL.md +30 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: github-prd-intake
|
|
3
|
-
description: "Scans a GitHub repository for issues carrying the configured `ready` PRD label and runs
|
|
3
|
+
description: "Scans a GitHub repository for issues carrying the configured `ready` PRD label and runs the first eligible one through the dry-run validation pipeline. A PRD that passes every gate gets tickets written (to whatever destination tracker is configured — JIRA, GitHub Issues itself, or Linear) and the label flipped to the configured `ticketed` label; a PRD that fails gets clarifying-question comments and the label flipped to the configured `blocked` label. The GitHub counterpart of lisa:notion-prd-intake / lisa:confluence-prd-intake / lisa:linear-prd-intake. Composes existing skills (github-to-tracker, tracker-validate, tracker-source-artifacts, product-walkthrough)."
|
|
4
4
|
allowed-tools: ["Skill", "Bash"]
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -12,7 +12,7 @@ allowed-tools: ["Skill", "Bash"]
|
|
|
12
12
|
- A full GitHub repo URL (e.g., `https://github.com/acme/product-prds`).
|
|
13
13
|
- The literal token `github` — falls back to `.lisa.config.json` (`github.org` / `github.repo`).
|
|
14
14
|
|
|
15
|
-
Run one intake cycle against that repo.
|
|
15
|
+
Run one intake cycle against that repo. The first eligible issue with the `ready` label is claimed, validated, routed to either the `blocked` label (with clarifying comments) or the `ticketed` label (with destination tickets created), then the cycle exits. Remaining ready PRDs stay queued for later scheduler invocations.
|
|
16
16
|
|
|
17
17
|
## Workflow resolution
|
|
18
18
|
|
|
@@ -43,7 +43,7 @@ The **PRD closure rollup phase (3f)** transitions a `$TICKETED` PRD to `$SHIPPED
|
|
|
43
43
|
|
|
44
44
|
## Confirmation policy
|
|
45
45
|
|
|
46
|
-
Do NOT ask the caller whether to proceed. Once invoked with a repo, run the cycle to completion — claim, validate, branch to `$BLOCKED` or `$TICKETED`, write the summary. The caller has already authorized the run by invoking the skill; re-prompting defeats the purpose of a background
|
|
46
|
+
Do NOT ask the caller whether to proceed. Once invoked with a repo, run the cycle to completion for the first eligible PRD — claim, validate, branch to `$BLOCKED` or `$TICKETED`, write the summary, and exit. The caller has already authorized the run by invoking the skill; re-prompting defeats the purpose of a background queue.
|
|
47
47
|
|
|
48
48
|
Specifically forbidden:
|
|
49
49
|
|
|
@@ -69,7 +69,7 @@ draft → ready → in_review → blocked | ticketed → shipped → verified
|
|
|
69
69
|
|
|
70
70
|
(Defaults: `prd-draft` / `prd-ready` / `prd-in-review` / `prd-blocked` / `prd-ticketed` / `prd-shipped` / `prd-verified`.)
|
|
71
71
|
|
|
72
|
-
`verified` is the terminal state after `shipped`: it means the shipped product has been empirically checked against the PRD (set by `/lisa:verify-prd`, not by this intake skill). A failed post-ship verification
|
|
72
|
+
`verified` is the terminal state after `shipped`: it means the shipped product has been empirically checked against the PRD (set by `/lisa:verify-prd`, not by this intake skill). A failed post-ship verification does **not** use `blocked`; `/lisa:verify-prd` re-opens the PRD `shipped → ticketed` and creates build-ready fix tickets that auto-build and trigger a re-verify (the self-healing loop), introducing no `verifying` / `verification-failed` state. Like `draft` and `shipped`, `verified` is **product-owned** — this intake skill never sets, clears, or otherwise touches it. See the "PRD-level verification vs ticket verification" section of the `prd-lifecycle-rollup` rule.
|
|
73
73
|
|
|
74
74
|
Exactly one of these labels is expected on a PRD issue at any time.
|
|
75
75
|
|
|
@@ -124,9 +124,9 @@ gh issue list --repo <org>/<repo> --state open --limit 100 --json number,labels
|
|
|
124
124
|
|
|
125
125
|
If no PRD lifecycle labels appear on any open issue → convention not adopted; surface error and exit. If lifecycle labels exist but none are `$READY` → genuinely empty queue, exit cleanly with the idle message.
|
|
126
126
|
|
|
127
|
-
### Phase 3 — Process
|
|
127
|
+
### Phase 3 — Process the first eligible ready PRD
|
|
128
128
|
|
|
129
|
-
|
|
129
|
+
Select the first ready PRD issue returned by Phase 2 and process only that issue. Later scheduler invocations process the remaining ready PRDs.
|
|
130
130
|
|
|
131
131
|
#### 3a. Claim
|
|
132
132
|
|
|
@@ -225,9 +225,9 @@ For unanchored failures (`prd_anchor: null`), post one rollup comment prefixed w
|
|
|
225
225
|
|
|
226
226
|
After all comments are posted, transition: `gh issue edit <num> --remove-label "$IN_REVIEW" --add-label "$BLOCKED"`. Do NOT write any tickets.
|
|
227
227
|
|
|
228
|
-
#### 3d.
|
|
228
|
+
#### 3d. Stop
|
|
229
229
|
|
|
230
|
-
|
|
230
|
+
Stop immediately after the claimed PRD is ticketed, blocked, or recorded as an error.
|
|
231
231
|
|
|
232
232
|
#### 3e. Coverage audit (mandatory after $TICKETED)
|
|
233
233
|
|
|
@@ -238,7 +238,7 @@ Per-ticket gates prove each ticket is well-formed; they do NOT prove the *set* o
|
|
|
238
238
|
|
|
239
239
|
| Verdict | Action |
|
|
240
240
|
|---------|--------|
|
|
241
|
-
| `COMPLETE` | Done. Leave label as `$TICKETED`.
|
|
241
|
+
| `COMPLETE` | Done. Leave label as `$TICKETED`. End the cycle. |
|
|
242
242
|
| `COMPLETE_WITH_SCOPE_CREEP` | Post an advisory comment on the PRD issue naming the scope-creep tickets. Leave label as `$TICKETED`. |
|
|
243
243
|
| `GAPS_FOUND` | The created ticket set is incomplete. (a) For each gap, post a comment using the same product-facing template as Phase 3c.2 — anchored when `prd_anchor` is non-null. (b) Post one summary comment listing the tickets that *were* successfully created. (c) Transition labels from `$TICKETED` back to `$BLOCKED`. |
|
|
244
244
|
| `NO_TICKETS_FOUND` | Should not happen if step 2 succeeded. Log as Error; leave label as `$TICKETED` with a flag comment. |
|
|
@@ -338,6 +338,20 @@ The set of **required** children for the all-terminal check is the top-level chi
|
|
|
338
338
|
|
|
339
339
|
This phase only touches GitHub PRD issues. It implements exactly one PRD-lifecycle hop — `$TICKETED → $SHIPPED` — and the optional config-gated close that follows it. All terminal-state semantics, the generated-top-level-work boundary, the env-keyed `done` resolution, and the dedupe-by-child-ref idempotency come from the `prd-lifecycle-rollup` rule; this skill is its GitHub implementation, not a second source of truth.
|
|
340
340
|
|
|
341
|
+
#### 3g. PRD verification dispatch (close the loop on shipped PRDs)
|
|
342
|
+
|
|
343
|
+
`shipped` and `verified` are distinct facts about a PRD (see the `prd-lifecycle-rollup` rule's "PRD-level verification vs ticket verification" and "Closing the loop" sections). Rollup (3f) only reaches `$SHIPPED`; the `shipped → verified` (pass) / `shipped → ticketed` (fail) hops are owned by `/lisa:verify-prd`. This phase **closes that loop** by dispatching the initiative-level acceptance gate for shipped PRDs. It never performs the verification transition itself — the "never sets the verification outcome" invariant holds: `lisa:verify-prd`, not this skill, sets `verified` (or, on failure, re-opens the PRD to `ticketed`).
|
|
344
|
+
|
|
345
|
+
Re-query the PRDs currently carrying `$SHIPPED` via `gh issue list --repo <org>/<repo> --label "$SHIPPED" --state open`. Pick the **first** one and invoke `lisa:verify-prd <issue-url>`. Process **one shipped PRD per cycle** — `lisa:verify-prd` is a heavy full flow (spec-conformance + empirical verification + fix-issue creation), so it is bounded exactly like the single-ready-PRD claim in Phase 3; the scheduler drains the rest.
|
|
346
|
+
|
|
347
|
+
**Per-cycle combined bound:** each scheduler cycle dispatches at most one ready PRD (the Phase 3 single-ready-PRD claim) **and** at most one shipped PRD for verification (this Phase 3g dispatch), for a maximum of two PRD operations per cycle. Ready intake runs first (Phase 3), then shipped verify (Phase 3g).
|
|
348
|
+
|
|
349
|
+
`lisa:verify-prd` owns the outcome: on a CONFORMS verdict with all empirical checks passing it transitions `$SHIPPED → verified` and posts evidence; on a conformance miss or a failing/unavailable check it **re-opens the PRD `$SHIPPED → ticketed`** (never `blocked`) and creates **build-ready** fix tickets registered as the PRD's generated work, then posts a failure report — the fix tickets auto-build, rollup (3f) re-ships the PRD once they are terminal, and a later cycle re-verifies (the self-healing loop). Either branch moves the PRD out of `$SHIPPED`, so it is not re-picked this cycle; a PRD whose generated work is not actually terminal is guard-stopped by `lisa:verify-prd` (left `$SHIPPED`) — that is verify-prd's gate, not this skill's.
|
|
350
|
+
|
|
351
|
+
**`closeOnShipped` constraint:** when `github.labels.prd.rollup.closeOnShipped = true`, issues are closed immediately after reaching `$SHIPPED`. This Phase 3g query (`--state open`) will not find them, so those PRDs are permanently excluded from `lisa:verify-prd` dispatch. If PRD verification is required, set `github.labels.prd.rollup.closeOnShipped = false` (or omit it); closing on ship is an explicit opt-out of the shipped→verified verification loop.
|
|
352
|
+
|
|
353
|
+
This phase, like 3f, is **behaviorally identical across all four intake skills** (`github-prd-intake`, `linear-prd-intake`, `notion-prd-intake`, `confluence-prd-intake`) — only the `$SHIPPED` query surface differs; keep them aligned. Record the dispatched PRD + verify-prd's verdict in the summary.
|
|
354
|
+
|
|
341
355
|
### Phase 4 — Summary report
|
|
342
356
|
|
|
343
357
|
```text
|
|
@@ -379,10 +393,10 @@ When the configured destination tracker is GitHub Issues AND the PRD repo is the
|
|
|
379
393
|
|
|
380
394
|
## Idempotency & safety
|
|
381
395
|
|
|
382
|
-
- **
|
|
396
|
+
- **One item per cycle**: this skill processes the first eligible ready PRD issue from Phase 2, then exits. New or remaining ready issues are picked up by later scheduler invocations.
|
|
383
397
|
- **No writes outside the lifecycle**: this skill only ever writes to the destination tracker via `lisa:github-to-tracker` (which delegates to `lisa:tracker-write`), only ever changes labels among `$IN_REVIEW`, `$BLOCKED`, `$TICKETED`, `$SHIPPED`, only ever comments on the source PRD issue. It never edits PRD bodies and never touches the `draft` label. It sets the `$SHIPPED` label and may close the PRD issue **only** through the config-gated rollup phase (3f), and never deletes any issue.
|
|
384
398
|
- **Claim-first ordering**: the label flip to `$IN_REVIEW` happens BEFORE validation runs.
|
|
385
|
-
- **Failure
|
|
399
|
+
- **Failure handling**: an exception processing the selected PRD is caught and recorded under "Errors" in the summary, then the cycle exits. The PRD that errored is left labeled `$IN_REVIEW` — humans investigate from there.
|
|
386
400
|
- **Single-label invariant**: after every transition, verify exactly one lifecycle label is present.
|
|
387
401
|
- **Rollup idempotency**: rollup (Phase 3f) is a no-op on a PRD already carrying `$SHIPPED` (and already closed when `closeOnShipped` is `true`) — no duplicate transition, no duplicate close, no duplicate comment. The all-terminal condition is a pure function of the children's current states, so recomputing it is safe to re-run. Closure NEVER precedes the all-terminal condition.
|
|
388
402
|
|
|
@@ -57,10 +57,10 @@ Based on the milestone, suggest (but do NOT automatically perform) a label trans
|
|
|
57
57
|
| Milestone | Suggested label |
|
|
58
58
|
|-----------|-----------------|
|
|
59
59
|
| Plan created | `status:in-progress` |
|
|
60
|
-
| PR ready | `status:
|
|
61
|
-
| PR merged |
|
|
60
|
+
| PR ready | configured `done` label (`status:done` in this repo) |
|
|
61
|
+
| PR merged | no additional build-label transition |
|
|
62
62
|
|
|
63
|
-
The actual `status:in-progress` flip is owned by `lisa:github-build-intake` (claim) and `lisa:github-agent`. The `
|
|
63
|
+
The actual `status:in-progress` flip is owned by `lisa:github-build-intake` (claim) and `lisa:github-agent`. The configured `done` flip is owned by the build-intake owner after a successful build and evidence post. This skill never relabels.
|
|
64
64
|
|
|
65
65
|
### Step 5: Parent Status Rollup (`--rollup`)
|
|
66
66
|
|
|
@@ -82,12 +82,12 @@ 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 priority order and take the first match** (canonical roles from `config-resolution`; the GitHub label map is `status:blocked`, `status:in-progress`, `status:
|
|
85
|
+
**Evaluate the required children in priority order and take the first match** (canonical roles from `config-resolution`; the GitHub label map is `status:blocked`, `status:in-progress`, `status: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 any child carries `status:in-progress`
|
|
90
|
+
| else any child carries `status:in-progress` | `claimed` | `status:in-progress` |
|
|
91
91
|
| else **all** required children are terminal (closed / `status:done`) | `done` | the configured terminal `done` label |
|
|
92
92
|
| else (children exist, none started) | — | unchanged — parent keeps its non-ready container label |
|
|
93
93
|
|
|
@@ -194,7 +194,7 @@ GitHub Issues uses **labels** for the structured metadata that JIRA stores in cu
|
|
|
194
194
|
| Concept | Label format | Example |
|
|
195
195
|
|---------|--------------|---------|
|
|
196
196
|
| Issue type | `type:<value>` | `type:Story`, `type:Bug`, `type:Epic`, `type:Sub-task`, `type:Spike`, `type:Improvement` |
|
|
197
|
-
| Status | `status:<value>` | `status:ready`, `status:in-progress`, `status:
|
|
197
|
+
| Status | `status:<value>` | `status:ready`, `status:in-progress`, `status:on-dev`, `status:done` |
|
|
198
198
|
| Priority | `priority:<value>` | `priority:low`, `priority:medium`, `priority:high`, `priority:critical` |
|
|
199
199
|
| Components | `component:<name>` | `component:auth`, `component:billing` |
|
|
200
200
|
| Story points | `points:<n>` | `points:3`, `points:5`, `points:8` |
|
|
@@ -212,6 +212,14 @@ The build-ready status label (`status:ready`) is governed by the `leaf-only-life
|
|
|
212
212
|
|
|
213
213
|
For non-build-ready issues created fresh (Epics, Stories, and other containers), omit the status label entirely; the container's rollup state is derived, not set directly.
|
|
214
214
|
|
|
215
|
+
### Build-ready control input (`build_ready`)
|
|
216
|
+
|
|
217
|
+
`build_ready` is an optional write-control input (default: **omitted**). It governs whether a **leaf** work unit is stamped with the build-ready role on create. It never overrides `leaf-only-lifecycle` — a container is never stamped build-ready regardless of `build_ready`. "Not build-ready" is not a special status: it simply means the issue is created in its natural default (a plain open issue with **no `status:ready` label**), which a human can promote later.
|
|
218
|
+
|
|
219
|
+
- **Omitted** → current behavior: a leaf work unit receives `status:ready`. Preserves what every existing caller (`lisa:plan`, the `*-to-tracker` skills) relies on.
|
|
220
|
+
- **`build_ready: false`** → create the leaf **without** `status:ready`, so it sits in the backlog for a human to review and promote into the queue.
|
|
221
|
+
- **`build_ready: true`** → ensure the leaf carries `status:ready` so `lisa:intake` / `lisa:github-build-intake` auto-picks it up.
|
|
222
|
+
|
|
215
223
|
## Phase 5.5 — Validate (Pre-write Gate)
|
|
216
224
|
|
|
217
225
|
Before any write, invoke `lisa:github-validate-issue` with the full proposed spec assembled from Phases 2 / 3 / 4 / 5. Pass it as a YAML block per the `lisa:github-validate-issue` schema, including `runtime_behavior_change`, `authenticated_surface`, and `artifacts_attached` flags so the right gates run.
|
|
@@ -224,9 +232,9 @@ If the validator reports `FAIL`, do NOT proceed to Phase 6. Fix the spec and re-
|
|
|
224
232
|
|
|
225
233
|
### CREATE
|
|
226
234
|
|
|
227
|
-
1. Compose the body markdown from Phases 2/3/4 in a temp file (avoid quoting hell). Apply `status:ready` **only for a leaf work unit** per the Phase 5 leaf-only rule (`leaf-only-lifecycle`) — omit it for `Epic` / `Story` / `Spike` and any issue that has child work:
|
|
235
|
+
1. Compose the body markdown from Phases 2/3/4 in a temp file (avoid quoting hell). Apply `status:ready` **only for a leaf work unit** per the Phase 5 leaf-only rule (`leaf-only-lifecycle`) — omit it for `Epic` / `Story` / `Spike` and any issue that has child work, **and** only when `build_ready` is not `false` (a leaf with `build_ready: false` is created without `status:ready`; see the Build-ready control input):
|
|
228
236
|
```bash
|
|
229
|
-
# Leaf work unit (Bug / Task / Sub-task / Improvement with no children):
|
|
237
|
+
# Leaf work unit (Bug / Task / Sub-task / Improvement with no children), build_ready not false:
|
|
230
238
|
gh issue create \
|
|
231
239
|
--repo <org>/<repo> \
|
|
232
240
|
--title "<summary>" \
|
|
@@ -235,8 +243,9 @@ If the validator reports `FAIL`, do NOT proceed to Phase 6. Fix the spec and re-
|
|
|
235
243
|
[--label "component:<name>" ...] [--milestone "<milestone>"] \
|
|
236
244
|
[--assignee "<login>"]
|
|
237
245
|
|
|
238
|
-
# Container (Epic / Story / Spike / any issue with child work):
|
|
239
|
-
# identical, but WITHOUT --label "status:ready" —
|
|
246
|
+
# Container (Epic / Story / Spike / any issue with child work), OR a leaf with build_ready: false:
|
|
247
|
+
# identical, but WITHOUT --label "status:ready" — a container's state rolls up from children;
|
|
248
|
+
# a build_ready: false leaf waits in the backlog for a human to promote it.
|
|
240
249
|
gh issue create \
|
|
241
250
|
--repo <org>/<repo> \
|
|
242
251
|
--title "<summary>" \
|
|
@@ -293,7 +302,7 @@ The mapping below is the single source of truth for how JIRA concepts translate
|
|
|
293
302
|
| JIRA concept | GitHub Issues equivalent |
|
|
294
303
|
|---|---|
|
|
295
304
|
| Issue type | Label `type:<value>` |
|
|
296
|
-
| Status (Ready / In Progress /
|
|
305
|
+
| Status (Ready / In Progress / On Dev / Done) | Label `status:<value>` |
|
|
297
306
|
| Epic / Story / Sub-task hierarchy | Native sub-issues via `gh api graphql addSubIssue` |
|
|
298
307
|
| Acceptance Criteria | `## Acceptance Criteria` markdown section with a Gherkin code-fence |
|
|
299
308
|
| Validation Journey | `## Validation Journey` markdown section |
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: github-write-prd
|
|
3
|
+
description: "Creates or idempotently updates a PRD as a GitHub Issue in the configured source repo, carrying exactly one PRD lifecycle label (`prd-draft` by default, or `prd-ready` when initial_role is ready so lisa:github-prd-intake auto-claims it). The GitHub PRD-source writer behind lisa:prd-source-write — the source-side counterpart of lisa:github-write-issue. Dedupes by a stable marker embedded in the issue body (matched by marker, never by title) so re-running ideation references the existing PRD instead of opening a duplicate. Uses the `gh` CLI exclusively."
|
|
4
|
+
allowed-tools: ["Skill", "Bash"]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Write GitHub PRD: $ARGUMENTS
|
|
8
|
+
|
|
9
|
+
Create (or update) a PRD issue in the configured source repo. Invoked by `lisa:prd-source-write`
|
|
10
|
+
when `source = github`; do not call directly from a vendor-neutral caller.
|
|
11
|
+
|
|
12
|
+
`$ARGUMENTS` carries the `lisa:prd-source-write` spec: `title`, `body` (full PRD markdown),
|
|
13
|
+
`initial_role` (`draft` | `ready`, default `draft`), `dedupe_key`, `marker`, optional `source_ref`.
|
|
14
|
+
|
|
15
|
+
## Phase 1 — Resolve repo and PRD lifecycle labels
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
ORG=$(jq -r '.github.org // empty' .lisa.config.local.json 2>/dev/null); ORG="${ORG:-$(jq -r '.github.org // empty' .lisa.config.json)}"
|
|
19
|
+
REPO=$(jq -r '.github.repo // empty' .lisa.config.local.json 2>/dev/null); REPO="${REPO:-$(jq -r '.github.repo // empty' .lisa.config.json)}"
|
|
20
|
+
[ -z "$ORG" ] || [ -z "$REPO" ] && { echo "Error: github.org / github.repo not set in .lisa.config.json."; exit 1; }
|
|
21
|
+
|
|
22
|
+
read_role() { # path default
|
|
23
|
+
local lv gv; lv=$(jq -r "$1 // empty" .lisa.config.local.json 2>/dev/null); gv=$(jq -r "$1 // empty" .lisa.config.json 2>/dev/null)
|
|
24
|
+
echo "${lv:-${gv:-$2}}"
|
|
25
|
+
}
|
|
26
|
+
# Resolve the FULL PRD lifecycle vocabulary from config (never hard-code names) — needed so the
|
|
27
|
+
# "exactly one role" reconcile and the past-ready check work for projects that renamed any label.
|
|
28
|
+
PRD_DRAFT=$(read_role '.github.labels.prd.draft' 'prd-draft')
|
|
29
|
+
PRD_READY=$(read_role '.github.labels.prd.ready' 'prd-ready')
|
|
30
|
+
PRD_IN_REVIEW=$(read_role '.github.labels.prd.in_review' 'prd-in-review')
|
|
31
|
+
PRD_BLOCKED=$(read_role '.github.labels.prd.blocked' 'prd-blocked')
|
|
32
|
+
PRD_TICKETED=$(read_role '.github.labels.prd.ticketed' 'prd-ticketed')
|
|
33
|
+
PRD_SHIPPED=$(read_role '.github.labels.prd.shipped' 'prd-shipped')
|
|
34
|
+
PRD_VERIFIED=$(read_role '.github.labels.prd.verified' 'prd-verified')
|
|
35
|
+
# All lifecycle labels (for one-of reconcile) and the "progressed past ready" set (never down-rank):
|
|
36
|
+
ALL_PRD_LABELS=("$PRD_DRAFT" "$PRD_READY" "$PRD_IN_REVIEW" "$PRD_BLOCKED" "$PRD_TICKETED" "$PRD_SHIPPED" "$PRD_VERIFIED")
|
|
37
|
+
PROGRESSED=("$PRD_IN_REVIEW" "$PRD_BLOCKED" "$PRD_TICKETED" "$PRD_SHIPPED" "$PRD_VERIFIED")
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Resolve the target role label from `initial_role`: `ready` → `$PRD_READY`, otherwise `$PRD_DRAFT`.
|
|
41
|
+
Create the label lazily if missing (`gh label create <name> --repo $ORG/$REPO ...`).
|
|
42
|
+
|
|
43
|
+
## Phase 2 — Dedupe by marker (search before create)
|
|
44
|
+
|
|
45
|
+
The `marker` (e.g. `[lisa-project-ideation] idea=<key>`) is embedded in the issue body. Search for an
|
|
46
|
+
existing **open** PRD issue carrying it — match on the marker, **never** on the title:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
EXISTING=$(gh issue list --repo "$ORG/$REPO" --state open --search "\"$MARKER\" in:body" --json number,url --jq '.[0].number // empty')
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
- If `source_ref` was passed, use that issue as the target (skip the search).
|
|
53
|
+
- If an existing open PRD issue is found, this is an **update** — reuse it, do not create a second.
|
|
54
|
+
- If `gh`'s search index hasn't caught up (eventual consistency), additionally `gh issue list … --json number,body` and grep the body for the marker before deciding to create.
|
|
55
|
+
|
|
56
|
+
## Phase 3 — Create or update
|
|
57
|
+
|
|
58
|
+
**Marker normalization (both paths).** Before writing any body, ensure it contains **exactly one**
|
|
59
|
+
marker line — inject `<!-- $MARKER -->` if the caller's synthesized body doesn't already carry it.
|
|
60
|
+
**Never write a markerless body** (including on UPDATE or when `source_ref` is passed): a body without
|
|
61
|
+
the marker breaks future dedupe. If the body already has the marker, leave the single instance.
|
|
62
|
+
|
|
63
|
+
**CREATE** (no existing issue):
|
|
64
|
+
|
|
65
|
+
1. Write the marker-normalized PRD body to a temp file.
|
|
66
|
+
2. ```bash
|
|
67
|
+
gh issue create --repo "$ORG/$REPO" --title "$TITLE" --body-file /tmp/prd-body.md --label "$ROLE_LABEL"
|
|
68
|
+
```
|
|
69
|
+
3. Capture the returned issue number/URL.
|
|
70
|
+
|
|
71
|
+
**UPDATE** (existing issue or `source_ref`):
|
|
72
|
+
|
|
73
|
+
1. `gh issue edit <n> --repo "$ORG/$REPO" --body-file /tmp/prd-body.md` with the **marker-normalized**
|
|
74
|
+
body (regenerate in place; never drop the marker).
|
|
75
|
+
2. Reconcile the lifecycle label to **exactly one**: add `$ROLE_LABEL`, remove every other label in
|
|
76
|
+
the resolved `${ALL_PRD_LABELS[@]}` set (the config-resolved names — not a hard-coded list) via
|
|
77
|
+
`gh issue edit <n> --add-label / --remove-label`. Never leave a PRD carrying two lifecycle labels.
|
|
78
|
+
- Exception: do **not** down-rank a PRD whose current label is in the resolved `${PROGRESSED[@]}`
|
|
79
|
+
set (already past `ready`). If so, leave it and report `reused (already past ready)`.
|
|
80
|
+
|
|
81
|
+
## Phase 4 — Return
|
|
82
|
+
|
|
83
|
+
Return a structured result for `lisa:prd-source-write` to surface:
|
|
84
|
+
|
|
85
|
+
```yaml
|
|
86
|
+
ref: "<org>/<repo>#<n>"
|
|
87
|
+
url: "https://github.com/<org>/<repo>/issues/<n>"
|
|
88
|
+
role: draft | ready # the lifecycle label now applied (or the PRD's current role when reused past ready)
|
|
89
|
+
marker: "<MARKER>"
|
|
90
|
+
outcome: created | reused
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Rules
|
|
94
|
+
|
|
95
|
+
- Exactly one PRD lifecycle label at all times (leaf-only does not apply — PRDs are not build leaves).
|
|
96
|
+
- Match dedupe by marker, never by title.
|
|
97
|
+
- Never down-rank a PRD already past `ready`.
|
|
98
|
+
- A *closed* prior PRD does not suppress a new one — a recurrence after closure is a genuine new PRD.
|
|
99
|
+
- This is a source-side writer (`prd-*` labels). It never touches build labels (`status:*`) — that is
|
|
100
|
+
`lisa:github-write-issue`'s lane. See `config-resolution` "Self-host edge case".
|
|
@@ -49,16 +49,23 @@ When deciding the agents to use, consider:
|
|
|
49
49
|
|
|
50
50
|
Using the general-purpose agent in Team Lead session, Determine the name of this plan
|
|
51
51
|
|
|
52
|
-
Using the general-purpose agent in Team Lead session,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
Using the general-purpose agent in Team Lead session, **determine the base branch from the ticket's target environment, then sync the working branch onto the latest of it before any work** — so implementation always builds on current target-environment code:
|
|
53
|
+
|
|
54
|
+
1. **Resolve the target environment** from the resolved work item — its `## Target Backend Environment` section (the field the `*-write-*` / `*-add-journey` skills record).
|
|
55
|
+
2. **Map the environment to a base branch** via `.lisa.config.json` `deploy.branches` (e.g. `staging → staging`, `production → main`) — the forward direction of the same map the env-keyed `done` resolution uses in reverse (see the `config-resolution` rule). If the work item names **no** environment, the base branch is the **remote default branch** (`gh repo view --json defaultBranchRef -q .defaultBranchRef.name`, or `git remote set-head origin -a` then read `origin/HEAD`). If the named environment is absent from `deploy.branches`, or its branch does not exist on the remote, **stop and report** — never guess a base.
|
|
56
|
+
3. **Establish the feature branch off the latest base, conflict-free:**
|
|
57
|
+
- `git fetch origin`.
|
|
58
|
+
- Already on a feature branch with an **open PR** → reuse it. If the PR's base ≠ the resolved base branch, surface the mismatch and re-target only with confirmation — the ticket's environment is the source of truth.
|
|
59
|
+
- Already on a feature branch with **no open PR** → reuse it; its PR base will be the resolved base branch (do not ask the human — the environment determines it).
|
|
60
|
+
- On an **environment / default branch** → check out a feature branch named for this plan (with the work-item ref prefix, per the linkage rules below) **from `origin/<base>`**.
|
|
61
|
+
- **Rebase the feature branch onto `origin/<base>` and resolve any merge conflicts BEFORE starting work.** If the conflicts cannot be resolved cleanly and safely, create a fix task for the agent team (with the conflicting file list and current merge state) and resolve it before implementation begins — never start work on stale or conflicted code.
|
|
62
|
+
4. **The PR targets the resolved base branch** — carry it as `target_branch=<base>` into `lisa:git-submit-pr` (Verify flow). `git-submit-pr` already chooses a closing keyword when the base is the production/default branch and a non-closing reference for a non-terminal environment branch.
|
|
56
63
|
|
|
57
64
|
When the request came from a tracker work item, preserve its native identifier for development linkage:
|
|
58
65
|
|
|
59
66
|
- Capture `tracker_provider` and `work_item_ref` from the resolved input before creating or reusing a branch. Examples: `github` + `CodySwannGT/lisa#614`, `linear` + `ENG-123`, `jira` + `ENG-123`.
|
|
60
67
|
- If a new branch is needed and the provider can link branches by identifier, include the identifier in the branch name before the human-readable slug. Linear and JIRA integrations commonly link from branch names; GitHub issue linkage is PR-body driven, but including the issue number in the branch name is still useful. Keep branch names URL-safe, for example `codex/ENG-123-add-checkout-copy` or `codex/614-add-checkout-copy`.
|
|
61
|
-
- Pass the work-item ref and target branch to `lisa:git-submit-pr` when opening or updating the PR, for example `work_item_ref=CodySwannGT/lisa#614 target_branch
|
|
68
|
+
- Pass the work-item ref and target branch to `lisa:git-submit-pr` when opening or updating the PR, for example `work_item_ref=CodySwannGT/lisa#614 target_branch=<base resolved from the ticket's environment above>` (not hardcoded `main`). The PR workflow owns provider-specific body text and must decide whether to use a closing keyword or a non-closing reference.
|
|
62
69
|
- If the provider has no native branch or PR development-linkage surface, continue without linkage and mention that the provider was skipped.
|
|
63
70
|
|
|
64
71
|
Using the general-purpose agent in Team Lead session, Determine which flow applies:
|
|
@@ -122,7 +129,7 @@ Before shutting down the team, execute the Verify flow:
|
|
|
122
129
|
3. Write e2e test encoding the verification
|
|
123
130
|
4. Commit ALL outstanding changes in logical batches on the branch (minus sensitive data/information) — not just changes made by the agent team. This includes pre-existing uncommitted changes that were on the branch before the plan started. Do NOT filter commits to only "task-related" files. If it shows up in git status, it gets committed (unless it contains secrets).
|
|
124
131
|
5. Push the changes - if any pre-push hook blocks you, create a task for the agent team to fix the error/problem whether it was pre-existing or not
|
|
125
|
-
6. Open a pull request with auto-merge on via `lisa:git-submit-pr`, including the work-item ref when one exists so the PR can be linked natively to the source issue.
|
|
132
|
+
6. Open a pull request with auto-merge on via `lisa:git-submit-pr`, targeting the **base branch resolved from the ticket's environment** (`target_branch=<base>`, per the branch step above), and including the work-item ref when one exists so the PR can be linked natively to the source issue.
|
|
126
133
|
7. PR Watch Loop: Monitor the PR using `git-submit-pr`'s drive-to-merge behavior. Create a task for the agent team to resolve any code review comments by either implementing the suggestions or commenting why they should not be implemented and close the comment. Fix any failing checks and repush. If the PR is `BEHIND`, blocked by stale review state, or cannot enable auto-merge, follow the harness-agnostic `git-submit-pr` re-sync, review-gate, and direct-merge fallback loop until the PR is actually merged or a blocking failure is surfaced.
|
|
127
134
|
8. Merge the PR
|
|
128
135
|
9. Monitor the deploy action that triggers automatically from the successful merge
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: intake
|
|
3
|
-
description: "Vendor-agnostic
|
|
3
|
+
description: "Vendor-agnostic scanner for Ready queues. Given a Notion PRD database URL → finds the first Ready PRD and runs lisa:plan. Given a Confluence space or parent page URL → finds the first prd-ready PRD and runs lisa:plan. Given a Linear workspace URL or team key → finds the first prd-ready Linear project and runs lisa:plan. Given a GitHub repo URL or `org/repo` token → finds the first prd-ready GitHub issue and runs lisa:plan. Given a JIRA project key or JQL filter → finds the first Ready ticket and runs lisa:implement. Given a GitHub repo URL or `org/repo` token when `tracker = github` → finds the first `status:ready` issue and runs lisa:implement. On the PRD side it also closes the loop: each cycle rolls a ticketed PRD up to shipped and dispatches lisa:verify-prd for one shipped PRD (shipped → verified on pass; on fail, re-opened shipped → ticketed with build-ready fix tickets that auto-build and re-verify — never blocked). Designed as the cron target for /schedule — one eligible item per invocation, exits cleanly on empty. Symmetric counterpart to the single-item lisa:plan and lisa:implement skills."
|
|
4
4
|
allowed-tools: ["Skill", "Bash", "mcp__claude_ai_Notion__notion-fetch", "mcp__claude_ai_Notion__notion-search", "mcp__atlassian__getConfluencePage", "mcp__atlassian__getConfluenceSpaces", "mcp__atlassian__searchConfluenceUsingCql", "mcp__atlassian__getAccessibleAtlassianResources", "mcp__atlassian__searchJiraIssuesUsingJql", "mcp__atlassian__getJiraIssue", "mcp__linear-server__list_projects", "mcp__linear-server__list_teams", "mcp__linear-server__list_project_labels"]
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Intake: $ARGUMENTS
|
|
8
8
|
|
|
9
|
-
Run one
|
|
9
|
+
Run one intake cycle against the queue identified by `$ARGUMENTS`. Scans for `Status = Ready`, claims the first eligible item, dispatches it to the appropriate single-item lifecycle skill, then exits. Remaining Ready items are left for later scheduler invocations.
|
|
10
10
|
|
|
11
11
|
## Confirmation policy
|
|
12
12
|
|
|
@@ -41,7 +41,7 @@ Until the team is established, the first Codex teammate has been spawned, or the
|
|
|
41
41
|
|
|
42
42
|
If you ARE already inside an agent team (e.g., a teammate invoked this skill via the Skill tool), do NOT create a second team — many harnesses reject double-creates. Continue within the existing team. The team lead created the team; teammates inherit it.
|
|
43
43
|
|
|
44
|
-
The cycle's outer team is created by Intake.
|
|
44
|
+
The cycle's outer team is created by Intake. The one item it processes (a PRD via `lisa:plan`, a ticket via `lisa:implement`) executes within that team — those skills' orchestration preambles detect the existing team and skip creating a second team. One team per cron cycle, one eligible Ready item per cycle.
|
|
45
45
|
|
|
46
46
|
## Source dispatch
|
|
47
47
|
|
|
@@ -49,16 +49,16 @@ Detect the queue type from `$ARGUMENTS` and route:
|
|
|
49
49
|
|
|
50
50
|
| If `$ARGUMENTS` is... | Queue type | Per-item dispatch |
|
|
51
51
|
|------------------------|------------|---------------------|
|
|
52
|
-
| A Notion **database** URL or database ID | PRD queue (Notion) | Invoke `lisa:notion-prd-intake` (which scans the DB for Status=Ready, claims
|
|
53
|
-
| A Confluence **space** URL or space key (e.g. `https://acme.atlassian.net/wiki/spaces/PRD` or `PRD`) | PRD queue (Confluence) | Invoke `lisa:confluence-prd-intake` (which CQL-queries the space for `label = "prd-ready"`, claims
|
|
52
|
+
| A Notion **database** URL or database ID | PRD queue (Notion) | Invoke `lisa:notion-prd-intake` (which scans the DB for Status=Ready, claims the first eligible PRD, runs `lisa:plan` via the dry-run validate → branch → write pipeline, then exits) |
|
|
53
|
+
| A Confluence **space** URL or space key (e.g. `https://acme.atlassian.net/wiki/spaces/PRD` or `PRD`) | PRD queue (Confluence) | Invoke `lisa:confluence-prd-intake` (which CQL-queries the space for `label = "prd-ready"`, claims the first eligible PRD by relabeling to `prd-in-review`, runs the dry-run validate → branch → write pipeline, then exits) |
|
|
54
54
|
| A Confluence **parent page** URL or page ID (the page whose descendants are PRDs) | PRD queue (Confluence, narrowed) | Invoke `lisa:confluence-prd-intake` with the parent ID (CQL: `ancestor = <id> AND label = "prd-ready"`) |
|
|
55
|
-
| A Linear **workspace** URL (e.g. `https://linear.app/acme`) | PRD queue (Linear) | Invoke `lisa:linear-prd-intake` (which queries `list_projects({label: "prd-ready"})` across the workspace, claims
|
|
55
|
+
| A Linear **workspace** URL (e.g. `https://linear.app/acme`) | PRD queue (Linear) | Invoke `lisa:linear-prd-intake` (which queries `list_projects({label: "prd-ready"})` across the workspace, claims the first eligible project by relabeling to `prd-in-review`, runs the dry-run validate → branch → write pipeline, then exits) |
|
|
56
56
|
| A Linear **team** URL (e.g. `https://linear.app/acme/team/ENG/projects`) or a token already routed as a Linear team key | PRD queue (Linear, narrowed) | Invoke `lisa:linear-prd-intake` with the team key (`list_projects({team, label: "prd-ready"})`) |
|
|
57
57
|
| The literal token `linear` | PRD queue (Linear, default workspace) | Invoke `lisa:linear-prd-intake linear` — only valid if `linear.workspace` is configured in `.lisa.config.json` |
|
|
58
|
-
| A JIRA project key (e.g. `SE`) | Work queue (JIRA) | Invoke `lisa:jira-build-intake` (which scans the project for Status=Ready, claims
|
|
58
|
+
| A JIRA project key (e.g. `SE`) | Work queue (JIRA) | Invoke `lisa:jira-build-intake` (which scans the project for Status=Ready, claims the first eligible ticket via In Progress, runs `lisa:implement`, transitions to On Dev on success, then exits) |
|
|
59
59
|
| A full JQL filter (e.g. `project = SE AND component = "frontend"`) | Work queue (JIRA, narrowed) | Invoke `lisa:jira-build-intake` with the JQL |
|
|
60
|
-
| A GitHub **repository** URL or `org/repo` token (e.g. `https://github.com/acme/product-prds` or `acme/product-prds`) when used for **PRDs** | PRD queue (GitHub) | Invoke `lisa:github-prd-intake` (which queries `gh issue list --label prd-ready`, claims
|
|
61
|
-
| A GitHub **repository** URL or `org/repo` token when `tracker = github` is configured (build-queue mode) | Work queue (GitHub) | Invoke `lisa:tracker-build-intake` which dispatches to `lisa:github-build-intake` (which queries `gh issue list --label status:ready`, claims via `status:in-progress`, runs `lisa:implement
|
|
60
|
+
| A GitHub **repository** URL or `org/repo` token (e.g. `https://github.com/acme/product-prds` or `acme/product-prds`) when used for **PRDs** | PRD queue (GitHub) | Invoke `lisa:github-prd-intake` (which queries `gh issue list --label prd-ready`, claims the first eligible PRD by relabeling to `prd-in-review`, runs the dry-run validate → branch → write pipeline, then exits). PRD discovery is independent of the destination tracker — the resulting tickets land wherever `.lisa.config.json` `tracker` says. |
|
|
61
|
+
| A GitHub **repository** URL or `org/repo` token when `tracker = github` is configured (build-queue mode) | Work queue (GitHub) | Invoke `lisa:tracker-build-intake` which dispatches to `lisa:github-build-intake` (which queries `gh issue list --label status:ready`, claims the first eligible issue via `status:in-progress`, runs `lisa:implement`, relabels to `status:on-dev` on success, then exits). |
|
|
62
62
|
| The literal token `github` | Defaults to `.lisa.config.json` `github.org` / `github.repo`. Routes by **the `intake_mode` flag** in `$ARGUMENTS` (`prd` or `build`); if the flag is absent, prefer the PRD queue when both label namespaces are present, otherwise pick whichever exists. | Invoke the matching skill (`lisa:github-prd-intake` or `lisa:tracker-build-intake`). |
|
|
63
63
|
|
|
64
64
|
Disambiguation rules:
|
|
@@ -81,15 +81,16 @@ The single-item skills (`lisa:plan`, `lisa:implement`) and the per-vendor batch
|
|
|
81
81
|
1. **Resolve the queue** — fetch the database/project metadata, confirm the Status property/workflow has the expected `Ready` value.
|
|
82
82
|
2. **Pre-flight check** — for JIRA, confirm `In Progress` and `On Dev` are reachable transitions before doing any per-ticket work. Stop with a clear error if the workflow is misconfigured.
|
|
83
83
|
3. **Find Ready items** — query the queue. Empty → exit cleanly with `"No items with Status=Ready. Nothing to do."` This is the common idle case for a scheduled run.
|
|
84
|
-
4. **Process
|
|
84
|
+
4. **Process the first eligible Ready item only** (claim-first ordering for idempotency):
|
|
85
85
|
- Notion PRDs → `lisa:notion-prd-intake` handles per-item: claim (Status=In Review), dry-run validate, branch to Blocked or Ticketed, coverage audit
|
|
86
86
|
- Confluence PRDs → `lisa:confluence-prd-intake` handles per-item: claim (relabel to `prd-in-review`), dry-run validate, branch to `prd-blocked` or `prd-ticketed`, coverage audit
|
|
87
87
|
- Linear PRDs → `lisa:linear-prd-intake` handles per-item: claim (relabel project to `prd-in-review`), dry-run validate, branch to `prd-blocked` or `prd-ticketed` (with a sentinel feedback issue under each project hosting clarifying-question comments), coverage audit
|
|
88
88
|
- GitHub PRDs → `lisa:github-prd-intake` handles per-item: claim (relabel issue to `prd-in-review`), dry-run validate, branch to `prd-blocked` or `prd-ticketed` (with clarifying-question comments posted directly on the PRD issue), coverage audit
|
|
89
89
|
- JIRA tickets → `lisa:jira-build-intake` handles per-item: claim, dispatch to `lisa:jira-agent`, transition to On Dev on success
|
|
90
90
|
- GitHub build issues (when `tracker = github`) → `lisa:tracker-build-intake` → `lisa:github-build-intake` handles per-item: claim (relabel to `status:in-progress`), dispatch to `lisa:github-agent`, relabel to `status:on-dev` on success
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
- **Closing the PRD loop:** beyond claiming one Ready PRD, every PRD scanner also runs the closure rollup (`ticketed → shipped`, Phase 3f) and **dispatches `lisa:verify-prd` for one shipped PRD** (Phase 3g) each cycle — so a shipped PRD does not sit unverified. On pass the PRD goes `shipped → verified`; on fail it is re-opened `shipped → ticketed` with **build-ready fix tickets** that auto-build and trigger a re-verify (never `blocked`). The scanner only dispatches; `lisa:verify-prd` owns the transition (per the `prd-lifecycle-rollup` rule's "Closing the loop" section), and the self-healing loop continues until the PRD verifies.
|
|
92
|
+
5. **Stop after one item** — a claimed Ready item, a safe-blocked container, or a per-item error ends the *ready-claim* portion of the cycle. The per-vendor PRD scanner still runs its rollup and one verify-prd dispatch. Remaining Ready items stay untouched for later scheduler invocations.
|
|
93
|
+
6. **Summary report** — the single processed/skipped/error item, total processed, total errors.
|
|
93
94
|
|
|
94
95
|
## Schedule examples
|
|
95
96
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: jira-build-intake
|
|
3
|
-
description: "Symmetric counterpart to notion-prd-intake on the JIRA side. Scans a JIRA project (or JQL filter) for tickets in the configured `ready` status, claims
|
|
3
|
+
description: "Symmetric counterpart to notion-prd-intake on the JIRA side. Scans a JIRA project (or JQL filter) for tickets in the configured `ready` status, claims the first eligible ticket by transitioning to the configured `claimed` status, runs the implementation/build flow via jira-agent, transitions to the configured `done` status on completion, then exits. Enforces the claim-time arm of the `leaf-only-lifecycle` rule: a parent/container with open child work (or a childless Epic/Story/Spike) that still carries a stale build-ready status is skipped or safe-blocked with a lifecycle-repair comment, never claimed. The `ready` status is the human-flipped signal that a TODO ticket is truly ready for development — mirroring how Notion PRDs work product Draft → Ready → (us) In Review → Blocked|Ticketed."
|
|
4
4
|
allowed-tools: ["Skill", "Bash"]
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -13,7 +13,7 @@ All Atlassian operations in this skill go through `lisa:atlassian-access`. Do no
|
|
|
13
13
|
1. A JIRA project key (e.g. `SE`) — scans that project for tickets in the configured `ready` status.
|
|
14
14
|
2. A full JQL filter (e.g. `project = SE AND component = "frontend" AND Status = Ready`) — used as-is. The skill will not append a `Status = <ready>` clause if the JQL already names a status, so callers can intentionally widen.
|
|
15
15
|
|
|
16
|
-
Run one build-intake cycle.
|
|
16
|
+
Run one build-intake cycle. The first eligible ready ticket is claimed, built via the `lisa:jira-agent` flow, transitioned to the configured `done` status (env-aware — see below), then the cycle exits. Remaining ready tickets stay queued for later scheduler invocations.
|
|
17
17
|
|
|
18
18
|
## Workflow resolution
|
|
19
19
|
|
|
@@ -68,11 +68,11 @@ else
|
|
|
68
68
|
fi
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
Run one build-intake cycle.
|
|
71
|
+
Run one build-intake cycle. The first eligible ticket in `$READY` is claimed by transitioning to `$CLAIMED`, built via the `lisa:jira-agent` flow, transitioned to `$DONE` on completion, then the cycle exits.
|
|
72
72
|
|
|
73
73
|
## Confirmation policy
|
|
74
74
|
|
|
75
|
-
Do NOT ask the caller whether to proceed. Once invoked with a project key or JQL, run the cycle to completion — claim
|
|
75
|
+
Do NOT ask the caller whether to proceed. Once invoked with a project key or JQL, run the cycle to completion — claim and dispatch the first eligible ticket through `lisa:jira-agent`, transition a successful build to `$DONE`, write the summary, and exit. The caller (a human or a cron) has already authorized the run by invoking the skill; re-prompting defeats the purpose of a background queue.
|
|
76
76
|
|
|
77
77
|
Specifically forbidden:
|
|
78
78
|
|
|
@@ -116,13 +116,26 @@ Invoke `lisa:atlassian-access` `operation: search-issues jql: "<JQL>"`. Capture
|
|
|
116
116
|
|
|
117
117
|
If empty, report `"No tickets with Status=$READY. Nothing to do."` and exit. This is the common idle case.
|
|
118
118
|
|
|
119
|
-
### Phase 3 — Process
|
|
119
|
+
### Phase 3 — Process the first eligible ready ticket
|
|
120
|
+
|
|
121
|
+
#### 3a.0 Repo-scope gate (claim only current-repo tickets)
|
|
122
|
+
|
|
123
|
+
A JIRA project can oversee multiple repos (`frontend` / `backend` / `infrastructure`). This skill claims only tickets for the repo it is running in. Run this gate **before** the leaf-only gate (3a) and the claim (3b), per the `repo-scope-split` rule's "Claim-time repo scoping" section (cite it by slug; do not restate its decision table).
|
|
124
|
+
|
|
125
|
+
1. **Resolve the current repo** per `config-resolution` "Repo scoping" (`.repo` → `.github.repo` → `git remote get-url origin` basename). If unresolvable, stop and report — do not claim tickets you cannot scope.
|
|
126
|
+
2. **Cheap path first.** Prefer candidates already carrying `repo:<current>` — a JIRA **label**, or a **component** equal to the repo name (accepted as an alias). Keep the Phase 2 scan broad (it must still see unlabeled tickets so they can be determined and stamped); this gate orders/filters the results.
|
|
127
|
+
3. **Per candidate, apply the repo-scope decision (`repo-scope-split`):**
|
|
128
|
+
- Carries `repo:<other>` (label or component) → **skip** (leave it `ready` for that repo's own intake); next candidate.
|
|
129
|
+
- **Unlabeled** → determine the target repo(s) from the ticket (description, AC, technical approach) confirmed against the code surfaces, then **stamp** `repo:<name>` via `lisa:atlassian-access` `operation: write-ticket` (add the label / set the component) so later cycles filter cheaply; re-apply with the now-known repo.
|
|
130
|
+
- **Multi-repo leaf → split, never claim.** Run the `repo-scope-split` work-time procedure to break it into single-repo siblings, each created **build-ready** (`build_ready: true`) and stamped with its own `repo:<name>`; the current repo's sibling becomes a normal candidate.
|
|
131
|
+
- **Single-repo leaf for the current repo** → fall through to 3a (leaf-only gate) and 3b (claim).
|
|
132
|
+
4. Continue until a claimable current-repo leaf is found (claim it; one per cycle) or the ready set is exhausted — exit cleanly with `"No ready tickets for repo <current>. Nothing to do."`.
|
|
120
133
|
|
|
121
134
|
#### 3a. Leaf-only claim gate (skip / safe-block containers)
|
|
122
135
|
|
|
123
136
|
Build intake claims **only independently implementable leaf work units**. This enforces the claim-time arm of the vendor-neutral `leaf-only-lifecycle` rule: a parent/container that still carries a stale build-ready status (e.g. `Ready` applied before this rule existed, or hand-applied to an Epic/Story) is **never claimed** — intake skips it or safe-blocks it with a clear lifecycle-repair message. It is the claim-time complement to the write-time labeling in `lisa:jira-write-ticket` and the validate-time S15 gate in `lisa:jira-validate-ticket`; all three cite the same rule so the classification never drifts. **Never silently implement a container.**
|
|
124
137
|
|
|
125
|
-
Run this gate **before** the claim transition,
|
|
138
|
+
Run this gate **before** the claim transition, starting with the oldest/highest-priority ready candidate. Do NOT transition, comment "Claimed", or invoke `lisa:jira-agent` for a ticket that fails the gate.
|
|
126
139
|
|
|
127
140
|
**Resolve container vs. leaf — structural first, then nominal.** Per `leaf-only-lifecycle` the classification is structural: a ticket is a **container** if it has **open** child work, whatever its declared type; otherwise the **issue type** decides. Resolve child work using the same hierarchy `lisa:jira-read-ticket` uses — JIRA's native Epic → Story → Sub-task parentage (Epic link / parent field for Stories under an Epic, and the subtask relationship for Sub-tasks under a Story/Task). Issue links (`blocks` / `is blocked by`) express cross-item dependencies and are **not** parentage — do not count them as children.
|
|
128
141
|
|
|
@@ -151,7 +164,7 @@ Classify and act (first match wins). The issue type comes from the ticket's `iss
|
|
|
151
164
|
|
|
152
165
|
The childless-parent exception is narrow: childlessness enables a claim **only** for types that are leaf work units to begin with. A childless Epic/Story/Spike is an incomplete decomposition, not an implementable unit — it is never claimed.
|
|
153
166
|
|
|
154
|
-
**Safe-block (default action for a flagged container).** Leave the build-ready status in place (don't silently transition it away — that hides the lifecycle error), post a single lifecycle-repair comment,
|
|
167
|
+
**Safe-block (default action for a flagged container).** Leave the build-ready status in place (don't silently transition it away — that hides the lifecycle error), post a single lifecycle-repair comment, record the ticket under "Skipped (container)" in the summary, and end the cycle. Do NOT transition to `$CLAIMED`. Keep the comment idempotent — skip posting if an identical `[claude-build-intake]` lifecycle-repair comment already exists on the ticket, so a re-entrant cycle doesn't spam it.
|
|
155
168
|
|
|
156
169
|
Post via `lisa:atlassian-access` `operation: comment key: <TICKET> body: "<message>"` with:
|
|
157
170
|
|
|
@@ -199,9 +212,9 @@ If `lisa:jira-agent` returned Success:
|
|
|
199
212
|
|
|
200
213
|
For any non-Success outcome, do NOT transition. The ticket sits in `$CLAIMED` (or wherever `lisa:jira-agent` left it for the Blocked case) — the cycle's job is done; humans take it from there.
|
|
201
214
|
|
|
202
|
-
#### 3e.
|
|
215
|
+
#### 3e. Stop
|
|
203
216
|
|
|
204
|
-
|
|
217
|
+
Stop immediately after the first claimed, skipped, blocked, held, or errored ticket. Later scheduler invocations process the remaining ready tickets.
|
|
205
218
|
|
|
206
219
|
### Phase 4 — Summary report
|
|
207
220
|
|
|
@@ -233,8 +246,8 @@ Total PRs opened: <n>
|
|
|
233
246
|
- **Claim-first ordering**: `$CLAIMED` set BEFORE `lisa:jira-agent` invocation — no double-pickup.
|
|
234
247
|
- **No writes outside the lifecycle**: this skill only transitions `$READY → $CLAIMED` and `$CLAIMED → $DONE`, then verifies terminal native resolution when `$DONE` is the true terminal state per `leaf-only-lifecycle`. Every other status change is owned by `lisa:jira-agent` (which suggests transitions but only auto-transitions on the verify-FAIL path).
|
|
235
248
|
- **Terminal native closure**: for terminal `$DONE`, the resulting JIRA issue must be in a resolved / closed state (`statusCategory = Done` and resolution set when required). Intermediate env statuses stay unresolved / open.
|
|
236
|
-
- **
|
|
237
|
-
- **Single cycle per query**: do not run two `lisa:jira-build-intake` cycles
|
|
249
|
+
- **One item per cycle**: per-ticket exceptions are caught and recorded, then the cycle exits. The scheduler owns retrying or moving on to the next ready item.
|
|
250
|
+
- **Single cycle per query**: do not run two `lisa:jira-build-intake` cycles concurrently against overlapping queries — concurrent claims could race. The scheduling layer (when added) is responsible for serialization.
|
|
238
251
|
- **Never invent a transition**: if `$CLAIMED` or `$DONE` aren't valid transitions in the project's workflow, stop and report rather than guessing alternative names.
|
|
239
252
|
|
|
240
253
|
## Configuration
|
|
@@ -200,6 +200,13 @@ Before create/update, verify each field is populated where applicable:
|
|
|
200
200
|
- Sprint: only if actively sprinting this work
|
|
201
201
|
- Assignee: leave unset if unknown rather than auto-assigning
|
|
202
202
|
|
|
203
|
+
### Build-ready control input (`build_ready`)
|
|
204
|
+
|
|
205
|
+
`build_ready` is an optional write-control input (default: **omitted**). It governs whether a **leaf** work unit is promoted to the build-ready role on create. It never overrides `leaf-only-lifecycle` — a container is never promoted regardless of `build_ready`. Unlike the label-based trackers, JIRA tickets are **already created not-ready** (in the project's default initial status, e.g. `TODO`/`Backlog`); the build-ready role is the configured `ready` status (`jira.workflow.ready`, default `Ready`), reached by an explicit transition.
|
|
206
|
+
|
|
207
|
+
- **Omitted** or **`build_ready: false`** → current behavior: leave the ticket in the project's default created status. No transition. A human (or `build_ready: true`) promotes it to the `ready` status later.
|
|
208
|
+
- **`build_ready: true`** → after create, transition the **leaf** to the resolved `ready` role so `lisa:intake` / `lisa:jira-build-intake` auto-picks it up (see Phase 6 CREATE step). Resolve the role name with the standard pattern (`.jira.workflow.ready` // `Ready`, local overrides global). Best-effort: if the transition is unreachable, record it and leave the ticket in its default status rather than failing the write.
|
|
209
|
+
|
|
203
210
|
## Phase 5.5 — Validate (Pre-write Gate)
|
|
204
211
|
|
|
205
212
|
Before any write, invoke `lisa:jira-validate-ticket` with the full proposed spec assembled from Phases 2 / 3 / 4 / 5. Pass it as a YAML block per the `lisa:jira-validate-ticket` schema, including `runtime_behavior_change`, `authenticated_surface`, and `artifacts_attached` flags so the right gates run.
|
|
@@ -222,6 +229,7 @@ If the validator reports `PASS`, continue to Phase 6.
|
|
|
222
229
|
3. For each relationship from Phase 4b, invoke `lisa:atlassian-access` with `operation: link from: <K1> to: <K2> type: "<link-type>"`. Use the exact link-type names supported by the project; surface errors if an unknown type is passed.
|
|
223
230
|
4. Attach remote links from Phase 4c (via `lisa:atlassian-access` `operation: write-ticket` UPDATE form or whatever remote-link operation is dispatched).
|
|
224
231
|
5. If the ticket changes runtime behavior, invoke the `lisa:jira-add-journey` skill to append the Validation Journey section.
|
|
232
|
+
6. **Build-ready promotion (only when `build_ready: true` and the ticket is a leaf work unit):** transition the new ticket to the resolved `ready` status via `lisa:atlassian-access` `operation: transition key: <K> to: "<ready-status>"` (resolve `<ready-status>` as `.jira.workflow.ready` // `Ready`, local overrides global). Skip this step entirely when `build_ready` is omitted or `false`, or for any container. If the transition is unreachable, record it and leave the ticket in its default status — do not fail the write.
|
|
225
233
|
|
|
226
234
|
### UPDATE
|
|
227
235
|
|