@codyswann/lisa 2.61.0 → 2.61.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/package.json +1 -1
  2. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  3. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  4. package/plugins/lisa/agents/github-agent.md +4 -5
  5. package/plugins/lisa/agents/github-build-intake.md +1 -1
  6. package/plugins/lisa/rules/config-resolution.md +3 -4
  7. package/plugins/lisa/rules/leaf-only-lifecycle.md +1 -1
  8. package/plugins/lisa/skills/confluence-prd-intake/SKILL.md +13 -13
  9. package/plugins/lisa/skills/confluence-prd-intake/agents/openai.yaml +2 -2
  10. package/plugins/lisa/skills/github-build-intake/SKILL.md +19 -21
  11. package/plugins/lisa/skills/github-evidence/SKILL.md +3 -26
  12. package/plugins/lisa/skills/github-evidence/agents/openai.yaml +2 -2
  13. package/plugins/lisa/skills/github-journey/SKILL.md +2 -2
  14. package/plugins/lisa/skills/github-prd-intake/SKILL.md +10 -10
  15. package/plugins/lisa/skills/github-prd-intake/agents/openai.yaml +2 -2
  16. package/plugins/lisa/skills/github-sync/SKILL.md +5 -5
  17. package/plugins/lisa/skills/github-write-issue/SKILL.md +2 -2
  18. package/plugins/lisa/skills/intake/SKILL.md +12 -12
  19. package/plugins/lisa/skills/intake/agents/openai.yaml +2 -2
  20. package/plugins/lisa/skills/jira-build-intake/SKILL.md +11 -11
  21. package/plugins/lisa/skills/linear-build-intake/SKILL.md +9 -9
  22. package/plugins/lisa/skills/linear-prd-intake/SKILL.md +12 -12
  23. package/plugins/lisa/skills/linear-prd-intake/agents/openai.yaml +2 -2
  24. package/plugins/lisa/skills/notion-prd-intake/SKILL.md +11 -11
  25. package/plugins/lisa/skills/notion-prd-intake/agents/openai.yaml +2 -2
  26. package/plugins/lisa/skills/setup-github/SKILL.md +0 -1
  27. package/plugins/lisa/skills/tracker-build-intake/SKILL.md +2 -2
  28. package/plugins/lisa/skills/tracker-build-intake/agents/openai.yaml +2 -2
  29. package/plugins/lisa/skills/tracker-evidence/SKILL.md +2 -2
  30. package/plugins/lisa/skills/tracker-sync/SKILL.md +1 -1
  31. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  32. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  33. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  34. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  35. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  37. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  38. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  39. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  41. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  43. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  44. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  45. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  47. package/plugins/src/base/agents/github-agent.md +4 -5
  48. package/plugins/src/base/agents/github-build-intake.md +1 -1
  49. package/plugins/src/base/rules/config-resolution.md +3 -4
  50. package/plugins/src/base/rules/leaf-only-lifecycle.md +1 -1
  51. package/plugins/src/base/skills/confluence-prd-intake/SKILL.md +13 -13
  52. package/plugins/src/base/skills/github-build-intake/SKILL.md +19 -21
  53. package/plugins/src/base/skills/github-evidence/SKILL.md +3 -26
  54. package/plugins/src/base/skills/github-journey/SKILL.md +2 -2
  55. package/plugins/src/base/skills/github-prd-intake/SKILL.md +10 -10
  56. package/plugins/src/base/skills/github-sync/SKILL.md +5 -5
  57. package/plugins/src/base/skills/github-write-issue/SKILL.md +2 -2
  58. package/plugins/src/base/skills/intake/SKILL.md +12 -12
  59. package/plugins/src/base/skills/jira-build-intake/SKILL.md +11 -11
  60. package/plugins/src/base/skills/linear-build-intake/SKILL.md +9 -9
  61. package/plugins/src/base/skills/linear-prd-intake/SKILL.md +12 -12
  62. package/plugins/src/base/skills/notion-prd-intake/SKILL.md +11 -11
  63. package/plugins/src/base/skills/setup-github/SKILL.md +0 -1
  64. package/plugins/src/base/skills/tracker-build-intake/SKILL.md +2 -2
  65. package/plugins/src/base/skills/tracker-evidence/SKILL.md +2 -2
  66. package/plugins/src/base/skills/tracker-sync/SKILL.md +1 -1
package/package.json CHANGED
@@ -82,7 +82,7 @@
82
82
  "lodash": ">=4.18.1"
83
83
  },
84
84
  "name": "@codyswann/lisa",
85
- "version": "2.61.0",
85
+ "version": "2.61.1",
86
86
  "description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
87
87
  "main": "dist/index.js",
88
88
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.61.0",
3
+ "version": "2.61.1",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.61.0",
3
+ "version": "2.61.1",
4
4
  "description": "Universal governance: agents, skills, commands, hooks, and rules for all projects.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -49,7 +49,7 @@ Use the `github-verify` skill to check the issue against organizational standard
49
49
 
50
50
  **Gating behavior — this is the one place auto-relabeling is allowed:**
51
51
 
52
- Resolve build labels from `.lisa.config.json` `github.labels.build.*` (defaults: `status:ready` / `status:in-progress` / `status:code-review` / env-keyed `status:on-*`); resolve the `blocked` label from the same section (`github.labels.build.blocked`, default `status:blocked`).
52
+ Resolve build labels from `.lisa.config.json` `github.labels.build.*` (defaults: `status:ready` / `status:in-progress` / env-keyed `status:on-*`); resolve the `blocked` label from the same section (`github.labels.build.blocked`, default `status:blocked`).
53
53
 
54
54
  If `github-verify` returns `FAIL` on any of the above, do NOT continue:
55
55
 
@@ -126,7 +126,6 @@ Use the `github-evidence` skill to:
126
126
  - Upload verification evidence to the GitHub `pr-assets` release (in the implementation repo)
127
127
  - Update the PR description's `## Evidence` section
128
128
  - Post a comment on the originating issue with the evidence summary
129
- - Relabel the issue from the `claimed` label to the `review` label (configured via `github.labels.build.{claimed,review}`)
130
129
 
131
130
  ### 8. Suggest Status Transition
132
131
 
@@ -135,14 +134,14 @@ Based on the milestone, suggest (but don't auto-relabel beyond the explicit Step
135
134
  | Milestone | Suggested role | Default label |
136
135
  |-----------|----------------|---------------|
137
136
  | Plan created | `claimed` | `status:in-progress` |
138
- | PR ready | `review` (Step 7 sets this) | `status:code-review` |
139
- | PR merged | `done` (env-aware) | env-keyed variant per `github.labels.build.done` |
137
+ | PR ready | `done` (env-aware; build-intake sets this after success) | env-keyed variant per `github.labels.build.done` |
138
+ | PR merged | no additional build-label transition | already at configured `done` |
140
139
 
141
140
  Note: `done` may be a string or an env-keyed map (`{ dev, staging, production }`). When suggesting the PR-merged transition, the env is implied by the PR's base branch via `deploy.branches` — surface the resolved label name; do not auto-transition.
142
141
 
143
142
  ## Rules
144
143
 
145
- - Never auto-relabel build labels, with two explicit exceptions: (a) when `github-verify` returns FAIL for the pre-flight gate (Step 2), relabel to the configured `blocked` label and reassign to the original author; (b) when `github-evidence` runs at completion (Step 7), relabel to the configured `review` label. Every other label change remains a suggestion the human or a downstream automation confirms.
144
+ - Never auto-relabel build labels, with one explicit exception: when `github-verify` returns FAIL for the pre-flight gate (Step 2), relabel to the configured `blocked` label and reassign to the original author. The build-intake owner transitions a successful issue from `claimed` directly to the configured `done` label after PR evidence is posted.
146
145
  - Always read the full issue graph via `github-read-issue` before determining intent — don't rely on the `type:` label alone.
147
146
  - Never create or materially edit an issue by calling `gh issue create` / `gh issue edit` directly — always delegate to `github-write-issue` (or, from a vendor-neutral caller, `tracker-write`) so relationships, Gherkin criteria, and metadata gates are enforced.
148
147
  - If sign-in credentials are in the issue body, extract and pass them to the flow. If the issue touches an authenticated surface and credentials are missing, that is a Step 2 failure — block and reassign rather than guessing.
@@ -17,7 +17,7 @@ skills:
17
17
 
18
18
  You are a GitHub build-intake agent. Your single job is to run one cycle against a GitHub repo — find issues carrying the configured `ready` build label, dispatch each through the build flow, relabel successful builds to the configured (env-aware) `done` label — then report what happened.
19
19
 
20
- Build-label role names (`ready`, `claimed`, `review`, `done`) are resolved from `.lisa.config.json` `github.labels.build.*` by the `github-build-intake` skill. The defaults match the legacy hardcoded names (`status:ready`, `status:in-progress`, `status:code-review`, env-keyed `{ dev: status:on-dev, staging: status:on-stg, production: status:done }`).
20
+ Build-label role names (`ready`, `claimed`, `done`) are resolved from `.lisa.config.json` `github.labels.build.*` by the `github-build-intake` skill. The defaults are `status:ready`, `status:in-progress`, and env-keyed `{ dev: status:on-dev, staging: status:on-stg, production: status:done }`.
21
21
 
22
22
  ## Confirmation policy
23
23
 
@@ -68,7 +68,6 @@ fi
68
68
  "build": {
69
69
  "ready": "status:ready",
70
70
  "claimed": "status:in-progress",
71
- "review": "status:code-review",
72
71
  "blocked": "status:blocked",
73
72
  "done": { "dev": "status:on-dev", "staging": "status:on-stg", "production": "status:done" }
74
73
  },
@@ -194,11 +193,11 @@ Every lifecycle skill operates on a fixed set of **roles** (`ready`, `claimed`,
194
193
  |---|---|---|---|
195
194
  | `ready` | Human signal "this is buildable; agent may claim" | `Ready` (status) | `status:ready` (label) |
196
195
  | `claimed` | Agent has picked the item up | `In Progress` (status) | `status:in-progress` (label) |
197
- | `review` | Build complete, in code review | `Code Review` (status) | `status:code-review` (label) |
196
+ | `review` | Optional post-build review hold, when a tracker/project still uses one | `Code Review` (status) | Linear default: `status:code-review`; GitHub has no default review label |
198
197
  | `blocked` | Agent stopped on triage ambiguities or external blocker | `Blocked` (status) | `status:blocked` (label) |
199
198
  | `done` | Terminal state for this work, **env-keyed** | map of env → status | map of env → label |
200
199
 
201
- `review` is required for label-driven systems (GitHub, Linear) because that's how the agent signals "PR opened, awaiting human review." For JIRA, `review` is optional projects that keep the ticket in `claimed` until terminal can omit it and lifecycle skills will skip the intermediate transition.
200
+ `review` is optional. GitHub build intake skips it by default and moves successful builds directly from `claimed` to the configured `done` label. Linear and JIRA projects that still use a post-build review hold can configure `review`; projects that keep the ticket in `claimed` until terminal can omit it and lifecycle skills will skip the intermediate transition.
202
201
 
203
202
  `blocked` is what every vendor agent flips to when triage finds unresolved ambiguities or the build path is blocked by something the agent can't resolve. Different from `claimed` because it explicitly signals "human attention required."
204
203
 
@@ -328,7 +327,7 @@ Initiatives (Linear's cross-Project rollup) are NOT used — they're intended fo
328
327
  When `github-to-tracker` is invoked AND `tracker = "github"`, both reads and writes hit the same GitHub repo. Label namespaces are kept separate so the two flows don't collide:
329
328
 
330
329
  - PRD-source labels: `prd-draft`, `prd-ready`, `prd-in-review`, `prd-blocked`, `prd-ticketed`, `prd-shipped`, `prd-verified` — owned by `github-prd-intake`, `verify-prd`, and the human PM.
331
- - Build-queue labels: `status:ready`, `status:in-progress`, `status:code-review`, `status:on-dev`, `status:done` — owned by `github-build-intake` and `github-agent`.
330
+ - Build-queue labels: `status:ready`, `status:in-progress`, `status:on-dev`, `status:done` — owned by `github-build-intake` and `github-agent`.
332
331
  - Sentinel issue label: `prd-intake-feedback` — owned by `github-prd-intake`.
333
332
 
334
333
  Never overload one label across both lifecycles.
@@ -81,7 +81,7 @@ Notes:
81
81
 
82
82
  The terminal rollup state is whatever the project configures for `done` — which is **env-keyed** (`config-resolution` "Env-keyed `done`"): a `done` map keyed by environment (`dev`, `staging`, `production`), resolved from the 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. A downstream project with dev/staging/prod environments rolls a parent up to whichever terminal `done` value matches the environment its leaves shipped to. The rule stays generic and multi-env capable.
83
83
 
84
- **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, and the build lifecycle collapses to one chain: `ready → claimed (in-progress) → review (code-review) → 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.
84
+ **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.
85
85
 
86
86
  ## Terminal native closure
87
87
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: confluence-prd-intake
3
- description: "Scans a Confluence space (or a parent page) for PRD pages currently parented under the configured `ready` lifecycle page and runs each one through the dry-run validation pipeline. PRDs that pass every gate get tickets written and are re-parented under the `ticketed` lifecycle page; PRDs that fail get clarifying-question comments and are re-parented under the `blocked` lifecycle page. Confluence counterpart of `lisa:notion-prd-intake` — the workflow is identical; only the source-of-truth tools and the state encoding differ (parent-page re-parenting instead of a status property). Composes existing skills (confluence-to-tracker, tracker-validate, tracker-source-artifacts, product-walkthrough)."
3
+ description: "Scans a Confluence space (or a parent page) for PRD pages currently parented under the configured `ready` lifecycle page and runs the first eligible one through the dry-run validation pipeline. A PRD that passes every gate gets tickets written and is re-parented under the `ticketed` lifecycle page; a PRD that fails gets clarifying-question comments and is re-parented under the `blocked` lifecycle page. Confluence counterpart of `lisa:notion-prd-intake` — the workflow is identical; only the source-of-truth tools and the state encoding differ (parent-page re-parenting instead of a status property). Composes existing skills (confluence-to-tracker, tracker-validate, tracker-source-artifacts, product-walkthrough)."
4
4
  allowed-tools: ["Skill", "Bash"]
5
5
  ---
6
6
 
@@ -11,10 +11,10 @@ All Atlassian operations in this skill go through `lisa:atlassian-access`. Do no
11
11
  `$ARGUMENTS` is one of:
12
12
 
13
13
  - A Confluence **space** URL or space key — used as the surrounding scope sanity check. Example: `https://mycompany.atlassian.net/wiki/spaces/PRD` or `PRD`.
14
- - A Confluence **parent page** URL or page ID — overrides the configured `confluence.parents.ready` page for this run (useful when an operator wants to drain an alternative lifecycle parent). Example: `https://mycompany.atlassian.net/wiki/spaces/PRD/pages/123456789/PRDs`.
14
+ - A Confluence **parent page** URL or page ID — overrides the configured `confluence.parents.ready` page for this run (useful when an operator wants to target an alternative lifecycle parent). Example: `https://mycompany.atlassian.net/wiki/spaces/PRD/pages/123456789/PRDs`.
15
15
  - Empty — use `confluence.parents.ready` from `.lisa.config.json` as the scope.
16
16
 
17
- Run one intake cycle against the resolved `ready` lifecycle parent. Each direct child of that parent is treated as a PRD currently in the `ready` state. Each PRD is claimed (re-parented to `in_review`), validated, and routed to either the `blocked` parent (with clarifying comments) or the `ticketed` parent (with destination tickets created).
17
+ Run one intake cycle against the resolved `ready` lifecycle parent. Each direct child of that parent is treated as a PRD currently in the `ready` state. The first eligible PRD is claimed (re-parented to `in_review`), validated, routed to either the `blocked` parent (with clarifying comments) or the `ticketed` parent (with destination tickets created), then the cycle exits. Remaining ready PRDs stay queued for later scheduler invocations.
18
18
 
19
19
  ## Why parent pages, not labels
20
20
 
@@ -82,7 +82,7 @@ The **PRD closure rollup phase (3f)** re-parents a `ticketed` PRD to the `shippe
82
82
 
83
83
  ## Confirmation policy
84
84
 
85
- Do NOT ask the caller whether to proceed. Once invoked, run the cycle to completion — claim, validate, branch to the `blocked` or `ticketed` parent, write the summary. The caller (a human or a cron) has already authorized the run by invoking the skill; re-prompting defeats the purpose of a background batch.
85
+ Do NOT ask the caller whether to proceed. Once invoked, run the cycle to completion for the first eligible PRD — claim, validate, branch to the `blocked` or `ticketed` parent, 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.
86
86
 
87
87
  Specifically forbidden:
88
88
 
@@ -151,9 +151,9 @@ If the result set is empty, run a sanity probe across the other lifecycle parent
151
151
  - If every lifecycle parent has zero direct children → the lifecycle scaffolding is provisioned but unused, OR PRDs are still parented under the legacy structure. Surface: `"No PRDs found under any of the configured lifecycle parent pages (ready, in_review, blocked, ticketed). If this is a new project, move PRDs that are ready for ticketing under the configured 'ready' parent page (see Adoption section)."` Exit with an error — this is a setup / migration issue, not a normal idle cycle.
152
152
  - If any non-ready parent has children → the queue is genuinely empty (PRDs exist but are in `in_review`, `blocked`, `ticketed`, or `shipped`). Exit cleanly with `"No PRDs currently parented under the 'ready' lifecycle page. Nothing to do."`
153
153
 
154
- ### Phase 3 — Process each ready PRD
154
+ ### Phase 3 — Process the first eligible ready PRD
155
155
 
156
- For each PRD page (process serially to keep transitions auditable):
156
+ Select the first ready PRD page returned by Phase 2 and process only that page. Later scheduler invocations process the remaining ready PRDs.
157
157
 
158
158
  #### 3a. Claim
159
159
 
@@ -277,9 +277,9 @@ Use these exact badge labels — they are the validator's category values transl
277
277
 
278
278
  After all comments are posted (anchored groups + the optional footer summary), re-parent the PRD to the `blocked` lifecycle parent: `transition_prd "$PRD_ID" blocked`. Do NOT write any destination tickets.
279
279
 
280
- #### 3d. Continue
280
+ #### 3d. Stop
281
281
 
282
- Move to the next ready PRD. One PRD failing does not affect others.
282
+ Stop immediately after the claimed PRD is ticketed, blocked, or recorded as an error.
283
283
 
284
284
  #### 3e. Coverage audit (mandatory after re-parenting to `ticketed`)
285
285
 
@@ -290,7 +290,7 @@ Per-ticket gates prove each ticket is well-formed; they do NOT prove the *set* o
290
290
 
291
291
  | Verdict | Action |
292
292
  |---------|--------|
293
- | `COMPLETE` | Done. Leave PRD under `ticketed` parent. Move to next PRD. |
293
+ | `COMPLETE` | Done. Leave PRD under `ticketed` parent. End the cycle. |
294
294
  | `COMPLETE_WITH_SCOPE_CREEP` | Post an advisory footer comment naming the scope-creep tickets (so product can decide whether to close them as out-of-scope). Leave PRD under `ticketed` parent. |
295
295
  | `GAPS_FOUND` | The created ticket set is incomplete. (a) For each gap, post a comment using the same product-facing template as Phase 3c.3 — inline-anchored when `prd_anchor` is non-null, footer otherwise; category badge from the gap's `category` field; `What's unclear` and `Recommendation` from the audit report's `what` and `recommendation` fields. Apply the same forbidden-language rules from Phase 3c.5. (b) Post one footer summary comment listing the tickets that *were* successfully created (so product knows what to keep vs. what to extend). (c) Re-parent the PRD from `ticketed` back to `blocked`: `transition_prd "$PRD_ID" blocked`. |
296
296
  | `NO_TICKETS_FOUND` | Should not happen if step 2 succeeded. If it does, log it as an Error in the cycle summary and leave the PRD under `ticketed` with a comment flagging the audit failure for human review. |
@@ -354,7 +354,7 @@ This phase implements exactly one PRD-lifecycle hop — `ticketed → shipped`
354
354
 
355
355
  ### Phase 4 — Summary report
356
356
 
357
- After processing every ready PRD, emit a summary:
357
+ After processing the single selected PRD, emit a summary:
358
358
 
359
359
  ```text
360
360
  ## confluence-prd-intake summary
@@ -379,10 +379,10 @@ Print to the agent's output. Do not write this summary to Confluence or the dest
379
379
 
380
380
  ## Idempotency & safety
381
381
 
382
- - **Single-cycle scope**: this skill processes the ready set as it exists at the start of Phase 2. New PRDs moved under the `ready` parent mid-cycle are picked up next run.
382
+ - **One item per cycle**: this skill processes the first eligible ready PRD from Phase 2, then exits. New or remaining PRDs under the `ready` parent are picked up by later scheduler invocations.
383
383
  - **No writes outside the lifecycle**: this skill only ever writes to the destination tracker via `lisa:confluence-to-tracker` (which delegates to `lisa:tracker-write`), and only ever re-parents PRDs among `in_review`, `blocked`, `ticketed`, and `shipped` (the last via the rollup phase 3f only) via `lisa:atlassian-access` `operation: write-page`. It never edits PRD body content, never re-parents into or out of `draft`, never deletes pages. It re-parents under `shipped` and may archive the PRD page **only** through the config-gated rollup phase (3f).
384
384
  - **Claim-first ordering**: the re-parent to `in_review` happens BEFORE validation runs, so a re-entrant call won't double-process.
385
- - **Failure isolation**: an exception processing one PRD must not stop the cycle. Catch, record under "Errors" in the summary, continue to the next PRD. The PRD that errored is left under whatever parent it currently occupies (usually `in_review` if claim succeeded) — the human investigates from there.
385
+ - **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 under whatever parent it currently occupies (usually `in_review` if claim succeeded) — the human investigates from there.
386
386
  - **Single-parent invariant**: a page has exactly one parent by construction in Confluence — the multi-state ambiguity that label-based systems can hit (two `prd-*` labels simultaneously) cannot occur here. After every transition, re-read the page and confirm `parentId` matches the expected role; if not, surface as an Error and skip.
387
387
  - **Rollup idempotency**: rollup (Phase 3f) is a no-op on a PRD already parented under `$SHIPPED_PARENT` (and already archived when `closeOnShipped` is `true`) — no duplicate re-parent, no duplicate archive, no duplicate comment. The all-terminal condition is a pure function of the children's current states (deduped by child-ref identity), so recomputing it is safe to re-run. Archival NEVER precedes the all-terminal condition.
388
388
 
@@ -425,4 +425,4 @@ Before this skill can run against a project, the project must adopt the lifecycl
425
425
  3. Move each existing PRD page under the appropriate lifecycle parent based on its current state. Product moves PRDs from `draft` → `ready` when they are ready for ticketing (replaces the Notion `Status = Ready` flip).
426
426
  4. Reserve the `in_review`, `blocked`, and `ticketed` parents for this skill — humans should not re-parent PRDs into them manually except to recover from an error.
427
427
 
428
- If the project hasn't adopted these parent pages, the first run exits with a provisioning error (not the idle empty-set message) — this distinguishes a setup issue from a genuinely empty queue so operators know to run `/lisa:setup:confluence` rather than assuming the queue is drained. See Phase 2 for how the skill detects this case.
428
+ If the project hasn't adopted these parent pages, the first run exits with a provisioning error (not the idle empty-set message) — this distinguishes a setup issue from a genuinely empty queue so operators know to run `/lisa:setup:confluence` rather than assuming there is no work. See Phase 2 for how the skill detects this case.
@@ -1,4 +1,4 @@
1
1
  display_name: "Confluence PRD Intake"
2
- short_description: "Scans a Confluence space (or a parent page) for PRD pages currently parented under the configured `ready` lifecycle page and runs each one…"
2
+ short_description: "Scans a Confluence space (or a parent page) for PRD pages currently parented under the configured `ready` lifecycle page and runs the first…"
3
3
  default_prompt:
4
- - "Use $confluence-prd-intake: Scans a Confluence space (or a parent page) for PRD pages currently parented under the configured `ready` lifecycle page and runs each one…."
4
+ - "Use $confluence-prd-intake: Scans a Confluence space (or a parent page) for PRD pages currently parented under the configured `ready` lifecycle page and runs the first…."
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: github-build-intake
3
- description: "GitHub counterpart to lisa:jira-build-intake. Scans a GitHub repository for issues carrying the configured `ready` build label, claims each leaf work unit by relabeling to the configured `claimed` label, runs the implementation/build flow via lisa:github-agent, and relabels to the configured `done` label on completion. Enforces the claim-time arm of the `leaf-only-lifecycle` rule: a parent/container with open child work (or a childless Epic/Story/Spike) that still carries a stale build-ready label is moved out of the ready pickup queue into the configured `claimed` label with a lifecycle-repair comment, never dispatched to lisa:github-agent. The `ready` label is the human-flipped signal that an issue is truly ready for direct development pickup — mirroring how Notion PRDs work product Draft → Ready → (us) In Review → Blocked|Ticketed."
3
+ description: "GitHub counterpart to lisa:jira-build-intake. Scans a GitHub repository for issues carrying the configured `ready` build label, processes the first eligible issue, runs leaf work via lisa:github-agent, relabels to the configured `done` label on completion, then exits. Enforces the claim-time arm of the `leaf-only-lifecycle` rule: a parent/container with open child work (or a childless Epic/Story/Spike) that still carries a stale build-ready label is moved out of the ready pickup queue into the configured `claimed` label with a lifecycle-repair comment, never dispatched to lisa:github-agent. The `ready` label is the human-flipped signal that an issue is truly ready for direct development pickup — mirroring how Notion PRDs work product Draft → Ready → (us) In Review → Blocked|Ticketed."
4
4
  allowed-tools: ["Skill", "Bash"]
5
5
  ---
6
6
 
@@ -12,7 +12,7 @@ allowed-tools: ["Skill", "Bash"]
12
12
  2. A full GitHub repo URL (e.g., `https://github.com/acme/frontend-v2`).
13
13
  3. The literal token `github` — falls back to `.lisa.config.json` (`github.org` / `github.repo`).
14
14
 
15
- Run one build-intake cycle. Each issue in the configured `ready` build label is claimed, built via the `lisa:github-agent` flow, and relabeled to the configured `done` label (env-aware — see Workflow resolution). The cycle is the symmetric mirror of `lisa:notion-prd-intake`: humans flip the `ready` label, agents pick up and progress.
15
+ Run one build-intake cycle. The first eligible issue in the configured `ready` build label is claimed, built via the `lisa:github-agent` flow, relabeled to the configured `done` label (env-aware — see Workflow resolution), then the cycle exits. Remaining ready issues stay queued for later scheduler invocations.
16
16
 
17
17
  ## Workflow resolution
18
18
 
@@ -30,7 +30,6 @@ read_role() {
30
30
 
31
31
  READY=$(read_role ready "status:ready")
32
32
  CLAIMED=$(read_role claimed "status:in-progress")
33
- REVIEW=$(read_role review "status:code-review")
34
33
  ```
35
34
 
36
35
  For env-keyed `done`, resolve the env first, then look up `done[<env>]`:
@@ -51,10 +50,12 @@ fi
51
50
  DONE_TYPE=$(jq -r '.github.labels.build.done | type' .lisa.config.json 2>/dev/null)
52
51
  if [ "$DONE_TYPE" = "string" ]; then
53
52
  DONE=$(jq -r '.github.labels.build.done' .lisa.config.json)
53
+ DONE_LABELS_JSON=$(jq -c '[.github.labels.build.done]' .lisa.config.json)
54
54
  elif [ "$DONE_TYPE" = "object" ]; then
55
55
  [ -z "$TARGET_ENV" ] && { echo "ERROR: github.labels.build.done is env-keyed but env not resolvable"; exit 1; }
56
56
  DONE=$(jq -r --arg e "$TARGET_ENV" '.github.labels.build.done[$e] // empty' .lisa.config.json)
57
57
  [ -z "$DONE" ] && { echo "ERROR: github.labels.build.done has no entry for env '$TARGET_ENV'"; exit 1; }
58
+ DONE_LABELS_JSON=$(jq -c '[.github.labels.build.done[]]' .lisa.config.json)
58
59
  else
59
60
  case "$TARGET_ENV" in
60
61
  dev) DONE="status:on-dev" ;;
@@ -62,6 +63,7 @@ else
62
63
  production) DONE="status:done" ;;
63
64
  *) echo "ERROR: cannot resolve done label without env"; exit 1 ;;
64
65
  esac
66
+ DONE_LABELS_JSON=$(jq -cn --arg d "$DONE" '[$d]')
65
67
  fi
66
68
  ```
67
69
 
@@ -69,7 +71,7 @@ In prose below, the role names refer to the resolved labels: e.g. "the `ready` l
69
71
 
70
72
  ## Confirmation policy
71
73
 
72
- Do NOT ask the caller whether to proceed. Once invoked with a repo, run the cycle to completion — claim, dispatch each issue through `lisa:github-agent`, relabel successful builds to `$DONE`, write the summary. The caller (a human or a cron) has already authorized the run by invoking the skill; re-prompting defeats the purpose of a background batch.
74
+ Do NOT ask the caller whether to proceed. Once invoked with a repo, run the cycle to completion — claim and dispatch the first eligible issue through `lisa:github-agent`, relabel 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.
73
75
 
74
76
  Specifically forbidden:
75
77
 
@@ -81,7 +83,7 @@ Specifically forbidden:
81
83
  The only legitimate reasons to stop early:
82
84
 
83
85
  - Missing repo or required configuration. Surface the missing value and exit.
84
- - Label namespace not adopted (no issue carries any of `$READY` / `$CLAIMED` / `$REVIEW` / `$DONE`). Surface a label-convention error and exit (this is setup, not a normal idle cycle — see "Adoption" at the bottom).
86
+ - Label namespace not adopted (no issue carries any of `$READY` / `$CLAIMED` / `$DONE`). Surface a label-convention error and exit (this is setup, not a normal idle cycle — see "Adoption" at the bottom).
85
87
  - Empty ready set. Exit cleanly with `"No GitHub issues labeled $READY in <org>/<repo>. Nothing to do."`
86
88
 
87
89
  ## Lifecycle assumed
@@ -89,22 +91,20 @@ The only legitimate reasons to stop early:
89
91
  The GitHub Issues build lifecycle uses **labels** (we deliberately do NOT key off open/closed alone — closed issues aren't always the right post-build state):
90
92
 
91
93
  ```text
92
- ready → claimed → review → done(env-keyed) (downstream merge / archive)
93
- (human) (us claim) (us / PR opens) (us done; PR ready)
94
+ ready → claimed → done(env-keyed)
95
+ (human) (us claim) (us done; PR ready)
94
96
  ```
95
97
 
96
- (Defaults: `status:ready` / `status:in-progress` / `status:code-review` / `status:on-dev`/`status:on-stg`/`status:done`.)
98
+ (Defaults: `status:ready` / `status:in-progress` / `status:on-dev`/`status:on-stg`/`status:done`.)
97
99
 
98
100
  This skill ONLY transitions:
99
101
 
100
102
  - `$READY` → `$CLAIMED` (claim)
101
103
  - `$CLAIMED` → `$DONE` (build complete, PR ready)
102
104
 
103
- It never touches `$REVIEW` (set by the agent / PR open hook), `status:done`-as-terminal (set by merge automation or PM), or any other status.
105
+ A "transition" means: remove the old role label and add the new one, in two `gh issue edit` calls (`--remove-label` + `--add-label`) or one combined call. The skill MUST verify exactly one build-lifecycle label (from the resolved `$READY`/`$CLAIMED`/`$DONE` set) is present after the update having two simultaneously breaks idempotency.
104
106
 
105
- A "transition" means: remove the old role label and add the new one, in two `gh issue edit` calls (`--remove-label` + `--add-label`) or one combined call. The skill MUST verify exactly one build-lifecycle label (from the resolved `$READY`/`$CLAIMED`/`$REVIEW`/`$DONE` set) is present after the update having two simultaneously breaks idempotency.
106
-
107
- **Pre-flight check**: at the start of each cycle, confirm at least one of the resolved role labels (`$READY`, `$CLAIMED`, `$REVIEW`, or any `$DONE` value) exists on the repo via `gh label list --repo <org>/<repo> --json name`. If none exist, the convention has not been adopted — surface the label-convention error and exit.
107
+ **Pre-flight check**: at the start of each cycle, confirm at least one of the resolved role labels (`$READY`, `$CLAIMED`, or any `$DONE` value) exists on the repo via `gh label list --repo <org>/<repo> --json name`. If none exist, the convention has not been adoptedsurface the label-convention error and exit.
108
108
 
109
109
  ## Phases
110
110
 
@@ -127,19 +127,19 @@ If empty, run a secondary check to distinguish a genuinely empty queue from an u
127
127
 
128
128
  ```bash
129
129
  gh label list --repo <org>/<repo> --json name \
130
- | jq -r --arg r "$READY" --arg c "$CLAIMED" --arg v "$REVIEW" --arg d "$DONE" \
131
- '[.[] | .name | select(. == $r or . == $c or . == $v or . == $d)] | length'
130
+ | jq -r --arg r "$READY" --arg c "$CLAIMED" --argjson d "$DONE_LABELS_JSON" \
131
+ '[.[] | .name | select(. == $r or . == $c or (. as $n | $d | index($n)))] | length'
132
132
  ```
133
133
 
134
134
  If none of the configured role labels exist on the repo → label convention not adopted, surface a setup error and exit. If the role labels exist but none are `$READY` on any open issue → genuinely empty queue, exit cleanly with `"No GitHub issues labeled $READY. Nothing to do."`
135
135
 
136
- ### Phase 3 — Process each ready issue (serial)
136
+ ### Phase 3 — Process the first eligible ready issue
137
137
 
138
138
  #### 3a. Leaf-only claim gate (repair containers)
139
139
 
140
140
  Build intake dispatches **only independently implementable leaf work units** to the build agent. This enforces the claim-time arm of the vendor-neutral `leaf-only-lifecycle` rule: a parent/container that still carries a stale build-ready role (e.g. `status:ready` applied before this rule existed, or hand-applied to an Epic/Story) is **never dispatched** — intake moves it out of the pickup queue by replacing `$READY` with `$CLAIMED`, then posts a clear lifecycle-repair message. It is the claim-time complement to the write-time labeling in `lisa:github-write-issue` and the validate-time S15 gate in `lisa:github-validate-issue`; all three cite the same rule so the classification never drifts. **Never silently implement a container.**
141
141
 
142
- Run this gate **before** the leaf claim relabel, for every candidate issue. Do NOT comment "Claimed" or invoke `lisa:github-agent` for an issue that fails the gate. A container repair still changes labels: remove `$READY`, add `$CLAIMED`, and explain that parent/container `$CLAIMED` means rollup/build-lane progress through child/leaf work, not direct implementation.
142
+ Run this gate **before** the leaf claim relabel, starting with the oldest/highest-priority ready candidate. Do NOT comment "Claimed" or invoke `lisa:github-agent` for an issue that fails the gate. A container repair still changes labels: remove `$READY`, add `$CLAIMED`, explain that parent/container `$CLAIMED` means rollup/build-lane progress through child/leaf work rather than direct implementation, record it, and end the cycle.
143
143
 
144
144
  **Resolve container vs. leaf — structural first, then nominal.** Per `leaf-only-lifecycle` the classification is structural: an issue is a **container** if it has **open** child work, whatever its declared type; otherwise the **type label** decides. Resolve child work using the same hierarchy `lisa:github-read-issue` uses — native sub-issues first, then body parentage (task-list checkboxes referencing other issues, `Parent: #<n>` references). Dependency links such as `Blocked by:` are not parentage; they are handled by the active dependency hold gate below.
145
145
 
@@ -254,9 +254,9 @@ This close is idempotent: if the issue is already closed, record that native clo
254
254
 
255
255
  For any non-Success outcome, do NOT transition. The issue sits in `$CLAIMED` (or wherever `lisa:github-agent` left it) — humans take it from there.
256
256
 
257
- #### 3e. Continue
257
+ #### 3e. Stop
258
258
 
259
- Move to the next ready issue. One issue failing does not stop others.
259
+ Stop immediately after the first claimed, skipped, blocked, held, or errored issue. Later scheduler invocations process the remaining ready issues.
260
260
 
261
261
  ### Phase 4 — Summary report
262
262
 
@@ -291,7 +291,7 @@ Total PRs opened: <n>
291
291
  - **Claim-first ordering**: `$CLAIMED` set BEFORE `lisa:github-agent` invocation for leaves; containers are also moved to `$CLAIMED` to leave the ready pickup queue, but are not dispatched.
292
292
  - **No writes outside the lifecycle**: this skill only relabels `$READY → $CLAIMED` and `$CLAIMED → $DONE`. For containers, `$READY → $CLAIMED` is a lifecycle repair, not a direct build claim. Every other label change is owned by `lisa:github-agent`.
293
293
  - **Terminal native closure**: after `$CLAIMED → $DONE`, close the GitHub issue only when `$DONE` is the true terminal done value per `leaf-only-lifecycle`; intermediate env labels stay open.
294
- - **Failure isolation**: per-issue exceptions caught and recorded; the cycle continues.
294
+ - **One item per cycle**: per-issue exceptions are caught and recorded, then the cycle exits. The scheduler owns retrying or moving on to the next ready item.
295
295
  - **Single cycle per repo**: do not run two `lisa:github-build-intake` cycles in parallel against the same repo — concurrent claims could race. The scheduling layer is responsible for serialization.
296
296
  - **Single-label invariant**: after every transition, verify exactly one `status:*` label is present on the issue. If two are present (rare race), surface as an Error and skip — do NOT auto-resolve.
297
297
  - **Never pick an arbitrary env for `$DONE`**. If `done` is a map and env is ambiguous, fail loudly.
@@ -304,7 +304,6 @@ Total PRs opened: <n>
304
304
  | `.lisa.config.json` `github.repo` | (from `$ARGUMENTS`) | GitHub repo for the default queue |
305
305
  | `.lisa.config.json` `github.labels.build.ready` | `status:ready` | The label that signals "human says this is buildable" |
306
306
  | `.lisa.config.json` `github.labels.build.claimed` | `status:in-progress` | The label set on pickup |
307
- | `.lisa.config.json` `github.labels.build.review` | `status:code-review` | The label set when the PR opens (owned by `lisa:github-evidence`) |
308
307
  | `.lisa.config.json` `github.labels.build.done` | env-keyed map or string | The label set after a successful build; env-aware |
309
308
  | `.lisa.config.json` `deploy.branches` | — | Reverse-lookup map for env inference from PR base branch |
310
309
 
@@ -329,7 +328,6 @@ Before this skill can run, the repo must adopt the `status:*` label namespace. U
329
328
  ```bash
330
329
  gh label create status:ready --color FBCA04 --description "Ready for build" --repo <org>/<repo>
331
330
  gh label create status:in-progress --color 0E8A16 --description "Build in progress" --repo <org>/<repo>
332
- gh label create status:code-review --color 5319E7 --description "PR open, awaiting review" --repo <org>/<repo>
333
331
  gh label create status:on-dev --color 1D76DB --description "Built, deployed to dev" --repo <org>/<repo>
334
332
  gh label create status:done --color 0E8A16 --description "Shipped" --repo <org>/<repo>
335
333
  ```
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: github-evidence
3
- description: "Upload text evidence to the GitHub `pr-assets` release, update PR description, post a GitHub Issue comment with code blocks, and relabel the issue to the configured `review` label (default `status:code-review`). Reusable by any skill that captures evidence and generates evidence/comment.md (and optionally evidence/comment.txt). The GitHub counterpart of lisa:jira-evidence."
3
+ description: "Upload text evidence to the GitHub `pr-assets` release, update PR description, and post a GitHub Issue comment with code blocks. Reusable by any skill that captures evidence and generates evidence/comment.md (and optionally evidence/comment.txt). The GitHub counterpart of lisa:jira-evidence."
4
4
  allowed-tools: ["Bash"]
5
5
  ---
6
6
 
@@ -8,23 +8,6 @@ allowed-tools: ["Bash"]
8
8
 
9
9
  Upload captured evidence and generated templates to the GitHub PR description and the originating GitHub Issue. This skill is the posting step — it assumes evidence files and a comment template already exist in the evidence directory.
10
10
 
11
- ## Workflow resolution
12
-
13
- The `claimed` and `review` build labels are read from `.lisa.config.json` `github.labels.build.*`, falling back to the defaults documented in the `config-resolution` rule (`status:in-progress` and `status:code-review`).
14
-
15
- ```bash
16
- read_role() {
17
- local role="$1" default="$2"
18
- local local_v global_v
19
- local_v=$(jq -r ".github.labels.build.${role} // empty" .lisa.config.local.json 2>/dev/null)
20
- global_v=$(jq -r ".github.labels.build.${role} // empty" .lisa.config.json 2>/dev/null)
21
- echo "${local_v:-${global_v:-$default}}"
22
- }
23
-
24
- CLAIMED=$(read_role claimed "status:in-progress")
25
- REVIEW=$(read_role review "status:code-review")
26
- ```
27
-
28
11
  ## Arguments
29
12
 
30
13
  `$ARGUMENTS`: `<ISSUE_REF> <EVIDENCE_DIR> <PR_NUMBER>`
@@ -92,15 +75,9 @@ REVIEW=$(read_role review "status:code-review")
92
75
  gh issue comment <issue-number> --repo <issue-org>/<issue-repo> --body-file "$EVIDENCE_DIR/comment.md"
93
76
  ```
94
77
 
95
- 6. **Relabel the issue to the configured `review` label**
96
-
97
- ```bash
98
- gh issue edit <issue-number> --repo <issue-org>/<issue-repo> \
99
- --remove-label "$CLAIMED" \
100
- --add-label "$REVIEW"
101
- ```
78
+ 6. **Leave lifecycle labels unchanged**
102
79
 
103
- If the current label is already `$REVIEW`, skip. If neither `$CLAIMED` nor `$REVIEW` is present, log a warning and continue without changing labels the issue may have been hand-managed.
80
+ GitHub evidence posting is evidence-only. The caller that owns the build lifecycle (`lisa:github-build-intake` / `lisa:github-agent`) transitions the issue from the configured `claimed` label directly to the configured `done` label after a successful build. Do not apply `status:code-review` here.
104
81
 
105
82
  ## Evidence Naming Convention
106
83
 
@@ -1,4 +1,4 @@
1
1
  display_name: "Github Evidence"
2
- short_description: "Upload text evidence to the GitHub `pr-assets` release, update PR description, post a GitHub Issue comment with code blocks, and relabel…"
2
+ short_description: "Upload text evidence to the GitHub `pr-assets` release, update PR description, and post a GitHub Issue comment with code blocks"
3
3
  default_prompt:
4
- - "Use $github-evidence: Upload text evidence to the GitHub `pr-assets` release, update PR description, post a GitHub Issue comment with code blocks, and relabel…."
4
+ - "Use $github-evidence: Upload text evidence to the GitHub `pr-assets` release, update PR description, and post a GitHub Issue comment with code blocks."
@@ -89,7 +89,7 @@ Use `lisa:github-evidence` to post everything:
89
89
  # Equivalent of: bash scripts/post-evidence.sh — but invoked via the Skill tool
90
90
  ```
91
91
 
92
- Invoke the skill with `<ISSUE_REF> ./evidence <PR_NUMBER>`. It uploads the files to the `pr-assets` release, edits the PR's `## Evidence` section, posts a comment on the issue, and relabels the issue to `status:code-review`.
92
+ Invoke the skill with `<ISSUE_REF> ./evidence <PR_NUMBER>`. It uploads the files to the `pr-assets` release, edits the PR's `## Evidence` section, and posts a comment on the issue. The build-intake owner performs the direct `claimed` `done` lifecycle transition after success.
93
93
 
94
94
  ### Step 6: Verify
95
95
 
@@ -97,7 +97,7 @@ Confirm:
97
97
  - Evidence files exist as release assets named `pr-<PR>-NN-name.{txt,json}`.
98
98
  - The PR description contains the `## Evidence` section with code-block embeds.
99
99
  - The issue has a new comment whose body matches `comment.md`.
100
- - The issue's labels include `status:code-review` and not `status:in-progress`.
100
+ - The issue has the evidence comment, and the build-intake owner can transition it from `status:in-progress` directly to the configured `done` label.
101
101
 
102
102
  ## Verification Patterns Reference
103
103
 
@@ -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 each one through the dry-run validation pipeline. PRDs that pass every gate get tickets written (to whatever destination tracker is configured — JIRA, GitHub Issues itself, or Linear) and the label flipped to the configured `ticketed` label; PRDs that fail get 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)."
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. Each issue with the `ready` label is claimed, validated, and routed to either the `blocked` label (with clarifying comments) or the `ticketed` label (with destination tickets created).
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 batch.
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
 
@@ -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 each ready PRD
127
+ ### Phase 3 — Process the first eligible ready PRD
128
128
 
129
- Process serially to keep label transitions auditable.
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. Continue
228
+ #### 3d. Stop
229
229
 
230
- Move to the next ready PRD. One PRD failing does not affect others.
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`. Move to next PRD. |
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. |
@@ -379,10 +379,10 @@ When the configured destination tracker is GitHub Issues AND the PRD repo is the
379
379
 
380
380
  ## Idempotency & safety
381
381
 
382
- - **Single-cycle scope**: this skill processes the ready set as it exists at the start of Phase 2. New ready issues added mid-cycle are picked up next run.
382
+ - **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
383
  - **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
384
  - **Claim-first ordering**: the label flip to `$IN_REVIEW` happens BEFORE validation runs.
385
- - **Failure isolation**: an exception processing one PRD must not stop the cycle. Catch, record under "Errors" in the summary, continue. The PRD that errored is left labeled `$IN_REVIEW` — humans investigate from there.
385
+ - **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
386
  - **Single-label invariant**: after every transition, verify exactly one lifecycle label is present.
387
387
  - **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
388
 
@@ -1,4 +1,4 @@
1
1
  display_name: "Github PRD Intake"
2
- short_description: "Scans a GitHub repository for issues carrying the configured `ready` PRD label and runs each one through the dry-run validation pipeline"
2
+ short_description: "Scans a GitHub repository for issues carrying the configured `ready` PRD label and runs the first eligible one through the dry-run"
3
3
  default_prompt:
4
- - "Use $github-prd-intake: Scans a GitHub repository for issues carrying the configured `ready` PRD label and runs each one through the dry-run validation pipeline."
4
+ - "Use $github-prd-intake: Scans a GitHub repository for issues carrying the configured `ready` PRD label and runs the first eligible one through the dry-run…."
@@ -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:code-review` |
61
- | PR merged | `status:done` |
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 `status:code-review` flip is owned by `lisa:github-evidence`. The `status:done` flip is typically owned by merge automation or PM. This skill never relabels.
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:code-review`, `status:done`):
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` **or** `status:code-review` | `claimed` | `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:code-review`, `status:on-dev`, `status:done` |
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` |
@@ -293,7 +293,7 @@ The mapping below is the single source of truth for how JIRA concepts translate
293
293
  | JIRA concept | GitHub Issues equivalent |
294
294
  |---|---|
295
295
  | Issue type | Label `type:<value>` |
296
- | Status (Ready / In Progress / Code Review / On Dev / Done) | Label `status:<value>` |
296
+ | Status (Ready / In Progress / On Dev / Done) | Label `status:<value>` |
297
297
  | Epic / Story / Sub-task hierarchy | Native sub-issues via `gh api graphql addSubIssue` |
298
298
  | Acceptance Criteria | `## Acceptance Criteria` markdown section with a Gherkin code-fence |
299
299
  | Validation Journey | `## Validation Journey` markdown section |