@codyswann/lisa 2.223.3 → 2.225.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/package.json +1 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-agent-ready/SKILL.md +97 -7
- package/plugins/lisa/.codex-plugin/skills/lisa-github-build-intake/SKILL.md +13 -3
- package/plugins/lisa/.codex-plugin/skills/lisa-intake/SKILL.md +17 -5
- package/plugins/lisa/.codex-plugin/skills/lisa-queue-status/SKILL.md +13 -5
- package/plugins/lisa/.codex-plugin/skills/lisa-repair-intake/SKILL.md +24 -10
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-automations/SKILL.md +12 -7
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-github/SKILL.md +54 -3
- package/plugins/lisa/commands/agent-ready.md +2 -2
- package/plugins/lisa/rules/eager/factory-model.md +3 -2
- package/plugins/lisa/rules/reference/config-resolution.md +8 -0
- package/plugins/lisa/rules/reference/factory-model.md +9 -5
- package/plugins/lisa/scripts/automation-status-expected-fleet.mjs +40 -10
- package/plugins/lisa/scripts/queue-contract-resolution.mjs +73 -4
- package/plugins/lisa/scripts/queue-status-build-readers.mjs +62 -10
- package/plugins/lisa/skills/lisa-agent-ready/SKILL.md +98 -8
- package/plugins/lisa/skills/lisa-agent-ready/agents/openai.yaml +2 -2
- package/plugins/lisa/skills/lisa-github-build-intake/SKILL.md +13 -3
- package/plugins/lisa/skills/lisa-intake/SKILL.md +17 -5
- package/plugins/lisa/skills/lisa-queue-status/SKILL.md +13 -5
- package/plugins/lisa/skills/lisa-repair-intake/SKILL.md +24 -10
- package/plugins/lisa/skills/lisa-setup-automations/SKILL.md +12 -7
- package/plugins/lisa/skills/lisa-setup-github/SKILL.md +54 -3
- package/plugins/lisa-agy/commands/lisa/agent-ready.md +2 -2
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/scripts/automation-status-expected-fleet.mjs +40 -10
- package/plugins/lisa-agy/scripts/queue-contract-resolution.mjs +73 -4
- package/plugins/lisa-agy/scripts/queue-status-build-readers.mjs +62 -10
- package/plugins/lisa-agy/skills/lisa-agent-ready/SKILL.md +98 -8
- package/plugins/lisa-agy/skills/lisa-github-build-intake/SKILL.md +13 -3
- package/plugins/lisa-agy/skills/lisa-intake/SKILL.md +17 -5
- package/plugins/lisa-agy/skills/lisa-queue-status/SKILL.md +13 -5
- package/plugins/lisa-agy/skills/lisa-repair-intake/SKILL.md +24 -10
- package/plugins/lisa-agy/skills/lisa-setup-automations/SKILL.md +12 -7
- package/plugins/lisa-agy/skills/lisa-setup-github/SKILL.md +54 -3
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/commands/lisa/agent-ready.md +2 -2
- package/plugins/lisa-copilot/rules/eager/factory-model.md +3 -2
- package/plugins/lisa-copilot/rules/reference/config-resolution.md +8 -0
- package/plugins/lisa-copilot/rules/reference/factory-model.md +9 -5
- package/plugins/lisa-copilot/scripts/automation-status-expected-fleet.mjs +40 -10
- package/plugins/lisa-copilot/scripts/queue-contract-resolution.mjs +73 -4
- package/plugins/lisa-copilot/scripts/queue-status-build-readers.mjs +62 -10
- package/plugins/lisa-copilot/skills/lisa-agent-ready/SKILL.md +98 -8
- package/plugins/lisa-copilot/skills/lisa-github-build-intake/SKILL.md +13 -3
- package/plugins/lisa-copilot/skills/lisa-intake/SKILL.md +17 -5
- package/plugins/lisa-copilot/skills/lisa-queue-status/SKILL.md +13 -5
- package/plugins/lisa-copilot/skills/lisa-repair-intake/SKILL.md +24 -10
- package/plugins/lisa-copilot/skills/lisa-setup-automations/SKILL.md +12 -7
- package/plugins/lisa-copilot/skills/lisa-setup-github/SKILL.md +54 -3
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/commands/lisa/agent-ready.md +2 -2
- package/plugins/lisa-cursor/rules/config-resolution-reference.mdc +8 -0
- package/plugins/lisa-cursor/rules/factory-model-reference.mdc +9 -5
- package/plugins/lisa-cursor/rules/factory-model.mdc +3 -2
- package/plugins/lisa-cursor/scripts/automation-status-expected-fleet.mjs +40 -10
- package/plugins/lisa-cursor/scripts/queue-contract-resolution.mjs +73 -4
- package/plugins/lisa-cursor/scripts/queue-status-build-readers.mjs +62 -10
- package/plugins/lisa-cursor/skills/lisa-agent-ready/SKILL.md +98 -8
- package/plugins/lisa-cursor/skills/lisa-github-build-intake/SKILL.md +13 -3
- package/plugins/lisa-cursor/skills/lisa-intake/SKILL.md +17 -5
- package/plugins/lisa-cursor/skills/lisa-queue-status/SKILL.md +13 -5
- package/plugins/lisa-cursor/skills/lisa-repair-intake/SKILL.md +24 -10
- package/plugins/lisa-cursor/skills/lisa-setup-automations/SKILL.md +12 -7
- package/plugins/lisa-cursor/skills/lisa-setup-github/SKILL.md +54 -3
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/src/base/commands/agent-ready.md +2 -2
- package/plugins/src/base/rules/eager/factory-model.md +3 -2
- package/plugins/src/base/rules/reference/config-resolution.md +8 -0
- package/plugins/src/base/rules/reference/factory-model.md +9 -5
- package/plugins/src/base/scripts/automation-status-expected-fleet.mjs +40 -10
- package/plugins/src/base/scripts/queue-contract-resolution.mjs +73 -4
- package/plugins/src/base/scripts/queue-status-build-readers.mjs +62 -10
- package/plugins/src/base/skills/lisa-agent-ready/SKILL.md +98 -8
- package/plugins/src/base/skills/lisa-github-build-intake/SKILL.md +13 -3
- package/plugins/src/base/skills/lisa-intake/SKILL.md +17 -5
- package/plugins/src/base/skills/lisa-queue-status/SKILL.md +13 -5
- package/plugins/src/base/skills/lisa-repair-intake/SKILL.md +24 -10
- package/plugins/src/base/skills/lisa-setup-automations/SKILL.md +12 -7
- package/plugins/src/base/skills/lisa-setup-github/SKILL.md +54 -3
- package/ui/index.html +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.225.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.225.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, across Claude and Codex.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.225.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.225.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.225.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "Make a brownfield project agent-ready: build the initial knowledge wiki
|
|
2
|
+
description: "Make a brownfield project agent-ready: build the initial knowledge wiki through read-only, redacted ingestion, persist complete/partial/unavailable coverage for every source, write wiki/gaps.md with the questions only a human can answer, and converge over re-runs until every source is complete and zero gaps remain. Run before letting the automation fleet operate a brownfield project unattended."
|
|
3
3
|
argument-hint: "[path]"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
Use the /lisa-agent-ready skill to build the initial knowledge wiki
|
|
6
|
+
Use the /lisa-agent-ready skill to build the initial knowledge wiki through read-only, redacted ingestion of every inventoried source, persist each source's complete/partial/unavailable status, write the human-answerable gaps to wiki/gaps.md, absorb any answered gaps from a prior run, and report whether every source is complete with zero gaps or what still blocks readiness. $ARGUMENTS
|
|
@@ -30,8 +30,9 @@ The rules that follow from this:
|
|
|
30
30
|
agents must be visible to all of them.
|
|
31
31
|
|
|
32
32
|
Brownfield on-ramp: an existing codebase becomes agent-ready **before** the fleet runs unattended
|
|
33
|
-
— `/lisa:agent-ready` converges human knowledge
|
|
34
|
-
standards adoption refactors to
|
|
33
|
+
— `/lisa:agent-ready` converges human knowledge through read-only, redacted source ingestion (every
|
|
34
|
+
source must be complete and the gaps loop must reach none), then standards adoption refactors to
|
|
35
|
+
conformance without behavior change.
|
|
35
36
|
|
|
36
37
|
End state: end users have zero direct contact with coding agents — they interact with the tracker,
|
|
37
38
|
the PRD source, and the shipped software.
|
|
@@ -272,6 +272,7 @@ Each vendor section is **conditionally required**: required only when that vendo
|
|
|
272
272
|
|-------|---------------|-------|
|
|
273
273
|
| `github.org` | `tracker = "github"` or `source = "github"` or any `github-*` skill is invoked | GitHub organization or user name. |
|
|
274
274
|
| `github.repo` | same as above | GitHub repository name. |
|
|
275
|
+
| `github.queueRepo` | no | Optional GitHub **build** queue repository, distinct from this repo's identity and PRD source. Store the canonical `owner/repo`. A short repo name is accepted at runtime and normalized to `github.org`. Explicit GitHub repo/URL arguments always win; otherwise GitHub build intake, build repair, build queue status, and scheduled ticket commands use this value, falling back to `github.org/github.repo` when absent. This never changes `repo:<name>` scoping, PRD intake, or automation naming, which remain tied to `repo` / `github.repo`. |
|
|
275
276
|
| `github.projects.v2.owner.kind` | GitHub Project coordination is enabled | Owner type for the shared ProjectV2. Supported values are `organization` and `user`. |
|
|
276
277
|
| `github.projects.v2.owner.slug` | GitHub Project coordination is enabled | Owner login for the shared ProjectV2. In v1 it MUST match the tracked repository namespace (`github.org`); cross-namespace coordination is rejected. |
|
|
277
278
|
| `github.projects.v2.number` | GitHub Project coordination is enabled | Human-facing ProjectV2 number from the GitHub UI / URL. Later utilities resolve the opaque node id from this owner + number pair. |
|
|
@@ -285,6 +286,13 @@ Each vendor section is **conditionally required**: required only when that vendo
|
|
|
285
286
|
|
|
286
287
|
When `tracker = "github"` AND `source = "github"` (self-host), both reads and writes hit the same GitHub repo. Label namespaces are kept separate so the two flows don't collide — see "Self-host edge case" below.
|
|
287
288
|
|
|
289
|
+
When `github.queueRepo` points at an umbrella repository, build-queue **scans** happen there while the
|
|
290
|
+
current repository's identity remains `github.org/github.repo`. Resolve a GitHub queue in this
|
|
291
|
+
order for a build-mode scan: explicit `owner/repo` or GitHub URL argument, merged-config `github.queueRepo`, then
|
|
292
|
+
`github.org/github.repo`. Queue status must show both identity and queue; build counts and claims
|
|
293
|
+
remain filtered to `repo:<github.repo>`. Setup writes the canonical `owner/repo` form and omits the
|
|
294
|
+
key when the queue is the identity repo.
|
|
295
|
+
|
|
288
296
|
`github.projects.v2` is optional. When absent, GitHub issue / PR writes remain repository-local exactly as they work today. When present, the shared Project is a coordination view layered on top of real issues and pull requests; it does not replace lifecycle labels, comments, dependencies, or native issue / PR state as Lisa's durable source of truth.
|
|
289
297
|
|
|
290
298
|
When `github.projects.v2` is present, later setup/doctor and writer preflight validation MUST read the referenced Project's owner + access level before any membership write depends on it. The validation contract is:
|
|
@@ -77,12 +77,16 @@ Greenfield projects are agent-ready by construction. A brownfield project must e
|
|
|
77
77
|
two ordered steps before the automation fleet runs unattended:
|
|
78
78
|
|
|
79
79
|
1. **Knowledge convergence** (`/lisa:agent-ready`): build the initial knowledge wiki from every
|
|
80
|
-
|
|
80
|
+
inventoried source — repository, git history, tracker, connected systems — under the operating
|
|
81
81
|
premise *"starting tomorrow, you maintain this project without human input; today is your only
|
|
82
|
-
chance to ask questions."*
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
82
|
+
chance to ask questions."* Connected sources are untrusted and read-only; secrets, credentials,
|
|
83
|
+
and policy-detected sensitive PII are redacted, while ordinary person-level user data is omitted
|
|
84
|
+
or aggregated before any wiki persistence. Every source records `complete`, `partial`, or
|
|
85
|
+
`unavailable`, and incomplete access remains linked to an unresolved gap. Everything derivable is
|
|
86
|
+
derived and written into the wiki; what only a human can answer becomes a product-readable entry
|
|
87
|
+
in `wiki/gaps.md`. Humans answer inline, a **fresh session** re-runs the skill, verified answers are
|
|
88
|
+
absorbed into wiki pages, and the loop repeats until every source is complete and a run reports
|
|
89
|
+
zero open gaps.
|
|
86
90
|
2. **Standards adoption**: apply Lisa's full lint rules, guardrails, and thresholds — the project
|
|
87
91
|
goes red by design — then refactor to conformance **without changing business logic or
|
|
88
92
|
functionality**, via the improve/fix flows, with behavior preservation proven by tests and
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
import {
|
|
12
12
|
resolveBuildQueueArgument,
|
|
13
|
+
resolveGithubQueueRepoRef,
|
|
13
14
|
resolveGithubRepoRef,
|
|
14
15
|
resolvePrdQueueArgument,
|
|
15
16
|
resolvePrdSource,
|
|
@@ -119,9 +120,32 @@ export function resolveExpectedAutomationFleet(input = {}) {
|
|
|
119
120
|
|
|
120
121
|
const tracker = config.tracker;
|
|
121
122
|
const source = resolvePrdSource(config);
|
|
122
|
-
const
|
|
123
|
-
const
|
|
124
|
-
|
|
123
|
+
const explicitGithubIdentity = `${identity.owner}/${identity.repo}`;
|
|
124
|
+
const githubQueue =
|
|
125
|
+
tracker === "github"
|
|
126
|
+
? resolveGithubQueueRepoRef(config, {
|
|
127
|
+
gitRemoteUrl: input.gitRemoteUrl,
|
|
128
|
+
})
|
|
129
|
+
: null;
|
|
130
|
+
const explicitGithubQueue = githubQueue
|
|
131
|
+
? `${githubQueue.owner}/${githubQueue.repo}`
|
|
132
|
+
: undefined;
|
|
133
|
+
const prdQueue =
|
|
134
|
+
source === "github"
|
|
135
|
+
? `${explicitGithubIdentity} intake_mode=prd`
|
|
136
|
+
: resolvePrdQueueArgument(config, source);
|
|
137
|
+
const buildQueue = resolveBuildQueueArgument(config, tracker, {
|
|
138
|
+
explicitQueue: tracker === "github" ? explicitGithubQueue : undefined,
|
|
139
|
+
gitRemoteUrl: input.gitRemoteUrl,
|
|
140
|
+
});
|
|
141
|
+
const repairQueue = resolveRepairQueueArgument(
|
|
142
|
+
config,
|
|
143
|
+
source,
|
|
144
|
+
tracker,
|
|
145
|
+
explicitGithubIdentity,
|
|
146
|
+
explicitGithubQueue,
|
|
147
|
+
buildQueue
|
|
148
|
+
);
|
|
125
149
|
|
|
126
150
|
const expected = [
|
|
127
151
|
createExpectedEntry(
|
|
@@ -237,10 +261,17 @@ function createUnsupportedEntry(identity, id, reason) {
|
|
|
237
261
|
* @param {string | undefined} tracker
|
|
238
262
|
* @returns {string}
|
|
239
263
|
*/
|
|
240
|
-
function resolveRepairQueueArgument(
|
|
264
|
+
function resolveRepairQueueArgument(
|
|
265
|
+
config,
|
|
266
|
+
source,
|
|
267
|
+
tracker,
|
|
268
|
+
explicitGithubIdentity,
|
|
269
|
+
explicitGithubQueue,
|
|
270
|
+
resolvedBuildQueue
|
|
271
|
+
) {
|
|
241
272
|
if (tracker === "github" && source === "github") {
|
|
242
273
|
requireGithubRepo(config);
|
|
243
|
-
return
|
|
274
|
+
return `${explicitGithubIdentity} intake_mode=both build_queue=${explicitGithubQueue}`;
|
|
244
275
|
}
|
|
245
276
|
|
|
246
277
|
if (tracker === "linear" && source === "linear") {
|
|
@@ -260,13 +291,12 @@ function resolveRepairQueueArgument(config, source, tracker) {
|
|
|
260
291
|
|
|
261
292
|
if (tracker === "github" && source === undefined) {
|
|
262
293
|
requireGithubRepo(config);
|
|
263
|
-
return
|
|
294
|
+
return `${explicitGithubIdentity} intake_mode=both build_queue=${explicitGithubQueue}`;
|
|
264
295
|
}
|
|
265
296
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
: `${buildQueue} intake_mode=build`;
|
|
297
|
+
return resolvedBuildQueue.includes("intake_mode=")
|
|
298
|
+
? resolvedBuildQueue
|
|
299
|
+
: `${resolvedBuildQueue} intake_mode=build`;
|
|
270
300
|
}
|
|
271
301
|
|
|
272
302
|
/**
|
|
@@ -173,12 +173,17 @@ export function resolvePrdQueueArgument(
|
|
|
173
173
|
*/
|
|
174
174
|
export function resolveBuildQueueArgument(
|
|
175
175
|
config = {},
|
|
176
|
-
tracker = resolveBuildTracker(config)
|
|
176
|
+
tracker = resolveBuildTracker(config),
|
|
177
|
+
options = {}
|
|
177
178
|
) {
|
|
178
179
|
switch (tracker) {
|
|
179
|
-
case "github":
|
|
180
|
-
|
|
180
|
+
case "github": {
|
|
181
|
+
const queue = resolveGithubQueueRepoRef(config, options);
|
|
182
|
+
if (options.explicitQueue || config.github?.queueRepo) {
|
|
183
|
+
return `${queue.owner}/${queue.repo} intake_mode=build`;
|
|
184
|
+
}
|
|
181
185
|
return "github intake_mode=build";
|
|
186
|
+
}
|
|
182
187
|
case "linear":
|
|
183
188
|
requireLinearWorkspace(config);
|
|
184
189
|
return "linear";
|
|
@@ -340,6 +345,14 @@ export function resolveQueueContract(input = {}) {
|
|
|
340
345
|
const source = resolvePrdSource(config);
|
|
341
346
|
const tracker = resolveBuildTracker(config);
|
|
342
347
|
|
|
348
|
+
const githubIdentity = resolveGithubRepoRef(config, input.gitRemoteUrl);
|
|
349
|
+
const githubQueue =
|
|
350
|
+
tracker === "github"
|
|
351
|
+
? resolveGithubQueueRepoRef(config, {
|
|
352
|
+
gitRemoteUrl: input.gitRemoteUrl,
|
|
353
|
+
})
|
|
354
|
+
: null;
|
|
355
|
+
|
|
343
356
|
return {
|
|
344
357
|
currentRepo: resolveCurrentRepo(input),
|
|
345
358
|
source,
|
|
@@ -349,7 +362,15 @@ export function resolveQueueContract(input = {}) {
|
|
|
349
362
|
...resolvePrdLifecycleRoles(config, source),
|
|
350
363
|
},
|
|
351
364
|
buildQueue: {
|
|
352
|
-
argument: resolveBuildQueueArgument(config, tracker
|
|
365
|
+
argument: resolveBuildQueueArgument(config, tracker, {
|
|
366
|
+
gitRemoteUrl: input.gitRemoteUrl,
|
|
367
|
+
}),
|
|
368
|
+
...(tracker === "github"
|
|
369
|
+
? {
|
|
370
|
+
identityRepo: `${githubIdentity.owner}/${githubIdentity.repo}`,
|
|
371
|
+
queueRepo: `${githubQueue.owner}/${githubQueue.repo}`,
|
|
372
|
+
}
|
|
373
|
+
: {}),
|
|
353
374
|
...resolveBuildLifecycleRoles(config, tracker),
|
|
354
375
|
},
|
|
355
376
|
};
|
|
@@ -408,6 +429,54 @@ export function resolveGithubRepoRef(config = {}, gitRemoteUrl) {
|
|
|
408
429
|
return null;
|
|
409
430
|
}
|
|
410
431
|
|
|
432
|
+
/**
|
|
433
|
+
* Resolve the GitHub queue without changing the repository identity used
|
|
434
|
+
* for automation names and `repo:<name>` claim scoping. An explicit invocation
|
|
435
|
+
* target wins, followed by `github.queueRepo`, then the identity repo.
|
|
436
|
+
*
|
|
437
|
+
* `github.queueRepo` may be a short repo name (normalized to the identity
|
|
438
|
+
* owner) or an `owner/repo` reference. Cross-owner queues therefore remain
|
|
439
|
+
* explicit while the common same-organization umbrella layout stays concise.
|
|
440
|
+
*
|
|
441
|
+
* @param {Record<string, any>} config
|
|
442
|
+
* @param {{ readonly explicitQueue?: string, readonly gitRemoteUrl?: string }} [options]
|
|
443
|
+
* @returns {{ readonly owner: string, readonly repo: string }}
|
|
444
|
+
*/
|
|
445
|
+
export function resolveGithubQueueRepoRef(config = {}, options = {}) {
|
|
446
|
+
const identity = resolveGithubRepoRef(config, options.gitRemoteUrl);
|
|
447
|
+
if (!identity) {
|
|
448
|
+
throw new Error(
|
|
449
|
+
"Unable to resolve the GitHub repository identity: github.org/github.repo or a GitHub origin remote is required."
|
|
450
|
+
);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
const configured = options.explicitQueue ?? config.github?.queueRepo;
|
|
454
|
+
if (configured === undefined || configured === null || configured === "") {
|
|
455
|
+
return identity;
|
|
456
|
+
}
|
|
457
|
+
if (typeof configured !== "string") {
|
|
458
|
+
throw new Error(
|
|
459
|
+
"Unable to resolve the GitHub queue: github.queueRepo must be a repo name or owner/repo."
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
const value = configured
|
|
464
|
+
.trim()
|
|
465
|
+
.replace(/^https:\/\/github\.com\//i, "")
|
|
466
|
+
.replace(/\.git$/i, "");
|
|
467
|
+
const parts = value.split("/").filter(Boolean);
|
|
468
|
+
if (parts.length === 1) {
|
|
469
|
+
return { owner: identity.owner, repo: parts[0] };
|
|
470
|
+
}
|
|
471
|
+
if (parts.length === 2) {
|
|
472
|
+
return { owner: parts[0], repo: parts[1] };
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
throw new Error(
|
|
476
|
+
"Unable to resolve the GitHub queue: github.queueRepo must be a repo name or owner/repo."
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
|
|
411
480
|
/**
|
|
412
481
|
* @param {string | undefined} gitRemoteUrl
|
|
413
482
|
* @returns {string | null}
|
|
@@ -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
|
|
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
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
/**
|