@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.
Files changed (150) 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/confluence-prd-intake.md +1 -1
  5. package/plugins/lisa/agents/github-agent.md +4 -5
  6. package/plugins/lisa/agents/github-build-intake.md +1 -1
  7. package/plugins/lisa/agents/github-prd-intake.md +1 -1
  8. package/plugins/lisa/agents/linear-prd-intake.md +1 -1
  9. package/plugins/lisa/agents/notion-prd-intake.md +1 -1
  10. package/plugins/lisa/commands/intake.md +1 -1
  11. package/plugins/lisa/commands/project-ideation.md +3 -3
  12. package/plugins/lisa/commands/repair-intake.md +6 -0
  13. package/plugins/lisa/commands/research.md +3 -3
  14. package/plugins/lisa/commands/setup-automations.md +6 -0
  15. package/plugins/lisa/commands/tear-down-automations.md +6 -0
  16. package/plugins/lisa/commands/verify-prd.md +2 -2
  17. package/plugins/lisa/rules/config-resolution.md +63 -4
  18. package/plugins/lisa/rules/intent-routing.md +4 -3
  19. package/plugins/lisa/rules/leaf-only-lifecycle.md +1 -1
  20. package/plugins/lisa/rules/prd-lifecycle-rollup.md +10 -2
  21. package/plugins/lisa/rules/repo-scope-split.md +18 -1
  22. package/plugins/lisa/skills/confluence-prd-intake/SKILL.md +24 -14
  23. package/plugins/lisa/skills/confluence-prd-intake/agents/openai.yaml +2 -2
  24. package/plugins/lisa/skills/confluence-write-prd/SKILL.md +103 -0
  25. package/plugins/lisa/skills/confluence-write-prd/agents/openai.yaml +4 -0
  26. package/plugins/lisa/skills/github-build-intake/SKILL.md +32 -21
  27. package/plugins/lisa/skills/github-evidence/SKILL.md +3 -26
  28. package/plugins/lisa/skills/github-evidence/agents/openai.yaml +2 -2
  29. package/plugins/lisa/skills/github-journey/SKILL.md +2 -2
  30. package/plugins/lisa/skills/github-prd-intake/SKILL.md +25 -11
  31. package/plugins/lisa/skills/github-prd-intake/agents/openai.yaml +2 -2
  32. package/plugins/lisa/skills/github-sync/SKILL.md +5 -5
  33. package/plugins/lisa/skills/github-write-issue/SKILL.md +15 -6
  34. package/plugins/lisa/skills/github-write-prd/SKILL.md +100 -0
  35. package/plugins/lisa/skills/github-write-prd/agents/openai.yaml +4 -0
  36. package/plugins/lisa/skills/implement/SKILL.md +13 -6
  37. package/plugins/lisa/skills/intake/SKILL.md +13 -12
  38. package/plugins/lisa/skills/intake/agents/openai.yaml +2 -2
  39. package/plugins/lisa/skills/jira-build-intake/SKILL.md +24 -11
  40. package/plugins/lisa/skills/jira-write-ticket/SKILL.md +8 -0
  41. package/plugins/lisa/skills/linear-build-intake/SKILL.md +22 -9
  42. package/plugins/lisa/skills/linear-prd-intake/SKILL.md +23 -13
  43. package/plugins/lisa/skills/linear-prd-intake/agents/openai.yaml +2 -2
  44. package/plugins/lisa/skills/linear-write-issue/SKILL.md +10 -2
  45. package/plugins/lisa/skills/linear-write-prd/SKILL.md +90 -0
  46. package/plugins/lisa/skills/linear-write-prd/agents/openai.yaml +4 -0
  47. package/plugins/lisa/skills/notion-access/SKILL.md +2 -0
  48. package/plugins/lisa/skills/notion-prd-intake/SKILL.md +22 -12
  49. package/plugins/lisa/skills/notion-prd-intake/agents/openai.yaml +2 -2
  50. package/plugins/lisa/skills/notion-write-prd/SKILL.md +107 -0
  51. package/plugins/lisa/skills/notion-write-prd/agents/openai.yaml +4 -0
  52. package/plugins/lisa/skills/prd-source-write/SKILL.md +80 -0
  53. package/plugins/lisa/skills/prd-source-write/agents/openai.yaml +4 -0
  54. package/plugins/lisa/skills/project-ideation/SKILL.md +183 -80
  55. package/plugins/lisa/skills/repair-intake/SKILL.md +403 -0
  56. package/plugins/lisa/skills/repair-intake/agents/openai.yaml +4 -0
  57. package/plugins/lisa/skills/research/SKILL.md +19 -3
  58. package/plugins/lisa/skills/research/agents/openai.yaml +2 -2
  59. package/plugins/lisa/skills/setup-automations/SKILL.md +78 -0
  60. package/plugins/lisa/skills/setup-automations/agents/openai.yaml +4 -0
  61. package/plugins/lisa/skills/setup-github/SKILL.md +0 -1
  62. package/plugins/lisa/skills/tear-down-automations/SKILL.md +34 -0
  63. package/plugins/lisa/skills/tear-down-automations/agents/openai.yaml +4 -0
  64. package/plugins/lisa/skills/tracker-build-intake/SKILL.md +6 -2
  65. package/plugins/lisa/skills/tracker-build-intake/agents/openai.yaml +2 -2
  66. package/plugins/lisa/skills/tracker-evidence/SKILL.md +2 -2
  67. package/plugins/lisa/skills/tracker-sync/SKILL.md +1 -1
  68. package/plugins/lisa/skills/verify-prd/SKILL.md +41 -38
  69. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  70. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  71. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  72. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  73. package/plugins/lisa-expo/commands/exploratory-qa.md +3 -3
  74. package/plugins/lisa-expo/skills/exploratory-qa/SKILL.md +48 -18
  75. package/plugins/lisa-expo/skills/exploratory-qa/agents/openai.yaml +2 -2
  76. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  77. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  78. package/plugins/lisa-harper-fabric/commands/exploratory-qa.md +3 -3
  79. package/plugins/lisa-harper-fabric/skills/exploratory-qa/SKILL.md +48 -18
  80. package/plugins/lisa-harper-fabric/skills/exploratory-qa/agents/openai.yaml +2 -2
  81. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  82. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  83. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  84. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  85. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  86. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  87. package/plugins/lisa-rails/commands/exploratory-qa.md +3 -3
  88. package/plugins/lisa-rails/skills/exploratory-qa/SKILL.md +48 -18
  89. package/plugins/lisa-rails/skills/exploratory-qa/agents/openai.yaml +2 -2
  90. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  91. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  92. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  93. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  94. package/plugins/lisa-wiki/skills/lisa-wiki-ingest/SKILL.md +30 -1
  95. package/plugins/src/base/agents/confluence-prd-intake.md +1 -1
  96. package/plugins/src/base/agents/github-agent.md +4 -5
  97. package/plugins/src/base/agents/github-build-intake.md +1 -1
  98. package/plugins/src/base/agents/github-prd-intake.md +1 -1
  99. package/plugins/src/base/agents/linear-prd-intake.md +1 -1
  100. package/plugins/src/base/agents/notion-prd-intake.md +1 -1
  101. package/plugins/src/base/commands/intake.md +1 -1
  102. package/plugins/src/base/commands/project-ideation.md +3 -3
  103. package/plugins/src/base/commands/repair-intake.md +6 -0
  104. package/plugins/src/base/commands/research.md +3 -3
  105. package/plugins/src/base/commands/setup-automations.md +6 -0
  106. package/plugins/src/base/commands/tear-down-automations.md +6 -0
  107. package/plugins/src/base/commands/verify-prd.md +2 -2
  108. package/plugins/src/base/rules/config-resolution.md +63 -4
  109. package/plugins/src/base/rules/intent-routing.md +4 -3
  110. package/plugins/src/base/rules/leaf-only-lifecycle.md +1 -1
  111. package/plugins/src/base/rules/prd-lifecycle-rollup.md +10 -2
  112. package/plugins/src/base/rules/repo-scope-split.md +18 -1
  113. package/plugins/src/base/skills/confluence-prd-intake/SKILL.md +24 -14
  114. package/plugins/src/base/skills/confluence-write-prd/SKILL.md +103 -0
  115. package/plugins/src/base/skills/github-build-intake/SKILL.md +32 -21
  116. package/plugins/src/base/skills/github-evidence/SKILL.md +3 -26
  117. package/plugins/src/base/skills/github-journey/SKILL.md +2 -2
  118. package/plugins/src/base/skills/github-prd-intake/SKILL.md +25 -11
  119. package/plugins/src/base/skills/github-sync/SKILL.md +5 -5
  120. package/plugins/src/base/skills/github-write-issue/SKILL.md +15 -6
  121. package/plugins/src/base/skills/github-write-prd/SKILL.md +100 -0
  122. package/plugins/src/base/skills/implement/SKILL.md +13 -6
  123. package/plugins/src/base/skills/intake/SKILL.md +13 -12
  124. package/plugins/src/base/skills/jira-build-intake/SKILL.md +24 -11
  125. package/plugins/src/base/skills/jira-write-ticket/SKILL.md +8 -0
  126. package/plugins/src/base/skills/linear-build-intake/SKILL.md +22 -9
  127. package/plugins/src/base/skills/linear-prd-intake/SKILL.md +23 -13
  128. package/plugins/src/base/skills/linear-write-issue/SKILL.md +10 -2
  129. package/plugins/src/base/skills/linear-write-prd/SKILL.md +90 -0
  130. package/plugins/src/base/skills/notion-access/SKILL.md +2 -0
  131. package/plugins/src/base/skills/notion-prd-intake/SKILL.md +22 -12
  132. package/plugins/src/base/skills/notion-write-prd/SKILL.md +107 -0
  133. package/plugins/src/base/skills/prd-source-write/SKILL.md +80 -0
  134. package/plugins/src/base/skills/project-ideation/SKILL.md +183 -80
  135. package/plugins/src/base/skills/repair-intake/SKILL.md +403 -0
  136. package/plugins/src/base/skills/research/SKILL.md +19 -3
  137. package/plugins/src/base/skills/setup-automations/SKILL.md +78 -0
  138. package/plugins/src/base/skills/setup-github/SKILL.md +0 -1
  139. package/plugins/src/base/skills/tear-down-automations/SKILL.md +34 -0
  140. package/plugins/src/base/skills/tracker-build-intake/SKILL.md +6 -2
  141. package/plugins/src/base/skills/tracker-evidence/SKILL.md +2 -2
  142. package/plugins/src/base/skills/tracker-sync/SKILL.md +1 -1
  143. package/plugins/src/base/skills/verify-prd/SKILL.md +41 -38
  144. package/plugins/src/expo/commands/exploratory-qa.md +3 -3
  145. package/plugins/src/expo/skills/exploratory-qa/SKILL.md +48 -18
  146. package/plugins/src/harper-fabric/commands/exploratory-qa.md +3 -3
  147. package/plugins/src/harper-fabric/skills/exploratory-qa/SKILL.md +48 -18
  148. package/plugins/src/rails/commands/exploratory-qa.md +3 -3
  149. package/plugins/src/rails/skills/exploratory-qa/SKILL.md +48 -18
  150. package/plugins/src/wiki/skills/lisa-wiki-ingest/SKILL.md +30 -1
@@ -0,0 +1,103 @@
1
+ ---
2
+ name: confluence-write-prd
3
+ description: "Creates or idempotently updates a PRD as a Confluence page parented under the configured lifecycle parent page (the draft parent by default, or the ready parent when initial_role is ready so lisa:confluence-prd-intake auto-claims it). The Confluence PRD-source writer behind lisa:prd-source-write. Confluence models PRD state by PARENT PAGE (not labels), per config-resolution. Dedupes by a stable marker embedded in the page body, found via CQL (matched by marker, never by title). All Atlassian access goes through lisa:atlassian-access."
4
+ allowed-tools: ["Skill", "Bash"]
5
+ ---
6
+
7
+ # Write Confluence PRD: $ARGUMENTS
8
+
9
+ Create (or update) a PRD page in Confluence. Invoked by `lisa:prd-source-write` when
10
+ `source = confluence`; do not call directly from a vendor-neutral caller. **All Confluence
11
+ operations go through `lisa:atlassian-access`** — never call the Atlassian API/MCP or `acli` directly.
12
+
13
+ Confluence's PRD lifecycle uses **parent pages**, not labels (scoped API tokens can't write
14
+ Confluence labels — see `config-resolution` "Confluence PRD lifecycle uses parent pages"). A PRD's
15
+ state is which lifecycle parent it lives under; "promote to ready" = re-parent to the ready parent.
16
+
17
+ `$ARGUMENTS` carries the `lisa:prd-source-write` spec: `title`, `body` (full PRD markdown),
18
+ `initial_role` (`draft` | `ready`, default `draft`), `dedupe_key`, `marker`, optional `source_ref`.
19
+
20
+ ## Phase 1 — Resolve lifecycle parents
21
+
22
+ ```bash
23
+ read_g() { 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); echo "${lv:-${gv:-$2}}"; }
24
+ SPACE=$(read_g '.confluence.spaceKey' '')
25
+ CLOUDID=$(read_g '.atlassian.cloudId' '')
26
+ [ -z "$CLOUDID" ] && { echo "Error: atlassian.cloudId not set in .lisa.config.json."; exit 1; }
27
+ # Resolve the FULL set of lifecycle parents from config (never hard-code) — needed for the target
28
+ # parent, the past-ready reverse-lookup, and to derive the space when spaceKey is absent.
29
+ DRAFT_PARENT=$(read_g '.confluence.parents.draft' '')
30
+ READY_PARENT=$(read_g '.confluence.parents.ready' '')
31
+ IN_REVIEW_PARENT=$(read_g '.confluence.parents.in_review' '')
32
+ BLOCKED_PARENT=$(read_g '.confluence.parents.blocked' '')
33
+ TICKETED_PARENT=$(read_g '.confluence.parents.ticketed' '')
34
+ SHIPPED_PARENT=$(read_g '.confluence.parents.shipped' '')
35
+ VERIFIED_PARENT=$(read_g '.confluence.parents.verified' '')
36
+ # "Progressed past ready" parents (never re-parent a PRD down from these):
37
+ PROGRESSED_PARENTS=("$IN_REVIEW_PARENT" "$BLOCKED_PARENT" "$TICKETED_PARENT" "$SHIPPED_PARENT" "$VERIFIED_PARENT")
38
+ ```
39
+
40
+ Resolve the target parent from `initial_role`: `ready` → `$READY_PARENT`, otherwise `$DRAFT_PARENT`.
41
+ If the needed parent id is unset, stop and report that `/lisa:setup:confluence` must provision the
42
+ lifecycle parent pages — do not create a PRD outside the lifecycle scaffolding.
43
+
44
+ **Resolve the space (config allows parent-page-only setups with no `spaceKey`).** If `$SPACE` is
45
+ empty, derive it from the target lifecycle parent: `lisa:atlassian-access` `operation: read-page id:
46
+ <target parent>` and read its space key from the response. If neither `confluence.spaceKey` is set nor
47
+ a space can be derived from the parent, **stop and report** that a space could not be established —
48
+ do not attempt a CQL search or create without it.
49
+
50
+ ## Phase 2 — Dedupe by marker (CQL search before create)
51
+
52
+ The `marker` is embedded in the page body. Find an existing PRD page carrying it — match the marker,
53
+ **never** the title:
54
+
55
+ ```text
56
+ lisa:atlassian-access operation: search-pages cql: 'space = "<SPACE>" AND text ~ "<marker>"'
57
+ ```
58
+
59
+ If `source_ref` was passed, target that page directly. If a page with the marker exists → **update**;
60
+ else → **create**.
61
+
62
+ ## Phase 3 — Create or update
63
+
64
+ **Storage-format body + marker (both paths).** Convert the PRD markdown to Confluence **storage
65
+ format** (XHTML): `#`/`##`/`###` → `<h1>/<h2>/<h3>`, paragraphs → `<p>`, lists → `<ul>/<ol><li>`,
66
+ fenced code → `<ac:structured-macro ac:name="code">`. Embed the marker as a storage comment
67
+ (`<!-- $MARKER -->`) or a small `<p>` so future CQL dedupe finds it. The body must always contain
68
+ **exactly one** marker; never write a markerless page (CREATE or UPDATE).
69
+
70
+ **CREATE:** `lisa:atlassian-access` `operation: write-page` (create form) with a payload that sets:
71
+ - `title`: `$TITLE`
72
+ - `space`: `$SPACE` (resolved in Phase 1)
73
+ - `ancestors`/`parentId`: the resolved lifecycle parent (`$DRAFT_PARENT` or `$READY_PARENT`)
74
+ - `body`: the storage-format, marker-normalized body above.
75
+
76
+ **UPDATE** (existing page or `source_ref`):
77
+ 1. **GET-then-PUT** (load-bearing, as `confluence-prd-intake` documents): first `operation: read-page
78
+ id: <page-id>` to read the current `version.number`, then `operation: write-page` (edit form) with
79
+ the marker-normalized storage body and `version.number` bumped to current+1. A PUT without the
80
+ current version is rejected; never drop the marker on the edit.
81
+ 2. Re-parent to the target lifecycle parent if the role changed — **unless** the page's current
82
+ parent is in the resolved `${PROGRESSED_PARENTS[@]}` set (already past `ready`). If so, leave it
83
+ and report `reused (already past ready)`. Reverse-lookup the current parent in
84
+ `confluence.parents.*` to determine its role before re-parenting.
85
+
86
+ ## Phase 4 — Return
87
+
88
+ ```yaml
89
+ ref: "<confluence-page-id>"
90
+ url: "<page url>"
91
+ role: draft | ready # derived from the lifecycle parent the page now lives under (or its current role when reused past ready)
92
+ marker: "<MARKER>"
93
+ outcome: created | reused
94
+ ```
95
+
96
+ ## Rules
97
+
98
+ - All access via `lisa:atlassian-access`; never call Atlassian directly.
99
+ - State is the parent page, not a label — never attempt Confluence label writes (they 401 on scoped
100
+ tokens; see `config-resolution`).
101
+ - Match dedupe by marker, never by title.
102
+ - Never re-parent a PRD already past `ready` down to draft/ready.
103
+ - Resolve parents from config (`confluence.parents.{draft,ready}`) — never hardcode page ids.
@@ -0,0 +1,4 @@
1
+ display_name: "Confluence Write PRD"
2
+ short_description: "Creates or idempotently updates a PRD as a Confluence page parented under the configured lifecycle parent page (the draft parent by…"
3
+ default_prompt:
4
+ - "Use $confluence-write-prd: Creates or idempotently updates a PRD as a Confluence page parented under the configured lifecycle parent page (the draft parent by…."
@@ -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,32 @@ 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
+
138
+ #### 3a.0 Repo-scope gate (claim only current-repo issues)
139
+
140
+ GitHub Issues live in one repo by definition, so the scanned repo's issues are usually inherently current-repo. But a planning/umbrella repo's issues can target sibling repos, so this skill still claims only issues 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).
141
+
142
+ 1. **Resolve the current repo** per `config-resolution` "Repo scoping" (`.repo` → `.github.repo` → `git remote get-url origin` basename). If unresolvable, stop and report.
143
+ 2. **Cheap path first.** Prefer candidates already carrying the `repo:<current>` label. Keep the Phase 2 scan broad so unlabeled issues are still seen, determined, and stamped.
144
+ 3. **Per candidate, apply the repo-scope decision (`repo-scope-split`):**
145
+ - Carries `repo:<other>` → **skip** (leave it `ready` for that repo's own intake); next candidate.
146
+ - **Unlabeled** → determine the target repo(s) from the issue + code surfaces, then **stamp** `repo:<name>` via `gh issue edit <n> --add-label "repo:<name>"` (create the label lazily) so later cycles filter cheaply; re-apply with the now-known repo. (An issue whose work is entirely in the scanned repo is simply labeled `repo:<current>`.)
147
+ - **Multi-repo leaf → split, never claim.** Run the `repo-scope-split` work-time procedure 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.
148
+ - **Single-repo leaf for the current repo** → fall through to 3a (leaf-only gate) and 3b (claim).
149
+ 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 issues for repo <current>. Nothing to do."`.
137
150
 
138
151
  #### 3a. Leaf-only claim gate (repair containers)
139
152
 
140
153
  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
154
 
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.
155
+ 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
156
 
144
157
  **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
158
 
@@ -254,9 +267,9 @@ This close is idempotent: if the issue is already closed, record that native clo
254
267
 
255
268
  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
269
 
257
- #### 3e. Continue
270
+ #### 3e. Stop
258
271
 
259
- Move to the next ready issue. One issue failing does not stop others.
272
+ Stop immediately after the first claimed, skipped, blocked, held, or errored issue. Later scheduler invocations process the remaining ready issues.
260
273
 
261
274
  ### Phase 4 — Summary report
262
275
 
@@ -291,7 +304,7 @@ Total PRs opened: <n>
291
304
  - **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
305
  - **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
306
  - **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.
307
+ - **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
308
  - **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
309
  - **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
310
  - **Never pick an arbitrary env for `$DONE`**. If `done` is a map and env is ambiguous, fail loudly.
@@ -304,7 +317,6 @@ Total PRs opened: <n>
304
317
  | `.lisa.config.json` `github.repo` | (from `$ARGUMENTS`) | GitHub repo for the default queue |
305
318
  | `.lisa.config.json` `github.labels.build.ready` | `status:ready` | The label that signals "human says this is buildable" |
306
319
  | `.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
320
  | `.lisa.config.json` `github.labels.build.done` | env-keyed map or string | The label set after a successful build; env-aware |
309
321
  | `.lisa.config.json` `deploy.branches` | — | Reverse-lookup map for env inference from PR base branch |
310
322
 
@@ -329,7 +341,6 @@ Before this skill can run, the repo must adopt the `status:*` label namespace. U
329
341
  ```bash
330
342
  gh label create status:ready --color FBCA04 --description "Ready for build" --repo <org>/<repo>
331
343
  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
344
  gh label create status:on-dev --color 1D76DB --description "Built, deployed to dev" --repo <org>/<repo>
334
345
  gh label create status:done --color 0E8A16 --description "Shipped" --repo <org>/<repo>
335
346
  ```
@@ -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
 
@@ -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 reuses `blocked` rather than introducing a separate `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.
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 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. |
@@ -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
- - **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.
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 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.
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
 
@@ -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` |
@@ -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" — its state rolls up from children.
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 / Code Review / On Dev / Done) | Label `status:<value>` |
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 |