@codyswann/lisa 2.223.2 → 2.224.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 (107) hide show
  1. package/all/copy-contents/gitignore +3 -0
  2. package/package.json +1 -1
  3. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  4. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  5. package/plugins/lisa/.codex-plugin/skills/lisa-github-build-intake/SKILL.md +13 -3
  6. package/plugins/lisa/.codex-plugin/skills/lisa-intake/SKILL.md +17 -5
  7. package/plugins/lisa/.codex-plugin/skills/lisa-queue-status/SKILL.md +13 -5
  8. package/plugins/lisa/.codex-plugin/skills/lisa-repair-intake/SKILL.md +24 -10
  9. package/plugins/lisa/.codex-plugin/skills/lisa-setup-automations/SKILL.md +12 -7
  10. package/plugins/lisa/.codex-plugin/skills/lisa-setup-github/SKILL.md +54 -3
  11. package/plugins/lisa/rules/reference/config-resolution.md +8 -0
  12. package/plugins/lisa/scripts/automation-status-expected-fleet.mjs +40 -10
  13. package/plugins/lisa/scripts/queue-contract-resolution.mjs +73 -4
  14. package/plugins/lisa/scripts/queue-status-build-readers.mjs +62 -10
  15. package/plugins/lisa/skills/lisa-github-build-intake/SKILL.md +13 -3
  16. package/plugins/lisa/skills/lisa-intake/SKILL.md +17 -5
  17. package/plugins/lisa/skills/lisa-queue-status/SKILL.md +13 -5
  18. package/plugins/lisa/skills/lisa-repair-intake/SKILL.md +24 -10
  19. package/plugins/lisa/skills/lisa-setup-automations/SKILL.md +12 -7
  20. package/plugins/lisa/skills/lisa-setup-github/SKILL.md +54 -3
  21. package/plugins/lisa-agy/plugin.json +1 -1
  22. package/plugins/lisa-agy/scripts/automation-status-expected-fleet.mjs +40 -10
  23. package/plugins/lisa-agy/scripts/queue-contract-resolution.mjs +73 -4
  24. package/plugins/lisa-agy/scripts/queue-status-build-readers.mjs +62 -10
  25. package/plugins/lisa-agy/skills/lisa-github-build-intake/SKILL.md +13 -3
  26. package/plugins/lisa-agy/skills/lisa-intake/SKILL.md +17 -5
  27. package/plugins/lisa-agy/skills/lisa-queue-status/SKILL.md +13 -5
  28. package/plugins/lisa-agy/skills/lisa-repair-intake/SKILL.md +24 -10
  29. package/plugins/lisa-agy/skills/lisa-setup-automations/SKILL.md +12 -7
  30. package/plugins/lisa-agy/skills/lisa-setup-github/SKILL.md +54 -3
  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-cdk-agy/plugin.json +1 -1
  34. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  35. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  37. package/plugins/lisa-copilot/rules/reference/config-resolution.md +8 -0
  38. package/plugins/lisa-copilot/scripts/automation-status-expected-fleet.mjs +40 -10
  39. package/plugins/lisa-copilot/scripts/queue-contract-resolution.mjs +73 -4
  40. package/plugins/lisa-copilot/scripts/queue-status-build-readers.mjs +62 -10
  41. package/plugins/lisa-copilot/skills/lisa-github-build-intake/SKILL.md +13 -3
  42. package/plugins/lisa-copilot/skills/lisa-intake/SKILL.md +17 -5
  43. package/plugins/lisa-copilot/skills/lisa-queue-status/SKILL.md +13 -5
  44. package/plugins/lisa-copilot/skills/lisa-repair-intake/SKILL.md +24 -10
  45. package/plugins/lisa-copilot/skills/lisa-setup-automations/SKILL.md +12 -7
  46. package/plugins/lisa-copilot/skills/lisa-setup-github/SKILL.md +54 -3
  47. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-cursor/rules/config-resolution-reference.mdc +8 -0
  49. package/plugins/lisa-cursor/scripts/automation-status-expected-fleet.mjs +40 -10
  50. package/plugins/lisa-cursor/scripts/queue-contract-resolution.mjs +73 -4
  51. package/plugins/lisa-cursor/scripts/queue-status-build-readers.mjs +62 -10
  52. package/plugins/lisa-cursor/skills/lisa-github-build-intake/SKILL.md +13 -3
  53. package/plugins/lisa-cursor/skills/lisa-intake/SKILL.md +17 -5
  54. package/plugins/lisa-cursor/skills/lisa-queue-status/SKILL.md +13 -5
  55. package/plugins/lisa-cursor/skills/lisa-repair-intake/SKILL.md +24 -10
  56. package/plugins/lisa-cursor/skills/lisa-setup-automations/SKILL.md +12 -7
  57. package/plugins/lisa-cursor/skills/lisa-setup-github/SKILL.md +54 -3
  58. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  59. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  60. package/plugins/lisa-expo-agy/plugin.json +1 -1
  61. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  63. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  64. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  65. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  66. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  67. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  68. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  69. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  70. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  71. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  72. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  73. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  74. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  75. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  76. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  77. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  78. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  79. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  80. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  81. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  82. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  83. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  84. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  85. package/plugins/lisa-rails-agy/plugin.json +1 -1
  86. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  87. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  88. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  89. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  90. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  91. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  92. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  93. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  94. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  95. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  96. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  97. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  98. package/plugins/src/base/rules/reference/config-resolution.md +8 -0
  99. package/plugins/src/base/scripts/automation-status-expected-fleet.mjs +40 -10
  100. package/plugins/src/base/scripts/queue-contract-resolution.mjs +73 -4
  101. package/plugins/src/base/scripts/queue-status-build-readers.mjs +62 -10
  102. package/plugins/src/base/skills/lisa-github-build-intake/SKILL.md +13 -3
  103. package/plugins/src/base/skills/lisa-intake/SKILL.md +17 -5
  104. package/plugins/src/base/skills/lisa-queue-status/SKILL.md +13 -5
  105. package/plugins/src/base/skills/lisa-repair-intake/SKILL.md +24 -10
  106. package/plugins/src/base/skills/lisa-setup-automations/SKILL.md +12 -7
  107. package/plugins/src/base/skills/lisa-setup-github/SKILL.md +54 -3
@@ -58,23 +58,75 @@ const HIGHLIGHT_COPY = {
58
58
  * readonly queueResolved?: boolean
59
59
  * readonly queueArgument?: string
60
60
  * readonly resolutionError?: string | null
61
+ * readonly currentRepo?: string | null
61
62
  * }} input
62
63
  */
63
64
  export function readGithubBuildQueueSnapshot(input = {}) {
64
65
  const roles = input.roles ?? resolveBuildLifecycleRoles({}, "github").roles;
65
- const normalizedItems = (input.issues ?? [])
66
+ const issues = input.issues ?? [];
67
+ const normalizedItems = issues
68
+ .filter(
69
+ issue =>
70
+ classifyGithubIssueRepoScope(issue, input.currentRepo) === "current"
71
+ )
72
+ .map(issue => normalizeGithubBuildIssue(issue, roles))
73
+ .filter(Boolean);
74
+ const unscopedCandidates = issues
75
+ .filter(
76
+ issue =>
77
+ classifyGithubIssueRepoScope(issue, input.currentRepo) === "unscoped"
78
+ )
66
79
  .map(issue => normalizeGithubBuildIssue(issue, roles))
67
80
  .filter(Boolean);
68
81
 
69
- return createBuildQueueSnapshot({
70
- tracker: "github",
71
- items: normalizedItems,
72
- roles,
73
- namespaceAdopted: input.namespaceAdopted,
74
- queueResolved: input.queueResolved,
75
- queueArgument: input.queueArgument,
76
- resolutionError: input.resolutionError,
77
- });
82
+ return {
83
+ ...createBuildQueueSnapshot({
84
+ tracker: "github",
85
+ items: normalizedItems,
86
+ roles,
87
+ namespaceAdopted: input.namespaceAdopted,
88
+ queueResolved: input.queueResolved,
89
+ queueArgument: input.queueArgument,
90
+ resolutionError: input.resolutionError,
91
+ }),
92
+ unscopedCount: unscopedCandidates.length,
93
+ unscopedCandidates,
94
+ };
95
+ }
96
+
97
+ /**
98
+ * Classify current-repo, unlabeled, and sibling-only candidates. Unlabeled work
99
+ * remains separately visible because build intake must determine and stamp its
100
+ * repo, but it must not inflate current-repo lifecycle counts. Containers
101
+ * carrying multiple repo labels are current when one label matches.
102
+ *
103
+ * @param {Record<string, any>} issue
104
+ * @param {string | null | undefined} currentRepo
105
+ * @returns {"current" | "unscoped" | "sibling"}
106
+ */
107
+ function classifyGithubIssueRepoScope(issue, currentRepo) {
108
+ if (typeof currentRepo !== "string" || currentRepo.trim().length === 0) {
109
+ return "current";
110
+ }
111
+
112
+ const repoLabels = (Array.isArray(issue?.labels) ? issue.labels : [])
113
+ .map(label =>
114
+ typeof label === "string"
115
+ ? label
116
+ : typeof label?.name === "string"
117
+ ? label.name
118
+ : ""
119
+ )
120
+ .map(label => label.trim().toLowerCase())
121
+ .filter(label => label.startsWith("repo:") && label.length > 5);
122
+
123
+ if (repoLabels.length === 0) {
124
+ return "unscoped";
125
+ }
126
+
127
+ return repoLabels.includes(`repo:${currentRepo.trim().toLowerCase()}`)
128
+ ? "current"
129
+ : "sibling";
78
130
  }
79
131
 
80
132
  /**
@@ -10,7 +10,13 @@ allowed-tools: ["Skill", "Bash"]
10
10
 
11
11
  1. A GitHub `org/repo` token (e.g., `acme/frontend-v2`).
12
12
  2. A full GitHub repo URL (e.g., `https://github.com/acme/frontend-v2`).
13
- 3. The literal token `github` falls back to `.lisa.config.json` (`github.org` / `github.repo`).
13
+ 3. The literal token `github` (or an omitted repo) resolves merged config
14
+ `github.queueRepo`, falling back to the identity `github.org/github.repo`.
15
+
16
+ An explicit `org/repo` token or GitHub URL always wins. `github.queueRepo` may be canonical
17
+ `owner/repo` or a short repo name normalized to `github.org`. It changes only the scanned queue;
18
+ the Phase 3a.0 `repo:<current>` gate still resolves the code repository from `repo` /
19
+ `github.repo` / the git remote.
14
20
 
15
21
  Run one build-intake cycle. The first eligible issue in the configured `ready` build label is claimed, built via the `github-agent` workflow run in-session (Phase 3c, culminating in `lisa-implement`), 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
22
 
@@ -133,7 +139,10 @@ A "transition" means: remove the old role label and add the new one, in two `gh
133
139
  1. Parse `$ARGUMENTS`:
134
140
  - `org/repo` token → use as-is.
135
141
  - GitHub URL → extract `org` and `repo`.
136
- - Literal `github` → resolve from `.lisa.config.json` (`github.org`, `github.repo`); error if not set.
142
+ - Literal `github` or omitted repo → resolve local then global `github.queueRepo`, falling back
143
+ to `github.org/github.repo`; normalize a short `queueRepo` to `github.org`; error if the
144
+ resulting identity/queue cannot be resolved.
145
+ - Never replace current-repo identity with the queue repo. An umbrella queue is only a scan target.
137
146
  2. Confirm `gh auth status` succeeds.
138
147
  3. Confirm the repo is reachable: `gh repo view <org>/<repo> --json name --jq '.name'`.
139
148
 
@@ -405,7 +414,8 @@ Total PRs opened: <n>
405
414
  | Variable | Default | Purpose |
406
415
  |----------|---------|---------|
407
416
  | `.lisa.config.json` `github.org` | (from `$ARGUMENTS`) | GitHub org for the default queue |
408
- | `.lisa.config.json` `github.repo` | (from `$ARGUMENTS`) | GitHub repo for the default queue |
417
+ | `.lisa.config.json` `github.repo` | (from `$ARGUMENTS`) | Current code-repo identity and `repo:<current>` scope |
418
+ | `.lisa.config.json` `github.queueRepo` | `github.org/github.repo` | Default GitHub scan repo when no explicit repo/URL is passed |
409
419
  | `.lisa.config.json` `github.labels.build.ready` | `status:ready` | The label that signals "human says this is buildable" |
410
420
  | `.lisa.config.json` `github.labels.build.claimed` | `status:in-progress` | The label set on pickup |
411
421
  | `.lisa.config.json` `github.labels.build.done` | env-keyed map or string | The label set after a successful build; env-aware |
@@ -6,7 +6,10 @@ allowed-tools: ["Skill", "Bash", "mcp__claude_ai_Notion__notion-fetch", "mcp__cl
6
6
 
7
7
  # Intake: $ARGUMENTS
8
8
 
9
- Run one intake cycle against the queue identified by `$ARGUMENTS`. Scans for `Status = Ready`, claims the first eligible item, dispatches it to the appropriate single-item lifecycle skill, then exits. Remaining Ready items are left for later scheduler invocations.
9
+ Run one intake cycle against the queue identified by `$ARGUMENTS`, or by merged GitHub config when
10
+ the repo argument is omitted and a GitHub source/tracker default is resolvable. Scan for
11
+ `Status = Ready`, claim the first eligible item, dispatch it to the appropriate single-item
12
+ lifecycle skill, then exit. Remaining Ready items are left for later scheduler invocations.
10
13
 
11
14
  For build-queue runs, Intake also accepts an optional `assignee=<vendor-user-id-or-login>` filter.
12
15
  Resolution order is:
@@ -22,7 +25,9 @@ as part of this filter.
22
25
 
23
26
  ## Confirmation policy
24
27
 
25
- Do NOT ask the caller whether to proceed. Once invoked with a queue, run the cycle to completion. The caller (a human at the CLI or a scheduled cron) has already authorized the run by invoking the skill; re-prompting defeats the purpose of a background batch.
28
+ Do NOT ask the caller whether to proceed. Once invoked, resolve the explicit or config-backed queue
29
+ and run the cycle to completion. The caller (a human at the CLI or a scheduled cron) has already
30
+ authorized the run by invoking the skill; re-prompting defeats the purpose of a background batch.
26
31
 
27
32
  Specifically forbidden:
28
33
 
@@ -33,7 +38,8 @@ Specifically forbidden:
33
38
 
34
39
  The only legitimate reasons to stop early:
35
40
 
36
- - Missing required input (no queue argument, missing project configuration). Surface the missing value and exit.
41
+ - Missing required input (no queue argument **and** no resolvable GitHub default, or missing project
42
+ configuration). Surface the missing value and exit.
37
43
  - The queue itself is misconfigured (Status property missing expected values, JIRA workflow can't reach required transitions). Surface and exit.
38
44
  - Empty `Ready` set. Exit cleanly with the idle-case message.
39
45
 
@@ -70,7 +76,7 @@ Detect the queue type from `$ARGUMENTS` and route:
70
76
  | A full JQL filter (e.g. `project = SE AND component = "frontend"`) | Work queue (JIRA, narrowed) | Invoke `lisa-jira-build-intake` with the JQL |
71
77
  | A GitHub **repository** URL or `org/repo` token (e.g. `https://github.com/acme/product-prds` or `acme/product-prds`) when used for **PRDs** | PRD queue (GitHub) | Invoke `lisa-github-prd-intake` (which queries `gh issue list --label prd-ready`, claims the first eligible PRD by relabeling to `prd-in-review`, runs the dry-run validate → branch → write pipeline, then exits). PRD discovery is independent of the destination tracker — the resulting tickets land wherever `.lisa.config.json` `tracker` says. |
72
78
  | A GitHub **repository** URL or `org/repo` token when `tracker = github` is configured (build-queue mode) | Work queue (GitHub) | Invoke `lisa-tracker-build-intake` which dispatches to `lisa-github-build-intake` (which queries `gh issue list --label status:ready`, optionally narrows by the resolved assignee filter, claims the first eligible issue via `status:in-progress`, runs `lisa-implement`, relabels to `status:on-dev` on success, then exits). |
73
- | The literal token `github` | Defaults to `.lisa.config.json` `github.org` / `github.repo`. Routes by **the `intake_mode` flag** in `$ARGUMENTS` (`prd` or `build`); if the flag is absent, prefer the PRD queue when both label namespaces are present, otherwise pick whichever exists. | Invoke the matching skill (`lisa-github-prd-intake` or `lisa-tracker-build-intake`). |
79
+ | The literal token `github` or omitted GitHub repo when merged config resolves a GitHub source/tracker and identity | Routes by **the `intake_mode` flag** in `$ARGUMENTS` (`prd` or `build`). Build mode defaults to merged `github.queueRepo`, then identity `github.org/github.repo`; PRD mode keeps its existing identity source. If the flag is absent, prefer the PRD queue when both label namespaces are present, otherwise pick whichever exists. | Invoke the matching skill (`lisa-github-prd-intake` or `lisa-tracker-build-intake`). |
74
80
 
75
81
  Disambiguation rules:
76
82
 
@@ -80,7 +86,13 @@ Disambiguation rules:
80
86
  - A `linear.app` URL → Linear queue. If the path is `/<workspace>` only or `/<workspace>/team/<KEY>/...`, route here. If the path includes `/project/<slug>-<id>` it's a single-PRD URL — direct the caller to `lisa-plan` instead, this skill is batch-only.
81
87
  - The literal token `linear` (case-insensitive) → Linear queue, default workspace from `linear.workspace` in `.lisa.config.json`.
82
88
  - A `github.com` URL or an `<org>/<repo>` token → GitHub queue. The PRD-vs-build dispatch is determined by which label namespace the repo currently uses: PRD-side (`prd-ready`) → `lisa-github-prd-intake`; build-side (`status:ready` and `tracker = github` in `.lisa.config.json`) → `lisa-tracker-build-intake`. If both namespaces are present, prefer the PRD queue unless `$ARGUMENTS` includes `intake_mode=build`. If the URL points at a single issue (`https://github.com/<org>/<repo>/issues/<n>`), this skill is batch-only — direct the caller to `lisa-plan` (for a single PRD issue) or `lisa-implement` (for a single build issue).
83
- - The literal token `github` (case-insensitive) GitHub queue, default repo from `.lisa.config.json` `github.org` / `github.repo`.
89
+ - A GitHub URL or `owner/repo` token is an explicit queue and always wins. The literal token
90
+ `github` (case-insensitive), or an omitted repo when merged config resolves a GitHub source/tracker
91
+ and identity, resolves local then global `github.queueRepo`, then identity
92
+ `github.org/github.repo` **for build dispatch**. Normalize a short queueRepo to `github.org`. PRD
93
+ dispatch remains on the configured GitHub PRD source. Without an explicit queue or resolvable
94
+ GitHub default, stop with the missing-input error. Do not use the build queue repo as current-repo
95
+ identity for `repo:<name>` scoping.
84
96
  - A bare alphanumeric token that matches the JIRA project key regex (uppercase letters / digits / hyphen, ≤10 chars — typically the value of `jira.project` in `.lisa.config.json`) is treated as a JIRA project key by default. A token that does not match the regex is treated as a Confluence space key. If it does not resolve as a Confluence space key either, attempt to resolve as a Linear team key via `lisa-linear-access operation: list-teams({query})` before giving up. The only time to stop and ask is when the token resolves to more than one of {JIRA project, Confluence space, Linear team, GitHub `org/repo`} simultaneously — in that overlap the user must disambiguate which queue to scan.
85
97
  - An `<org>/<repo>` token (slash-separated, both halves are GitHub-name-shaped) → GitHub queue.
86
98
  - A string starting with `project = ` or containing JQL operators (`AND`, `OR`, `=`, `!=`, `~`, etc.) → JQL filter.
@@ -58,11 +58,14 @@ Render the report in **grouped sections** so operators can scan it top-down with
58
58
  For each inspected queue, report:
59
59
 
60
60
  1. The queue source or tracker Lisa resolved.
61
- 2. Lifecycle counts using the repo's configured role names.
62
- 3. Whether the queue appears `IDLE`, `HEALTHY`, `ATTENTION_NEEDED`, or `MISCONFIGURED`.
63
- 4. Whether the lifecycle namespace appears adopted versus absent.
64
- 5. The oldest or most actionable blocked, in-review, claimed, shipped, or similar stuck items Lisa can surface without mutating work.
65
- 6. A concise remediation hint when attention is needed.
61
+ 2. For GitHub, both `Identity repo: <owner/repo>` and `Queue repo: <owner/repo>`, even when equal.
62
+ 3. Lifecycle counts using the repo's configured role names. GitHub umbrella-queue build counts
63
+ must be scoped to `repo:<currentRepo>` from the repo-scoping ladder; the queue repo is never
64
+ current-repo identity.
65
+ 4. Whether the queue appears `IDLE`, `HEALTHY`, `ATTENTION_NEEDED`, or `MISCONFIGURED`.
66
+ 5. Whether the lifecycle namespace appears adopted versus absent.
67
+ 6. The oldest or most actionable blocked, in-review, claimed, shipped, or similar stuck items Lisa can surface without mutating work.
68
+ 7. A concise remediation hint when attention is needed.
66
69
 
67
70
  The report should stay terminal-first and immediately actionable: observable queue facts first, then the smallest useful next step.
68
71
 
@@ -92,6 +95,11 @@ Queue sections should stay visually grouped. Do not interleave PRD and build fac
92
95
  ## Runtime and vendor expectations
93
96
 
94
97
  - Reuse the same config-resolution defaults and queue-routing rules that `intake` and `repair-intake` use.
98
+ - For GitHub, resolve an explicit repo/URL first, then merged `github.queueRepo`, then
99
+ `github.org/github.repo`; accept a short queueRepo by normalizing it to `github.org`.
100
+ - Pass the contract's `currentRepo` into `readGithubBuildQueueSnapshot`; lifecycle counts include
101
+ only `repo:<current>` work. Report its `unscopedCount` / `unscopedCandidates` separately because
102
+ intake still needs to determine and stamp unlabeled work; exclude sibling-only issues.
95
103
  - Work from the current repo's `.lisa.config.json` instead of hardcoding one vendor's lifecycle names.
96
104
  - Support the vendor families already served by Lisa intake: GitHub, Linear, JIRA, Notion, and Confluence.
97
105
  - If a queue cannot be resolved or its lifecycle namespace has not been adopted, report that explicitly as `MISCONFIGURED` rather than pretending the queue is empty.
@@ -6,7 +6,8 @@ allowed-tools: ["Skill", "Bash", "Read", "Write", "Edit"]
6
6
 
7
7
  # Repair Intake: $ARGUMENTS
8
8
 
9
- Run one batch-**repair** cycle against the queue identified by `$ARGUMENTS`. Where `lisa-intake`
9
+ Run one batch-**repair** cycle against the queue identified by `$ARGUMENTS`, or by merged GitHub
10
+ config when the queue is omitted and a GitHub source/tracker default is resolvable. Where `lisa-intake`
10
11
  scans the `ready` role and moves work *forward*, repair-intake scans the **stuck and
11
12
  close-out** roles and moves work *unstuck* or *fully closed*:
12
13
 
@@ -73,22 +74,24 @@ lifecycle state with provider-native closure and rollup state.
73
74
  ## Public contract
74
75
 
75
76
  ```text
76
- /lisa:repair-intake <queue> [intake_mode=prd|build|both] [stale_after=2h] [max_candidates=100] [force=true]
77
+ /lisa:repair-intake [<queue>] [intake_mode=prd|build|both] [build_queue=owner/repo] [stale_after=2h] [max_candidates=100] [force=true]
77
78
  ```
78
79
 
79
80
  | Token | Meaning | Default |
80
81
  |-------|---------|---------|
81
- | `<queue>` | Same queue identifier `lisa-intake` accepts (see Source dispatch). Required. | |
82
+ | `<queue>` | Same queue identifier `lisa-intake` accepts (see Source dispatch). Optional only when merged config resolves a GitHub source/tracker and identity; otherwise required. | merged GitHub default when resolvable |
82
83
  | `intake_mode` | `prd` \| `build` \| `both`. Only meaningful for a GitHub `org/repo` (or bare `github`) that hosts both PRD and build label namespaces. `both` is unique to repair — a repair sweep usefully covers both lifecycles in one schedule. Absent → `both` when both namespaces exist, else whichever lifecycle exists. | `both` for dual GitHub queues; otherwise infer |
84
+ | `build_queue` | GitHub build scan target used with literal `github`, especially `intake_mode=both`. Explicit `owner/repo` or URL for a build-only invocation wins over this token; otherwise this wins over `github.queueRepo`. It never redirects the PRD scan. | `github.queueRepo`, then `github.org/github.repo` |
83
85
  | `stale_after` | How long since the last state-changing transition into the in-progress role, or since the last human / PR-side forward-progress activity, before an in-progress item counts as stalled. Automation self-comments do not reset this clock. Accepts `24h`, `90m`, `2d`, or `0` (treat any in-progress item as stalled — manual recovery, also the only way to resume work on a provider that exposes no reliable timestamp). Overrides config. | `2h` |
84
86
  | `max_candidates` | Cap on how many stuck/close-out candidates to enumerate and evaluate. Repair every materially actionable candidate within this bounded set, then stop. Overrides config. | `100` |
85
87
  | `force` | `true` bypasses the loop-prevention backoff window (so a manual re-run re-attempts items even if their fingerprint is unchanged). It does **not** change the staleness rule — use `stale_after=0` for that. | `false` |
86
88
 
87
89
  ## Confirmation policy
88
90
 
89
- Do NOT ask the caller whether to proceed. Once invoked with a queue, run the cycle to
90
- completion. The caller (a human at the CLI or a scheduled cron) has already authorized the run
91
- by invoking the skill; re-prompting defeats the purpose of a background repair sweep.
91
+ Do NOT ask the caller whether to proceed. Once invoked, resolve the explicit or config-backed
92
+ queue and run the cycle to completion. The caller (a human at the CLI or a scheduled cron) has
93
+ already authorized the run by invoking the skill; re-prompting defeats the purpose of a
94
+ background repair sweep.
92
95
 
93
96
  Specifically forbidden:
94
97
 
@@ -105,8 +108,8 @@ Specifically forbidden:
105
108
 
106
109
  The only legitimate reasons to stop early:
107
110
 
108
- - Missing required input (no queue argument, missing project configuration). Surface the
109
- missing value and exit.
111
+ - Missing required input (no queue argument **and** no resolvable GitHub default, or missing
112
+ project configuration). Surface the missing value and exit.
110
113
  - The queue itself is misconfigured (Status property missing expected values, JIRA workflow
111
114
  can't reach required transitions). Surface and exit.
112
115
  - No stuck/close-out candidates, or none actionable this cycle. Exit cleanly with the idle-case
@@ -142,7 +145,7 @@ claim-and-advance). The essentials, inlined here so this skill is self-complete:
142
145
  | GitHub **repo** URL / `org/repo` (PRD namespace) | PRD (GitHub) | source=github | `in_review`, `blocked`, terminal/open PRDs, missing PRD child links, all-terminal generated-work rollups |
143
146
  | GitHub **repo** URL / `org/repo` with `tracker = github` (build namespace) | Build (GitHub) | tracker=github | `claimed`, `blocked`, terminal/open issues, parent rollups (intermediate-env + all-terminal), stale-`ready` containers |
144
147
  | GitHub **repo** URL / `org/repo` with an open issue missing configured lifecycle labels | GitHub label normalization | per classified lifecycle | add configured `prd.ready` or build `ready` |
145
- | Literal `github` | GitHub; route by `intake_mode` (`prd` / `build` / `both`) | per lifecycle | per lifecycle above, plus GitHub ready-label normalization |
148
+ | Literal `github` or omitted GitHub repo when merged config resolves a GitHub source/tracker and identity | GitHub; PRD scans identity, build scans `build_queue` merged `github.queueRepo` identity; `both` runs those two lane-specific targets | per lifecycle | per lifecycle above, plus GitHub ready-label normalization |
146
149
  | JIRA project key or full JQL | Build (JIRA) | tracker=jira | `claimed`, `blocked`, terminal/closure verification, parent rollups (intermediate-env + all-terminal), stale-`ready` containers |
147
150
 
148
151
  Disambiguation (same as `lisa-intake`): a `notion.so`/`notion.site` URL → Notion; an Atlassian
@@ -153,6 +156,17 @@ token / literal `github` → GitHub; a bare token matching the JIRA project-key
153
156
  URL is out of scope** — this skill is batch-only; repair one item by hand via `lisa-implement`
154
157
  (build) or by re-running `lisa:<source>-to-tracker` (PRD).
155
158
 
159
+ For GitHub `intake_mode=build` (a build-only invocation), an explicit URL or `owner/repo` wins;
160
+ otherwise resolve `build_queue`, then local/global `github.queueRepo`, falling back to
161
+ `github.org/github.repo`. For `intake_mode=both`, the primary `<queue>` is the PRD identity/source
162
+ repo and `build_queue` controls the build lane, falling back through `github.queueRepo` to identity.
163
+ A short queueRepo is normalized to `github.org`. Thus `both` is a bounded split scan: PRD candidates
164
+ at the primary identity queue, build candidates at the resolved build queue, combined into one
165
+ summary. Never apply both lifecycle namespaces to the umbrella repo merely because
166
+ `github.queueRepo` is set. Repository identity remains distinct and continues to drive
167
+ `repo:<current>` filtering, writes, and automation names. If neither an explicit queue nor a
168
+ resolvable merged GitHub default exists, stop with the missing-input error.
169
+
156
170
  Role names for every vendor are resolved from `.lisa.config.json` per the `config-resolution`
157
171
  rule — never hardcode status/label strings. The relevant repair roles:
158
172
 
@@ -968,7 +982,7 @@ bucket and show compact refs plus counts.
968
982
  /schedule "every 2 hours" /lisa:repair-intake https://linear.app/acme
969
983
  /schedule "every 2 hours" /lisa:repair-intake acme/product-prds
970
984
  /schedule "every 2 hours" /lisa:repair-intake acme/frontend-v2 intake_mode=build
971
- /schedule "every 2 hours" /lisa:repair-intake github intake_mode=both
985
+ /schedule "every 2 hours" /lisa:repair-intake acme/frontend intake_mode=both build_queue=acme/planning
972
986
  /schedule "every 4 hours" /lisa:repair-intake SE stale_after=12h
973
987
  /lisa:repair-intake SE stale_after=0 force=true # manual: treat all in-progress as stalled, ignore backoff
974
988
  ```
@@ -59,9 +59,9 @@ report the exact conflicting path(s).
59
59
 
60
60
  | Automation | Command it runs | Cadence |
61
61
  |---|---|---|
62
- | **intake-repair** | `/lisa:repair-intake <queue>` | every **60 minutes** |
63
- | **intake-prd** | `/lisa:intake <PRD queue>` (e.g. `github intake_mode=prd`) | every **60 minutes** |
64
- | **intake-tickets** | `/lisa:intake <build queue>` (e.g. `github intake_mode=build`) | every **10 minutes** |
62
+ | **intake-repair** | `/lisa:repair-intake <resolved repair queue>` (GitHub self-host example: `acme/frontend intake_mode=both build_queue=acme/planning`) | every **60 minutes** |
63
+ | **intake-prd** | `/lisa:intake <PRD queue>` (e.g. `acme/frontend intake_mode=prd`) | every **60 minutes** |
64
+ | **intake-tickets** | `/lisa:intake <build queue>` (e.g. `acme/planning intake_mode=build`) | every **10 minutes** |
65
65
  | **exploratory-bugs** | `/lisa-<stack>:exploratory-qa ready=<auto-start-tickets>` | **once a day** |
66
66
  | **exploratory-prds** | `/lisa:project-ideation prd_ready=<auto-start-prds>` | **once a day** |
67
67
  | **monitor** | `/lisa:monitor` | **once a day** |
@@ -75,10 +75,15 @@ lifecycle when the PRD queue has capacity," not "always create a new ready PRD."
75
75
  `/lisa:queue-status`; if pressure exists, the cycle should report the blocking role/ref and the
76
76
  smallest next action, usually `/lisa:intake <PRD queue>`, without invoking research or writing a PRD.
77
77
 
78
- **Queue resolution.** Resolve the intake/repair queue from `.lisa.config.json` — `source` for the
79
- PRD queue, `tracker` for the build queue (for the common GitHub case these are `github
80
- intake_mode=prd` and `github intake_mode=build`, matching how the existing Lisa intake automations
81
- are written).
78
+ **Queue resolution.** Resolve the intake/repair queue from merged config — `source` for the PRD
79
+ queue, `tracker` for the build queue. For GitHub, the PRD command uses canonical identity
80
+ `github.org/github.repo`; the build command resolves `github.queueRepo` and falls back to that
81
+ identity. Keep automation naming tied to the identity repo. Bake every resolved `owner/repo` into
82
+ the scheduled commands (for example `/lisa:intake acme/frontend intake_mode=prd`,
83
+ `/lisa:intake acme/planning intake_mode=build`, and
84
+ `/lisa:repair-intake acme/frontend intake_mode=both build_queue=acme/planning`) so a later
85
+ config/read-context failure cannot silently redirect the cron. A short queueRepo is normalized to
86
+ `github.org` before writing the automation.
82
87
 
83
88
  **Naming + scope (so teardown is precise).** Name each automation with the stable prefix
84
89
  `lisa-auto-<project>-` (e.g. `lisa-auto-<project>-intake-tickets`), where `<project>` identifies this
@@ -79,6 +79,23 @@ gh repo view "$ORG/$REPO" --json name,viewerPermission \
79
79
 
80
80
  If permission is `READ` / `TRIAGE`, stop — lisa cannot create labels or issues. Surface and exit.
81
81
 
82
+ ### Step 2b — Choose the queue repository
83
+
84
+ When GitHub is selected as the destination tracker, initialize the choice from an existing
85
+ `github.queueRepo`, or `$ORG/$REPO` when absent, then ask whether the build backlog lives there, in
86
+ the identity repo, or in another umbrella/planning repo. If the user gives an umbrella repo, accept a short name by normalizing it to `$ORG/<name>` or accept a full
87
+ `owner/repo`, then verify it is reachable and the authenticated identity can manage the lifecycle
88
+ labels Lisa needs:
89
+
90
+ ```bash
91
+ gh repo view "$QUEUE_ORG/$QUEUE_REPO" --json name,viewerPermission \
92
+ --jq 'if (.viewerPermission | IN("ADMIN","MAINTAIN","WRITE")) then "ok" else error("insufficient permission: \(.viewerPermission)") end'
93
+ ```
94
+
95
+ Store `github.queueRepo` only when the canonical queue `owner/repo` differs from `$ORG/$REPO`.
96
+ This choice changes queue scans, not repository identity: `github.repo`, `repo:<current>` claim
97
+ scoping, issue destinations, and automation naming remain tied to the identity/tracker repo.
98
+
82
99
  ### Step 3 — Scaffold the lifecycle label namespaces
83
100
 
84
101
  Read role → label mappings with the same default-fallback ladder the intake skills use, so the labels created here exactly match what they look for. Only the namespaces selected in Step 0 are scaffolded.
@@ -92,12 +109,13 @@ read_role() { # $1=namespace (build|prd) $2=role $3=default
92
109
  }
93
110
 
94
111
  # Idempotent label creator: create if missing, leave untouched if present.
112
+ # LABEL_ORG/LABEL_REPO select the repo for the namespace being scaffolded.
95
113
  ensure_label() { # $1=name $2=hex-color $3=description
96
114
  local name="$1" color="$2" desc="$3"
97
- if gh label list --repo "$ORG/$REPO" --limit 200 --json name --jq '.[].name' | grep -qxF "$name"; then
115
+ if gh label list --repo "$LABEL_ORG/$LABEL_REPO" --limit 200 --json name --jq '.[].name' | grep -qxF "$name"; then
98
116
  echo " = $name (exists)"
99
117
  else
100
- gh label create "$name" --repo "$ORG/$REPO" --color "$color" --description "$desc" \
118
+ gh label create "$name" --repo "$LABEL_ORG/$LABEL_REPO" --color "$color" --description "$desc" \
101
119
  && echo " + $name (created)"
102
120
  fi
103
121
  }
@@ -108,6 +126,8 @@ ensure_label() { # $1=name $2=hex-color $3=description
108
126
  Defaults from `config-resolution`. The `done` role is **env-keyed** — create all three by default; a project whose terminal state is env-independent can later collapse `github.labels.build.done` to a single string.
109
127
 
110
128
  ```bash
129
+ LABEL_ORG="$QUEUE_ORG"
130
+ LABEL_REPO="$QUEUE_REPO"
111
131
  ensure_label "$(read_role build ready status:ready)" FBCA04 "Ready for build (human signal)"
112
132
  ensure_label "$(read_role build claimed status:in-progress)" 0E8A16 "Build in progress (agent owns)"
113
133
  ensure_label "$(read_role build blocked status:blocked)" D93F0B "Blocked — human attention required"
@@ -119,6 +139,8 @@ ensure_label "$(read_role build done.production status:done)" 0E8A16 "Shipped
119
139
  #### 3b. PRD-lifecycle labels (only if GitHub is the PRD source)
120
140
 
121
141
  ```bash
142
+ LABEL_ORG="$ORG"
143
+ LABEL_REPO="$REPO"
122
144
  ensure_label "$(read_role prd draft prd-draft)" C5DEF5 "PRD in progress (product owns)"
123
145
  ensure_label "$(read_role prd ready prd-ready)" FBCA04 "PRD ready for ticketing"
124
146
  ensure_label "$(read_role prd in_review prd-in-review)" 5319E7 "Claude is reviewing this PRD"
@@ -145,6 +167,19 @@ jq --arg org "$ORG" --arg repo "$REPO" \
145
167
  '.github = ((.github // {}) | .org = $org | .repo = $repo)' \
146
168
  .lisa.config.json > .lisa.config.json.tmp && mv .lisa.config.json.tmp .lisa.config.json
147
169
 
170
+ # Queue repo is canonical owner/repo and omitted for the identity/default case.
171
+ # A source-only setup rerun preserves any existing build-queue choice.
172
+ if [ "$GITHUB_TRACKER_SELECTED" = "true" ]; then
173
+ if [ "$QUEUE_ORG/$QUEUE_REPO" = "$ORG/$REPO" ]; then
174
+ jq 'del(.github.queueRepo)' .lisa.config.json > .lisa.config.json.tmp \
175
+ && mv .lisa.config.json.tmp .lisa.config.json
176
+ else
177
+ jq --arg queue "$QUEUE_ORG/$QUEUE_REPO" '.github.queueRepo = $queue' \
178
+ .lisa.config.json > .lisa.config.json.tmp \
179
+ && mv .lisa.config.json.tmp .lisa.config.json
180
+ fi
181
+ fi
182
+
148
183
  # Conditionally write label overrides (only roles the user mapped to non-default names).
149
184
  # $LABEL_OVERRIDES_JSON is e.g. {"build":{"ready":"ready-for-dev"}} — {} if all defaults.
150
185
  if [ -n "$LABEL_OVERRIDES_JSON" ] && [ "$LABEL_OVERRIDES_JSON" != "{}" ]; then
@@ -198,8 +233,24 @@ Both are project-wide switches that change every downstream skill's default —
198
233
 
199
234
  ```bash
200
235
  jq -e '.github.org and .github.repo' .lisa.config.json >/dev/null
236
+ EFFECTIVE_ORG=$(jq -r '.github.org // empty' .lisa.config.local.json 2>/dev/null)
237
+ EFFECTIVE_ORG=${EFFECTIVE_ORG:-$(jq -r '.github.org' .lisa.config.json)}
238
+ EFFECTIVE_REPO=$(jq -r '.github.repo // empty' .lisa.config.local.json 2>/dev/null)
239
+ EFFECTIVE_REPO=${EFFECTIVE_REPO:-$(jq -r '.github.repo' .lisa.config.json)}
240
+ QUEUE_VALUE=$(jq -r '.github.queueRepo // empty' .lisa.config.local.json 2>/dev/null)
241
+ QUEUE_VALUE=${QUEUE_VALUE:-$(jq -r '.github.queueRepo // empty' .lisa.config.json)}
242
+ if [ -z "$QUEUE_VALUE" ]; then
243
+ QUEUE_REF="$EFFECTIVE_ORG/$EFFECTIVE_REPO"
244
+ elif [[ "$QUEUE_VALUE" == */* ]]; then
245
+ QUEUE_REF="$QUEUE_VALUE"
246
+ else
247
+ QUEUE_REF="$EFFECTIVE_ORG/$QUEUE_VALUE"
248
+ fi
249
+ gh repo view "$QUEUE_REF" --json nameWithOwner --jq .nameWithOwner
201
250
  gh label list --repo "$ORG/$REPO" --limit 200 --json name --jq '.[].name' \
202
- | grep -E 'status:|prd-' || true # show the scaffolded namespaces
251
+ | grep -E 'prd-' || true
252
+ gh label list --repo "$QUEUE_REF" --limit 200 --json name --jq '.[].name' \
253
+ | grep -E 'status:' || true
203
254
  ```
204
255
 
205
256
  If `github.projects.v2` is configured, setup verification MUST also run the shared Project utility in