ghostrail 0.15.2 → 0.17.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 +12 -9
- package/dist/agent/claude-code.d.ts.map +1 -1
- package/dist/agent/claude-code.js +4 -1
- package/dist/agent/claude-code.js.map +1 -1
- package/dist/board/page.d.ts +1 -1
- package/dist/board/page.d.ts.map +1 -1
- package/dist/board/page.js +2 -1
- package/dist/board/page.js.map +1 -1
- package/dist/board/server.d.ts +1 -1
- package/dist/board/server.d.ts.map +1 -1
- package/dist/board/server.js +7 -1
- package/dist/board/server.js.map +1 -1
- package/dist/board/stats.d.ts +1 -1
- package/dist/board/stats.d.ts.map +1 -1
- package/dist/board/stats.js +2 -1
- package/dist/board/stats.js.map +1 -1
- package/dist/claude-profile/index.d.ts +1 -1
- package/dist/claude-profile/index.d.ts.map +1 -1
- package/dist/claude-profile/index.js +1 -1
- package/dist/claude-profile/index.js.map +1 -1
- package/dist/claude-profile/setup.d.ts +7 -0
- package/dist/claude-profile/setup.d.ts.map +1 -1
- package/dist/claude-profile/setup.js +7 -0
- package/dist/claude-profile/setup.js.map +1 -1
- package/dist/cli/commands.d.ts +6 -0
- package/dist/cli/commands.d.ts.map +1 -1
- package/dist/cli/commands.js +204 -18
- package/dist/cli/commands.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +3 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/help.d.ts.map +1 -1
- package/dist/commands/help.js +15 -3
- package/dist/commands/help.js.map +1 -1
- package/dist/config/load.d.ts.map +1 -1
- package/dist/config/load.js +18 -2
- package/dist/config/load.js.map +1 -1
- package/dist/config/schema.d.ts +8 -2
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js.map +1 -1
- package/dist/dashboard/page.d.ts +7 -1
- package/dist/dashboard/page.d.ts.map +1 -1
- package/dist/dashboard/page.js +204 -39
- package/dist/dashboard/page.js.map +1 -1
- package/dist/dashboard/routes.d.ts +32 -0
- package/dist/dashboard/routes.d.ts.map +1 -1
- package/dist/dashboard/routes.js +45 -0
- package/dist/dashboard/routes.js.map +1 -1
- package/dist/dashboard/server.d.ts +35 -9
- package/dist/dashboard/server.d.ts.map +1 -1
- package/dist/dashboard/server.js +75 -11
- package/dist/dashboard/server.js.map +1 -1
- package/dist/doctor/checks.d.ts +87 -0
- package/dist/doctor/checks.d.ts.map +1 -0
- package/dist/doctor/checks.js +414 -0
- package/dist/doctor/checks.js.map +1 -0
- package/dist/doctor/index.d.ts +6 -0
- package/dist/doctor/index.d.ts.map +1 -0
- package/dist/doctor/index.js +5 -0
- package/dist/doctor/index.js.map +1 -0
- package/dist/doctor/probes.d.ts +42 -0
- package/dist/doctor/probes.d.ts.map +1 -0
- package/dist/doctor/probes.js +136 -0
- package/dist/doctor/probes.js.map +1 -0
- package/dist/doctor/report.d.ts +13 -0
- package/dist/doctor/report.d.ts.map +1 -0
- package/dist/doctor/report.js +32 -0
- package/dist/doctor/report.js.map +1 -0
- package/dist/doctor/run.d.ts +48 -0
- package/dist/doctor/run.d.ts.map +1 -0
- package/dist/doctor/run.js +109 -0
- package/dist/doctor/run.js.map +1 -0
- package/dist/doctor/types.d.ts +17 -0
- package/dist/doctor/types.d.ts.map +1 -0
- package/dist/doctor/types.js +6 -0
- package/dist/doctor/types.js.map +1 -0
- package/dist/factory/build.d.ts.map +1 -1
- package/dist/factory/build.js +1 -0
- package/dist/factory/build.js.map +1 -1
- package/dist/init/regions.d.ts +76 -0
- package/dist/init/regions.d.ts.map +1 -0
- package/dist/init/regions.js +247 -0
- package/dist/init/regions.js.map +1 -0
- package/dist/init/template.d.ts +7 -1
- package/dist/init/template.d.ts.map +1 -1
- package/dist/init/template.js +37 -2
- package/dist/init/template.js.map +1 -1
- package/dist/loop/budget.d.ts +11 -2
- package/dist/loop/budget.d.ts.map +1 -1
- package/dist/loop/budget.js +13 -3
- package/dist/loop/budget.js.map +1 -1
- package/dist/loop/comments.d.ts +20 -0
- package/dist/loop/comments.d.ts.map +1 -0
- package/dist/loop/comments.js +35 -0
- package/dist/loop/comments.js.map +1 -0
- package/dist/loop/engine.d.ts.map +1 -1
- package/dist/loop/engine.js +18 -0
- package/dist/loop/engine.js.map +1 -1
- package/dist/loop/index.d.ts +1 -0
- package/dist/loop/index.d.ts.map +1 -1
- package/dist/loop/index.js +1 -0
- package/dist/loop/index.js.map +1 -1
- package/dist/publish/gh.d.ts +8 -0
- package/dist/publish/gh.d.ts.map +1 -1
- package/dist/publish/gh.js +12 -0
- package/dist/publish/gh.js.map +1 -1
- package/dist/publish/githost.d.ts +8 -0
- package/dist/publish/githost.d.ts.map +1 -1
- package/dist/publish/githost.js.map +1 -1
- package/dist/publish/index.d.ts +1 -1
- package/dist/publish/index.d.ts.map +1 -1
- package/dist/publish/index.js +1 -1
- package/dist/publish/index.js.map +1 -1
- package/dist/respond/index.d.ts +3 -2
- package/dist/respond/index.d.ts.map +1 -1
- package/dist/respond/index.js +3 -2
- package/dist/respond/index.js.map +1 -1
- package/dist/respond/merge.d.ts +13 -0
- package/dist/respond/merge.d.ts.map +1 -0
- package/dist/respond/merge.js +181 -0
- package/dist/respond/merge.js.map +1 -0
- package/dist/respond/respond.d.ts +25 -5
- package/dist/respond/respond.d.ts.map +1 -1
- package/dist/respond/respond.js +57 -28
- package/dist/respond/respond.js.map +1 -1
- package/dist/respond/select.d.ts +15 -0
- package/dist/respond/select.d.ts.map +1 -1
- package/dist/respond/select.js +17 -0
- package/dist/respond/select.js.map +1 -1
- package/dist/source/dependencies.d.ts +81 -0
- package/dist/source/dependencies.d.ts.map +1 -0
- package/dist/source/dependencies.js +218 -0
- package/dist/source/dependencies.js.map +1 -0
- package/dist/source/index.d.ts +1 -0
- package/dist/source/index.d.ts.map +1 -1
- package/dist/source/index.js +1 -0
- package/dist/source/index.js.map +1 -1
- package/dist/source/linear.d.ts +17 -1
- package/dist/source/linear.d.ts.map +1 -1
- package/dist/source/linear.js +75 -9
- package/dist/source/linear.js.map +1 -1
- package/dist/store/events.d.ts +8 -0
- package/dist/store/events.d.ts.map +1 -1
- package/dist/store/events.js +10 -0
- package/dist/store/events.js.map +1 -1
- package/dist/store/file-store.d.ts +1 -1
- package/dist/store/file-store.d.ts.map +1 -1
- package/dist/store/file-store.js +7 -0
- package/dist/store/file-store.js.map +1 -1
- package/dist/store/index.d.ts +1 -1
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +1 -1
- package/dist/store/index.js.map +1 -1
- package/dist/store/port.d.ts +15 -0
- package/dist/store/port.d.ts.map +1 -1
- package/dist/store/port.js +17 -1
- package/dist/store/port.js.map +1 -1
- package/dist/triage/engine.d.ts.map +1 -1
- package/dist/triage/engine.js +2 -0
- package/dist/triage/engine.js.map +1 -1
- package/package.json +3 -1
- package/skill/ghostrail/SKILL.md +94 -43
- package/templates/code/prompts/resolve-issue.md +20 -4
- package/templates/code/prompts/respond.md +4 -0
- package/templates/code/prompts/triage.md +13 -0
- package/templates/content/prompts/draft.md +13 -0
- package/templates/content/prompts/respond.md +4 -0
package/dist/respond/respond.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { writeWorkspaceFile } from "../backend/fs.js";
|
|
2
2
|
import { mapWithConcurrency } from "../loop/concurrency.js";
|
|
3
3
|
import { GHOSTRAIL_MARKER, gitStageAllArgs, } from "../publish/githost.js";
|
|
4
|
-
import {
|
|
4
|
+
import { resolveConflictsAndMergeSafely } from "./merge.js";
|
|
5
|
+
import { isMergeCommand, latestTimestamp, selectNewComments } from "./select.js";
|
|
5
6
|
/** Where the respond pass drops the human feedback for the agent to read. */
|
|
6
7
|
export const FEEDBACK_PATH = ".ghostrail/feedback.md";
|
|
7
8
|
const nullLogger = { info: () => { }, warn: () => { } };
|
|
@@ -31,26 +32,61 @@ function noopComment(reason) {
|
|
|
31
32
|
return reason === undefined ? opening : `${opening}\n\n${reason}`;
|
|
32
33
|
}
|
|
33
34
|
/** Comment body ghostrail posts, always carrying the marker so it never re-reads its own. */
|
|
34
|
-
function markedComment(body) {
|
|
35
|
+
export function markedComment(body) {
|
|
35
36
|
return `${body}\n\n${GHOSTRAIL_MARKER}`;
|
|
36
37
|
}
|
|
37
38
|
/**
|
|
38
39
|
* The respond pass: for every open factory PR, act only on human comments newer
|
|
39
40
|
* than the per-PR watermark that do not carry the ghostrail marker (so it never
|
|
40
|
-
* acts on its own).
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
41
|
+
* acts on its own). A PR whose fresh comments ask the factory to resolve
|
|
42
|
+
* conflicts and merge (see {@link isMergeCommand}) is routed to that flow
|
|
43
|
+
* instead of the ordinary one; every other PR gets its new feedback handed to
|
|
44
|
+
* the agent, and — on a successful change — committed, pushed to the same
|
|
45
|
+
* branch, and summarized in a comment. The ordinary flow never opens a new PR
|
|
46
|
+
* and never merges. The watermark advances once a PR's new comments have been
|
|
47
|
+
* handled, on every path (success, blocked, or failed).
|
|
44
48
|
*/
|
|
45
49
|
export async function respondTick(deps, config) {
|
|
46
50
|
const logger = deps.logger ?? nullLogger;
|
|
47
51
|
const prs = await deps.host.listOpenPrs(config.label);
|
|
48
52
|
logger.info(`respond: ${prs.length} open ${config.label} PR(s)`);
|
|
53
|
+
// Fresh comments are read once per PR, up front, so the merge-command check
|
|
54
|
+
// below and the flow it dispatches to never re-fetch or re-filter them.
|
|
55
|
+
const withFresh = await mapWithConcurrency(prs, config.guardrails.concurrency, async (pr) => ({
|
|
56
|
+
pr,
|
|
57
|
+
fresh: await freshCommentsFor(deps, config, pr, logger),
|
|
58
|
+
}));
|
|
59
|
+
const mergeRequests = withFresh.filter(({ fresh }) => fresh.some((c) => isMergeCommand(c.body)));
|
|
60
|
+
const normal = withFresh.filter(({ fresh }) => !fresh.some((c) => isMergeCommand(c.body)));
|
|
61
|
+
// Merge requests are pipelined one at a time regardless of the configured
|
|
62
|
+
// concurrency: two of them racing the same base branch would only worsen the
|
|
63
|
+
// conflict situation this feature exists to fix.
|
|
64
|
+
const mergeResults = await mapWithConcurrency(mergeRequests, 1, ({ pr, fresh }) => resolveConflictsAndMergeSafely(deps, config, pr, fresh, logger));
|
|
49
65
|
// Same helper the fix loop and triage use, on the same guardrail. Each PR is
|
|
50
66
|
// an independent agent run of comparable cost and duration, so a sequential
|
|
51
67
|
// pass took as long as the sum of them, and this is the pass a human is most
|
|
52
68
|
// likely to be waiting on: it exists to answer review comments.
|
|
53
|
-
|
|
69
|
+
const normalResults = await mapWithConcurrency(normal, config.guardrails.concurrency, ({ pr, fresh }) => respondToPrSafely(deps, config, pr, fresh, logger));
|
|
70
|
+
const byNumber = new Map([...mergeResults, ...normalResults].map((result) => [result.prNumber, result]));
|
|
71
|
+
return prs
|
|
72
|
+
.map((pr) => byNumber.get(pr.number))
|
|
73
|
+
.filter((result) => result !== undefined);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The human comments a PR's next respond pass should act on: PR comments plus
|
|
77
|
+
* (when a tracker source is wired in) new comments on the issue the PR's
|
|
78
|
+
* branch encodes, filtered to fresh, non-self, unmarked ones.
|
|
79
|
+
*/
|
|
80
|
+
async function freshCommentsFor(deps, config, pr, logger) {
|
|
81
|
+
const prComments = await deps.host.listComments(pr.number);
|
|
82
|
+
const trackerComments = await listTrackerComments(deps, pr, logger);
|
|
83
|
+
const comments = [...prComments, ...trackerComments];
|
|
84
|
+
const since = await deps.watermarks.get(pr.number);
|
|
85
|
+
return selectNewComments(comments, {
|
|
86
|
+
selfLogins: config.selfLogins,
|
|
87
|
+
marker: GHOSTRAIL_MARKER,
|
|
88
|
+
...(since === undefined ? {} : { since }),
|
|
89
|
+
});
|
|
54
90
|
}
|
|
55
91
|
/**
|
|
56
92
|
* `respondToPr`, guaranteed not to throw.
|
|
@@ -61,9 +97,9 @@ export async function respondTick(deps, config) {
|
|
|
61
97
|
* meet it too. One PR whose host lookup fails is one failed result, not a dead
|
|
62
98
|
* pass.
|
|
63
99
|
*/
|
|
64
|
-
async function respondToPrSafely(deps, config, pr, logger) {
|
|
100
|
+
async function respondToPrSafely(deps, config, pr, fresh, logger) {
|
|
65
101
|
try {
|
|
66
|
-
return await respondToPr(deps, config, pr, logger);
|
|
102
|
+
return await respondToPr(deps, config, pr, fresh, logger);
|
|
67
103
|
}
|
|
68
104
|
catch (error) {
|
|
69
105
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -92,16 +128,7 @@ async function listTrackerComments(deps, pr, logger) {
|
|
|
92
128
|
return [];
|
|
93
129
|
}
|
|
94
130
|
}
|
|
95
|
-
async function respondToPr(deps, config, pr, logger) {
|
|
96
|
-
const prComments = await deps.host.listComments(pr.number);
|
|
97
|
-
const trackerComments = await listTrackerComments(deps, pr, logger);
|
|
98
|
-
const comments = [...prComments, ...trackerComments];
|
|
99
|
-
const since = await deps.watermarks.get(pr.number);
|
|
100
|
-
const fresh = selectNewComments(comments, {
|
|
101
|
-
selfLogins: config.selfLogins,
|
|
102
|
-
marker: GHOSTRAIL_MARKER,
|
|
103
|
-
...(since === undefined ? {} : { since }),
|
|
104
|
-
});
|
|
131
|
+
async function respondToPr(deps, config, pr, fresh, logger) {
|
|
105
132
|
if (fresh.length === 0) {
|
|
106
133
|
return { prNumber: pr.number, state: "noop" };
|
|
107
134
|
}
|
|
@@ -161,7 +188,7 @@ async function routeRespond(deps, pr, workspace, outcome, logger) {
|
|
|
161
188
|
await deps.host.postComment(pr.number, markedComment(noopComment(outcome.reason)));
|
|
162
189
|
return { prNumber: pr.number, state: "noop" };
|
|
163
190
|
case "done": {
|
|
164
|
-
const committed = await commitAndPush(deps.backend, workspace);
|
|
191
|
+
const committed = await commitAndPush(deps.backend, workspace, "respond: address review feedback");
|
|
165
192
|
if (!committed) {
|
|
166
193
|
await deps.host.postComment(pr.number, markedComment("No changes were needed for the latest feedback."));
|
|
167
194
|
return { prNumber: pr.number, state: "noop" };
|
|
@@ -172,20 +199,22 @@ async function routeRespond(deps, pr, workspace, outcome, logger) {
|
|
|
172
199
|
}
|
|
173
200
|
}
|
|
174
201
|
}
|
|
175
|
-
/**
|
|
176
|
-
|
|
202
|
+
/**
|
|
203
|
+
* Commit (with `message`) and push the workspace's changes to its branch.
|
|
204
|
+
* Returns false if there was nothing to commit. Shared with the
|
|
205
|
+
* resolve-conflicts-and-merge flow, where `message` names the merge rather
|
|
206
|
+
* than the feedback that prompted it, and a conflicted merge's resolution is
|
|
207
|
+
* committed the same way an ordinary feedback change is: stage everything but
|
|
208
|
+
* the scratch dir, then commit.
|
|
209
|
+
*/
|
|
210
|
+
export async function commitAndPush(backend, workspace, message) {
|
|
177
211
|
for (const args of gitStageAllArgs()) {
|
|
178
212
|
const staged = await backend.exec(workspace, ["git", ...args]);
|
|
179
213
|
if (staged.exitCode !== 0) {
|
|
180
214
|
throw new Error(`git ${args.join(" ")} failed: ${staged.stderr.trim() || staged.stdout.trim()}`);
|
|
181
215
|
}
|
|
182
216
|
}
|
|
183
|
-
const commit = await backend.exec(workspace, [
|
|
184
|
-
"git",
|
|
185
|
-
"commit",
|
|
186
|
-
"-m",
|
|
187
|
-
"respond: address review feedback",
|
|
188
|
-
]);
|
|
217
|
+
const commit = await backend.exec(workspace, ["git", "commit", "-m", message]);
|
|
189
218
|
if (commit.exitCode !== 0)
|
|
190
219
|
return false;
|
|
191
220
|
const push = await backend.exec(workspace, ["git", "push", "origin", workspace.branch]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"respond.js","sourceRoot":"","sources":["../../src/respond/respond.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAGtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,OAAO,EACL,gBAAgB,EAIhB,eAAe,GAChB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"respond.js","sourceRoot":"","sources":["../../src/respond/respond.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAGtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,OAAO,EACL,gBAAgB,EAIhB,eAAe,GAChB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,8BAA8B,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAGjF,6EAA6E;AAC7E,MAAM,CAAC,MAAM,aAAa,GAAG,wBAAwB,CAAC;AAEtD,MAAM,UAAU,GAAW,EAAE,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;AAsB9D,kFAAkF;AAClF,MAAM,WAAW,GAAG,qCAAqC,CAAC;AAE1D;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,UAAkB;IAC/C,MAAM,EAAE,GAAG,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7C,OAAO,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC;AACzD,CAAC;AAoBD,8EAA8E;AAC9E,MAAM,UAAU,cAAc,CAAC,QAA8B;IAC3D,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,MAAM,OAAO,CAAC,CAAC,SAAS,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAChG,OAAO,gCAAgC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;AACxE,CAAC;AAED;;;;GAIG;AACH,SAAS,WAAW,CAAC,MAA0B;IAC7C,MAAM,OAAO,GAAG,iDAAiD,CAAC;IAClE,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,OAAO,MAAM,EAAE,CAAC;AACpE,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,GAAG,IAAI,OAAO,gBAAgB,EAAE,CAAC;AAC1C,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAiB,EACjB,MAAqB;IAErB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,UAAU,CAAC;IACzC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACtD,MAAM,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,MAAM,SAAS,MAAM,CAAC,KAAK,QAAQ,CAAC,CAAC;IAEjE,4EAA4E;IAC5E,wEAAwE;IACxE,MAAM,SAAS,GAAG,MAAM,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC,WAAW,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QAC5F,EAAE;QACF,KAAK,EAAE,MAAM,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC;KACxD,CAAC,CAAC,CAAC;IAEJ,MAAM,aAAa,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjG,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAE3F,0EAA0E;IAC1E,6EAA6E;IAC7E,iDAAiD;IACjD,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAAC,aAAa,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAChF,8BAA8B,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAChE,CAAC;IACF,6EAA6E;IAC7E,4EAA4E;IAC5E,6EAA6E;IAC7E,gEAAgE;IAChE,MAAM,aAAa,GAAG,MAAM,kBAAkB,CAC5C,MAAM,EACN,MAAM,CAAC,UAAU,CAAC,WAAW,EAC7B,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CACtE,CAAC;IAEF,MAAM,QAAQ,GAAG,IAAI,GAAG,CACtB,CAAC,GAAG,YAAY,EAAE,GAAG,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAU,CAAC,CACxF,CAAC;IACF,OAAO,GAAG;SACP,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;SACpC,MAAM,CAAC,CAAC,MAAM,EAA2B,EAAE,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;AACvE,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,gBAAgB,CAC7B,IAAiB,EACjB,MAAqB,EACrB,EAAU,EACV,MAAc;IAEd,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;IAC3D,MAAM,eAAe,GAAG,MAAM,mBAAmB,CAAC,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;IACpE,MAAM,QAAQ,GAAG,CAAC,GAAG,UAAU,EAAE,GAAG,eAAe,CAAC,CAAC;IACrD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;IACnD,OAAO,iBAAiB,CAAC,QAAQ,EAAE;QACjC,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,MAAM,EAAE,gBAAgB;QACxB,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;KAC1C,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;GAQG;AACH,KAAK,UAAU,iBAAiB,CAC9B,IAAiB,EACjB,MAAqB,EACrB,EAAU,EACV,KAA2B,EAC3B,MAAc;IAEd,IAAI,CAAC;QACH,OAAO,MAAM,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IAC5D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC,CAAC;QACjD,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;IACpE,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,mBAAmB,CAChC,IAAiB,EACjB,EAAU,EACV,MAAc;IAEd,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,cAAc,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC;IAC9C,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACrC,IAAI,CAAC;QACH,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,OAAO,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;IACjG,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,CAAC,IAAI,CACT,YAAY,EAAE,CAAC,MAAM,yCAAyC,OAAO,KAAK,OAAO,EAAE,CACpF,CAAC;QACF,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,WAAW,CACxB,IAAiB,EACjB,MAAqB,EACrB,EAAU,EACV,KAA2B,EAC3B,MAAc;IAEd,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChD,CAAC;IAED,IAAI,SAAgC,CAAC;IACrC,IAAI,CAAC;QACH,SAAS,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;YACvC,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,UAAU,EAAE,EAAE,CAAC,UAAU;YACzB,MAAM,EAAE,EAAE,CAAC,UAAU;YACrB,IAAI,EAAE,QAAQ;YACd,GAAG,CAAC,IAAI,CAAC,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC;SACtF,CAAC,CAAC;QACH,MAAM,kBAAkB,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;QAExF,MAAM,IAAI,GAAa;YACrB,EAAE,EAAE,MAAM,EAAE,CAAC,MAAM,EAAE;YACrB,KAAK,EAAE,kBAAkB,EAAE,CAAC,MAAM,EAAE;YACpC,GAAG,EAAE,EAAE,CAAC,GAAG;SACZ,CAAC;QACF,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;YACnC,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,SAAS;YACT,IAAI;YACJ,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,UAAU,EAAE,MAAM,CAAC,UAAU;SAC9B,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAExE,MAAM,IAAI,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,IAAI,KAAK,SAAS;YAAE,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACnE,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,MAAM,cAAc,OAAO,EAAE,CAAC,CAAC;QAC1D,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;IACpE,CAAC;YAAS,CAAC;QACT,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;YACzC,CAAC;YAAC,MAAM,CAAC;gBACP,cAAc;YAChB,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,YAAY,CACzB,IAAiB,EACjB,EAAU,EACV,SAAoB,EACpB,OAAqB,EACrB,MAAc;IAEd,QAAQ,OAAO,CAAC,MAAM,EAAE,CAAC;QACvB,KAAK,SAAS;YACZ,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;YACzE,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC;QAE/E,KAAK,QAAQ;YACX,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,CACzB,EAAE,CAAC,MAAM,EACT,aAAa,CAAC,4DAA4D,OAAO,CAAC,KAAK,EAAE,CAAC,CAC3F,CAAC;YACF,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;QAE1E,KAAK,MAAM;YACT,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACnF,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAEhD,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,MAAM,SAAS,GAAG,MAAM,aAAa,CACnC,IAAI,CAAC,OAAO,EACZ,SAAS,EACT,kCAAkC,CACnC,CAAC;YACF,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,CACzB,EAAE,CAAC,MAAM,EACT,aAAa,CAAC,iDAAiD,CAAC,CACjE,CAAC;gBACF,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;YAChD,CAAC;YACD,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;YACvE,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,MAAM,oBAAoB,CAAC,CAAC;YACvD,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;QAC/E,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAAgB,EAChB,SAAoB,EACpB,OAAe;IAEf,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;QAC/D,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CACb,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAChF,CAAC;QACJ,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAC/E,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACxC,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACxF,IAAI,IAAI,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,oBAAoB,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAClF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/dist/respond/select.d.ts
CHANGED
|
@@ -14,6 +14,21 @@ export interface SelectOptions {
|
|
|
14
14
|
* Order is preserved.
|
|
15
15
|
*/
|
|
16
16
|
export declare function selectNewComments(comments: readonly PrComment[], options: SelectOptions): PrComment[];
|
|
17
|
+
/**
|
|
18
|
+
* The phrase a human types in a PR or tracker comment to ask the factory to
|
|
19
|
+
* resolve that PR's conflicts with the base branch and merge it. A plain
|
|
20
|
+
* phrase rather than an `@mention` or a `/command`: ghostrail posts through a
|
|
21
|
+
* personal or app token, not a mentionable bot identity, and the comment may
|
|
22
|
+
* come from a GitHub PR or a Linear issue, so the trigger has to read the
|
|
23
|
+
* same in both.
|
|
24
|
+
*/
|
|
25
|
+
export declare const MERGE_COMMAND_PHRASE = "resolve conflicts and merge";
|
|
26
|
+
/**
|
|
27
|
+
* True when `body` asks the factory to resolve conflicts and merge: a
|
|
28
|
+
* case-insensitive substring match, so the phrase can appear anywhere in a
|
|
29
|
+
* longer comment.
|
|
30
|
+
*/
|
|
31
|
+
export declare function isMergeCommand(body: string): boolean;
|
|
17
32
|
/**
|
|
18
33
|
* The latest `createdAt` across the comments (lexicographic max, valid for
|
|
19
34
|
* ISO-8601), or undefined when there are none. Used as the next watermark.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../src/respond/select.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,MAAM,WAAW,aAAa;IAC5B,gFAAgF;IAChF,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,SAAS,SAAS,EAAE,EAC9B,OAAO,EAAE,aAAa,GACrB,SAAS,EAAE,CAQb;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,SAAS,SAAS,EAAE,GAAG,MAAM,GAAG,SAAS,CAMlF"}
|
|
1
|
+
{"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../src/respond/select.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,MAAM,WAAW,aAAa;IAC5B,gFAAgF;IAChF,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,SAAS,SAAS,EAAE,EAC9B,OAAO,EAAE,aAAa,GACrB,SAAS,EAAE,CAQb;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,gCAAgC,CAAC;AAElE;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,SAAS,SAAS,EAAE,GAAG,MAAM,GAAG,SAAS,CAMlF"}
|
package/dist/respond/select.js
CHANGED
|
@@ -16,6 +16,23 @@ export function selectNewComments(comments, options) {
|
|
|
16
16
|
return true;
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* The phrase a human types in a PR or tracker comment to ask the factory to
|
|
21
|
+
* resolve that PR's conflicts with the base branch and merge it. A plain
|
|
22
|
+
* phrase rather than an `@mention` or a `/command`: ghostrail posts through a
|
|
23
|
+
* personal or app token, not a mentionable bot identity, and the comment may
|
|
24
|
+
* come from a GitHub PR or a Linear issue, so the trigger has to read the
|
|
25
|
+
* same in both.
|
|
26
|
+
*/
|
|
27
|
+
export const MERGE_COMMAND_PHRASE = "resolve conflicts and merge";
|
|
28
|
+
/**
|
|
29
|
+
* True when `body` asks the factory to resolve conflicts and merge: a
|
|
30
|
+
* case-insensitive substring match, so the phrase can appear anywhere in a
|
|
31
|
+
* longer comment.
|
|
32
|
+
*/
|
|
33
|
+
export function isMergeCommand(body) {
|
|
34
|
+
return body.toLowerCase().includes(MERGE_COMMAND_PHRASE);
|
|
35
|
+
}
|
|
19
36
|
/**
|
|
20
37
|
* The latest `createdAt` across the comments (lexicographic max, valid for
|
|
21
38
|
* ISO-8601), or undefined when there are none. Used as the next watermark.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"select.js","sourceRoot":"","sources":["../../src/respond/select.ts"],"names":[],"mappings":"AAWA;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAA8B,EAC9B,OAAsB;IAEtB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IAC7E,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE;QACjC,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YAAE,OAAO,KAAK,CAAC;QACzD,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,KAAK,CAAC;QACxD,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;QACpF,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,QAA8B;IAC5D,IAAI,MAA0B,CAAC;IAC/B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,GAAG,MAAM;YAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IACrF,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
1
|
+
{"version":3,"file":"select.js","sourceRoot":"","sources":["../../src/respond/select.ts"],"names":[],"mappings":"AAWA;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAA8B,EAC9B,OAAsB;IAEtB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IAC7E,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE;QACjC,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YAAE,OAAO,KAAK,CAAC;QACzD,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,KAAK,CAAC;QACxD,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;QACpF,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,6BAA6B,CAAC;AAElE;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC;AAC3D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,QAA8B;IAC5D,IAAI,MAA0B,CAAC;IAC/B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,GAAG,MAAM;YAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IACrF,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { EligibleFilter } from "../config/schema.js";
|
|
2
|
+
/** A blocking issue, resolved to just what dependency gating needs. */
|
|
3
|
+
export interface BlockerRef {
|
|
4
|
+
identifier: string;
|
|
5
|
+
/** Whether the blocker's workflow state is `completed` or `canceled`. */
|
|
6
|
+
done: boolean;
|
|
7
|
+
/** Whether the blocker itself carries the eligible label(s), directly or via its parent. */
|
|
8
|
+
inScope: boolean;
|
|
9
|
+
}
|
|
10
|
+
/** A child issue (Linear sub-issue) of a root, as fetched for dependency gating. */
|
|
11
|
+
export interface DependencyChild {
|
|
12
|
+
id: string;
|
|
13
|
+
identifier: string;
|
|
14
|
+
title: string;
|
|
15
|
+
url?: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
stateName?: string;
|
|
18
|
+
stateType?: string;
|
|
19
|
+
/** `null` when unassigned, `undefined` when the field was absent from the payload. */
|
|
20
|
+
assigneeId?: string | null;
|
|
21
|
+
assigneeEmail?: string;
|
|
22
|
+
blockers: BlockerRef[];
|
|
23
|
+
}
|
|
24
|
+
/** A top-level issue matching the eligible filter, with its children and blockers. */
|
|
25
|
+
export interface DependencyRoot {
|
|
26
|
+
id: string;
|
|
27
|
+
identifier: string;
|
|
28
|
+
title: string;
|
|
29
|
+
url?: string;
|
|
30
|
+
description?: string;
|
|
31
|
+
blockers: BlockerRef[];
|
|
32
|
+
children: DependencyChild[];
|
|
33
|
+
}
|
|
34
|
+
/** The minimal shape `resolveEpicDependencies` returns per workable/blocked item. */
|
|
35
|
+
export interface DependencyItem {
|
|
36
|
+
identifier: string;
|
|
37
|
+
title: string;
|
|
38
|
+
url?: string;
|
|
39
|
+
description?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface OutOfScopeBlock {
|
|
42
|
+
item: DependencyItem;
|
|
43
|
+
blockerIdentifier: string;
|
|
44
|
+
}
|
|
45
|
+
export interface DependencyDiscovery {
|
|
46
|
+
/** Items ready to run now, in discovery order. */
|
|
47
|
+
workable: DependencyItem[];
|
|
48
|
+
/** Items withheld because an incomplete blocker is outside the factory's scope. */
|
|
49
|
+
blockedOutOfScope: OutOfScopeBlock[];
|
|
50
|
+
}
|
|
51
|
+
/** Whether `labels` carries every name in `required` (vacuously true when `required` is empty). */
|
|
52
|
+
export declare function hasAllLabels(labels: string[], required: string[]): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Parse the `issues.nodes` payload from `ELIGIBLE_ISSUES_QUERY` into roots with
|
|
55
|
+
* their children and blockers. `required` is `[source].eligible.labels`, used
|
|
56
|
+
* to decide whether each blocker is in the factory's scope. Malformed nodes are
|
|
57
|
+
* skipped rather than thrown on: this is external data.
|
|
58
|
+
*/
|
|
59
|
+
export declare function parseDependencyRoots(data: Record<string, unknown>, required: string[]): DependencyRoot[];
|
|
60
|
+
export interface BlockerVerdict {
|
|
61
|
+
ready: boolean;
|
|
62
|
+
/** Set when blocked by something out of scope: that blocker's identifier. */
|
|
63
|
+
blockedBy?: string;
|
|
64
|
+
outOfScope: boolean;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Decide readiness from a candidate's blockers alone. Ready when every blocker
|
|
68
|
+
* is done. Otherwise: an incomplete out-of-scope blocker always wins (it is the
|
|
69
|
+
* hard-stop case), even alongside incomplete in-scope blockers; with only
|
|
70
|
+
* incomplete in-scope blockers, the candidate is quietly not ready yet.
|
|
71
|
+
*/
|
|
72
|
+
export declare function resolveBlockers(blockers: BlockerRef[]): BlockerVerdict;
|
|
73
|
+
/**
|
|
74
|
+
* Decide, per root, what's workable now and what's blocked on an out-of-scope
|
|
75
|
+
* dependency. A root with no children is a plain candidate on its own blockers.
|
|
76
|
+
* A root with children is an epic: it is never itself workable, and each
|
|
77
|
+
* eligible child (state/assignee-matching, not already done) is gated on its
|
|
78
|
+
* own blockers instead.
|
|
79
|
+
*/
|
|
80
|
+
export declare function resolveEpicDependencies(roots: DependencyRoot[], eligible: EligibleFilter, viewerId?: string): DependencyDiscovery;
|
|
81
|
+
//# sourceMappingURL=dependencies.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../../src/source/dependencies.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAc1E,uEAAuE;AACvE,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,IAAI,EAAE,OAAO,CAAC;IACd,4FAA4F;IAC5F,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,oFAAoF;AACpF,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sFAAsF;IACtF,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,UAAU,EAAE,CAAC;CACxB;AAED,sFAAsF;AACtF,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAED,qFAAqF;AACrF,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,cAAc,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,kDAAkD;IAClD,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,mFAAmF;IACnF,iBAAiB,EAAE,eAAe,EAAE,CAAC;CACtC;AAkBD,mGAAmG;AACnG,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAE1E;AAsFD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,QAAQ,EAAE,MAAM,EAAE,GACjB,cAAc,EAAE,CAUlB;AA+BD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,OAAO,CAAC;IACf,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,cAAc,CAQtE;AAgBD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,cAAc,EAAE,EACvB,QAAQ,EAAE,cAAc,EACxB,QAAQ,CAAC,EAAE,MAAM,GAChB,mBAAmB,CA2BrB"}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Epics and dependencies (TJ-1638): once an epic (an issue with children)
|
|
3
|
+
* carries the factory's label(s), its children become workable in their own
|
|
4
|
+
* right, gated by the `blocks` relations triage already records
|
|
5
|
+
* (`src/triage/apply.ts`). See `specs/epic-dependencies.spec.md`.
|
|
6
|
+
*
|
|
7
|
+
* Every function here is pure and driven off already-fetched GraphQL data, so
|
|
8
|
+
* it is testable without a network or a fake Linear server.
|
|
9
|
+
*/
|
|
10
|
+
const DONE_STATE_TYPES = new Set(["completed", "canceled"]);
|
|
11
|
+
function isRecord(value) {
|
|
12
|
+
return value !== null && typeof value === "object";
|
|
13
|
+
}
|
|
14
|
+
function parseLabelNames(raw) {
|
|
15
|
+
if (!isRecord(raw))
|
|
16
|
+
return [];
|
|
17
|
+
const nodes = raw.nodes;
|
|
18
|
+
if (!Array.isArray(nodes))
|
|
19
|
+
return [];
|
|
20
|
+
const out = [];
|
|
21
|
+
for (const node of nodes) {
|
|
22
|
+
const name = isRecord(node) ? node.name : undefined;
|
|
23
|
+
if (typeof name === "string")
|
|
24
|
+
out.push(name);
|
|
25
|
+
}
|
|
26
|
+
return out;
|
|
27
|
+
}
|
|
28
|
+
/** Whether `labels` carries every name in `required` (vacuously true when `required` is empty). */
|
|
29
|
+
export function hasAllLabels(labels, required) {
|
|
30
|
+
return required.every((name) => labels.includes(name));
|
|
31
|
+
}
|
|
32
|
+
function parseBlockerRefs(raw, required) {
|
|
33
|
+
if (!isRecord(raw))
|
|
34
|
+
return [];
|
|
35
|
+
const nodes = raw.nodes;
|
|
36
|
+
if (!Array.isArray(nodes))
|
|
37
|
+
return [];
|
|
38
|
+
const out = [];
|
|
39
|
+
for (const node of nodes) {
|
|
40
|
+
if (!isRecord(node) || !isRecord(node.issue))
|
|
41
|
+
continue;
|
|
42
|
+
const issue = node.issue;
|
|
43
|
+
const { identifier } = issue;
|
|
44
|
+
if (typeof identifier !== "string")
|
|
45
|
+
continue;
|
|
46
|
+
const stateType = isRecord(issue.state) ? issue.state.type : undefined;
|
|
47
|
+
const done = typeof stateType === "string" && DONE_STATE_TYPES.has(stateType);
|
|
48
|
+
const ownLabels = parseLabelNames(issue.labels);
|
|
49
|
+
const parent = issue.parent;
|
|
50
|
+
const parentLabels = isRecord(parent) ? parseLabelNames(parent.labels) : undefined;
|
|
51
|
+
const inScope = hasAllLabels(ownLabels, required) ||
|
|
52
|
+
(parentLabels !== undefined && hasAllLabels(parentLabels, required));
|
|
53
|
+
out.push({ identifier, done, inScope });
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
function parseDependencyChild(raw, required) {
|
|
58
|
+
if (!isRecord(raw))
|
|
59
|
+
return undefined;
|
|
60
|
+
const { id, identifier, title, url, description } = raw;
|
|
61
|
+
if (typeof id !== "string" || typeof identifier !== "string" || typeof title !== "string") {
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
const state = raw.state;
|
|
65
|
+
const stateName = isRecord(state) && typeof state.name === "string" ? state.name : undefined;
|
|
66
|
+
const stateType = isRecord(state) && typeof state.type === "string" ? state.type : undefined;
|
|
67
|
+
const assignee = raw.assignee;
|
|
68
|
+
const assigneeId = assignee === null
|
|
69
|
+
? null
|
|
70
|
+
: isRecord(assignee) && typeof assignee.id === "string"
|
|
71
|
+
? assignee.id
|
|
72
|
+
: undefined;
|
|
73
|
+
const assigneeEmail = isRecord(assignee) && typeof assignee.email === "string" ? assignee.email : undefined;
|
|
74
|
+
return {
|
|
75
|
+
id,
|
|
76
|
+
identifier,
|
|
77
|
+
title,
|
|
78
|
+
...(typeof url === "string" ? { url } : {}),
|
|
79
|
+
...(typeof description === "string" && description.trim().length > 0
|
|
80
|
+
? { description: description.trim() }
|
|
81
|
+
: {}),
|
|
82
|
+
...(stateName === undefined ? {} : { stateName }),
|
|
83
|
+
...(stateType === undefined ? {} : { stateType }),
|
|
84
|
+
...(assigneeId === undefined ? {} : { assigneeId }),
|
|
85
|
+
...(assigneeEmail === undefined ? {} : { assigneeEmail }),
|
|
86
|
+
blockers: parseBlockerRefs(raw.inverseRelations, required),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function parseDependencyRoot(raw, required) {
|
|
90
|
+
if (!isRecord(raw))
|
|
91
|
+
return undefined;
|
|
92
|
+
const { id, identifier, title, url, description } = raw;
|
|
93
|
+
if (typeof id !== "string" || typeof identifier !== "string" || typeof title !== "string") {
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
const childNodes = isRecord(raw.children) ? raw.children.nodes : undefined;
|
|
97
|
+
const children = [];
|
|
98
|
+
if (Array.isArray(childNodes)) {
|
|
99
|
+
for (const node of childNodes) {
|
|
100
|
+
const child = parseDependencyChild(node, required);
|
|
101
|
+
if (child !== undefined)
|
|
102
|
+
children.push(child);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
id,
|
|
107
|
+
identifier,
|
|
108
|
+
title,
|
|
109
|
+
...(typeof url === "string" ? { url } : {}),
|
|
110
|
+
...(typeof description === "string" && description.trim().length > 0
|
|
111
|
+
? { description: description.trim() }
|
|
112
|
+
: {}),
|
|
113
|
+
blockers: parseBlockerRefs(raw.inverseRelations, required),
|
|
114
|
+
children,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Parse the `issues.nodes` payload from `ELIGIBLE_ISSUES_QUERY` into roots with
|
|
119
|
+
* their children and blockers. `required` is `[source].eligible.labels`, used
|
|
120
|
+
* to decide whether each blocker is in the factory's scope. Malformed nodes are
|
|
121
|
+
* skipped rather than thrown on: this is external data.
|
|
122
|
+
*/
|
|
123
|
+
export function parseDependencyRoots(data, required) {
|
|
124
|
+
if (!isRecord(data))
|
|
125
|
+
return [];
|
|
126
|
+
const issues = data.issues;
|
|
127
|
+
const nodes = isRecord(issues) && Array.isArray(issues.nodes) ? issues.nodes : [];
|
|
128
|
+
const out = [];
|
|
129
|
+
for (const node of nodes) {
|
|
130
|
+
const root = parseDependencyRoot(node, required);
|
|
131
|
+
if (root !== undefined)
|
|
132
|
+
out.push(root);
|
|
133
|
+
}
|
|
134
|
+
return out;
|
|
135
|
+
}
|
|
136
|
+
/** Whether `assigneeId`/`assigneeEmail` satisfies an `EligibleFilter.assignee` constraint. */
|
|
137
|
+
function matchesAssignee(assigneeId, assigneeEmail, assignee, viewerId) {
|
|
138
|
+
if (assignee === undefined)
|
|
139
|
+
return true;
|
|
140
|
+
if (assignee === "unassigned")
|
|
141
|
+
return assigneeId === null || assigneeId === undefined;
|
|
142
|
+
if (assignee === "me")
|
|
143
|
+
return viewerId !== undefined && assigneeId === viewerId;
|
|
144
|
+
if (assignee.includes("@"))
|
|
145
|
+
return assigneeEmail === assignee;
|
|
146
|
+
return assigneeId === assignee;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Whether a child qualifies as a candidate: not already done, and matching the
|
|
150
|
+
* `state`/`assignee` constraints the top-level query would have applied to a
|
|
151
|
+
* root (the children connection isn't itself filtered by Linear).
|
|
152
|
+
*/
|
|
153
|
+
function childMatchesEligibility(child, eligible, viewerId) {
|
|
154
|
+
if (child.stateType !== undefined && DONE_STATE_TYPES.has(child.stateType))
|
|
155
|
+
return false;
|
|
156
|
+
if (eligible.state !== undefined && child.stateName !== eligible.state)
|
|
157
|
+
return false;
|
|
158
|
+
return matchesAssignee(child.assigneeId, child.assigneeEmail, eligible.assignee, viewerId);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Decide readiness from a candidate's blockers alone. Ready when every blocker
|
|
162
|
+
* is done. Otherwise: an incomplete out-of-scope blocker always wins (it is the
|
|
163
|
+
* hard-stop case), even alongside incomplete in-scope blockers; with only
|
|
164
|
+
* incomplete in-scope blockers, the candidate is quietly not ready yet.
|
|
165
|
+
*/
|
|
166
|
+
export function resolveBlockers(blockers) {
|
|
167
|
+
const incomplete = blockers.filter((blocker) => !blocker.done);
|
|
168
|
+
if (incomplete.length === 0)
|
|
169
|
+
return { ready: true, outOfScope: false };
|
|
170
|
+
const outOfScope = incomplete.find((blocker) => !blocker.inScope);
|
|
171
|
+
if (outOfScope !== undefined) {
|
|
172
|
+
return { ready: false, blockedBy: outOfScope.identifier, outOfScope: true };
|
|
173
|
+
}
|
|
174
|
+
return { ready: false, outOfScope: false };
|
|
175
|
+
}
|
|
176
|
+
function toDependencyItem(source) {
|
|
177
|
+
return {
|
|
178
|
+
identifier: source.identifier,
|
|
179
|
+
title: source.title,
|
|
180
|
+
...(source.url === undefined ? {} : { url: source.url }),
|
|
181
|
+
...(source.description === undefined ? {} : { description: source.description }),
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Decide, per root, what's workable now and what's blocked on an out-of-scope
|
|
186
|
+
* dependency. A root with no children is a plain candidate on its own blockers.
|
|
187
|
+
* A root with children is an epic: it is never itself workable, and each
|
|
188
|
+
* eligible child (state/assignee-matching, not already done) is gated on its
|
|
189
|
+
* own blockers instead.
|
|
190
|
+
*/
|
|
191
|
+
export function resolveEpicDependencies(roots, eligible, viewerId) {
|
|
192
|
+
const workable = [];
|
|
193
|
+
const blockedOutOfScope = [];
|
|
194
|
+
const place = (item, blockers) => {
|
|
195
|
+
const verdict = resolveBlockers(blockers);
|
|
196
|
+
if (verdict.ready) {
|
|
197
|
+
workable.push(item);
|
|
198
|
+
}
|
|
199
|
+
else if (verdict.blockedBy !== undefined) {
|
|
200
|
+
blockedOutOfScope.push({ item, blockerIdentifier: verdict.blockedBy });
|
|
201
|
+
}
|
|
202
|
+
// Otherwise: waiting on in-scope work still in flight. Say nothing; a later
|
|
203
|
+
// tick re-evaluates once the blocker completes.
|
|
204
|
+
};
|
|
205
|
+
for (const root of roots) {
|
|
206
|
+
if (root.children.length === 0) {
|
|
207
|
+
place(toDependencyItem(root), root.blockers);
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
for (const child of root.children) {
|
|
211
|
+
if (!childMatchesEligibility(child, eligible, viewerId))
|
|
212
|
+
continue;
|
|
213
|
+
place(toDependencyItem(child), child.blockers);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return { workable, blockedOutOfScope };
|
|
217
|
+
}
|
|
218
|
+
//# sourceMappingURL=dependencies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dependencies.js","sourceRoot":"","sources":["../../src/source/dependencies.ts"],"names":[],"mappings":"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"}
|
package/dist/source/index.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
+
export { type BlockerRef, type DependencyChild, type DependencyDiscovery, type DependencyItem, type DependencyRoot, hasAllLabels, parseDependencyRoots, resolveBlockers, resolveEpicDependencies, } from "./dependencies.js";
|
|
1
2
|
export { buildIssueFilter, createFetchRequester, ELIGIBLE_ISSUES_QUERY, LINEAR_ENDPOINT, type LinearRequester, LinearSource, type LinearSourceOptions, parseIssueNodes, } from "./linear.js";
|
|
2
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/source/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,eAAe,EACf,KAAK,eAAe,EACpB,YAAY,EACZ,KAAK,mBAAmB,EACxB,eAAe,GAChB,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/source/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,YAAY,EACZ,oBAAoB,EACpB,eAAe,EACf,uBAAuB,GACxB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,eAAe,EACf,KAAK,eAAe,EACpB,YAAY,EACZ,KAAK,mBAAmB,EACxB,eAAe,GAChB,MAAM,aAAa,CAAC"}
|
package/dist/source/index.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
+
export { hasAllLabels, parseDependencyRoots, resolveBlockers, resolveEpicDependencies, } from "./dependencies.js";
|
|
1
2
|
export { buildIssueFilter, createFetchRequester, ELIGIBLE_ISSUES_QUERY, LINEAR_ENDPOINT, LinearSource, parseIssueNodes, } from "./linear.js";
|
|
2
3
|
//# sourceMappingURL=index.js.map
|
package/dist/source/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/source/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,eAAe,EAEf,YAAY,EAEZ,eAAe,GAChB,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/source/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,YAAY,EACZ,oBAAoB,EACpB,eAAe,EACf,uBAAuB,GACxB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,eAAe,EAEf,YAAY,EAEZ,eAAe,GAChB,MAAM,aAAa,CAAC"}
|
package/dist/source/linear.d.ts
CHANGED
|
@@ -25,7 +25,16 @@ interface IssueNode {
|
|
|
25
25
|
*/
|
|
26
26
|
description?: string;
|
|
27
27
|
}
|
|
28
|
-
|
|
28
|
+
/**
|
|
29
|
+
* `inverseRelations(type: blocks)` on an issue is the incoming side of a
|
|
30
|
+
* `blocks` relation: the issues that block it (see `IssueRelationCreate`
|
|
31
|
+
* below, which always creates the relation from the blocker's side). Fetched
|
|
32
|
+
* on both roots and children so `resolveEpicDependencies` can gate readiness
|
|
33
|
+
* on them (TJ-1638); a query whose fake payload omits these fields (every
|
|
34
|
+
* existing test) parses to no children and no blockers, which is exactly the
|
|
35
|
+
* pre-TJ-1638 behavior.
|
|
36
|
+
*/
|
|
37
|
+
export declare const ELIGIBLE_ISSUES_QUERY = "\nquery EligibleIssues($filter: IssueFilter!, $first: Int!) {\n issues(filter: $filter, first: $first, orderBy: updatedAt) {\n nodes {\n id identifier title url description\n inverseRelations(filter: { type: { eq: blocks } }) {\n nodes {\n issue {\n id identifier\n state { type }\n labels { nodes { name } }\n parent { id identifier labels { nodes { name } } }\n }\n }\n }\n children(first: 100) {\n nodes {\n id identifier title url description\n state { name type }\n assignee { id email }\n inverseRelations(filter: { type: { eq: blocks } }) {\n nodes {\n issue {\n id identifier\n state { type }\n labels { nodes { name } }\n parent { id identifier labels { nodes { name } } }\n }\n }\n }\n }\n }\n }\n }\n}";
|
|
29
38
|
/** Scope in which to build a filter: the team key, optional project, and, when
|
|
30
39
|
* the assignee is `"me"`, the resolved viewer id to match. */
|
|
31
40
|
export interface FilterScope {
|
|
@@ -93,6 +102,13 @@ export declare class LinearSource implements TriageSource {
|
|
|
93
102
|
private readonly uuidByIdentifier;
|
|
94
103
|
constructor(request: LinearRequester, opts: LinearSourceOptions);
|
|
95
104
|
listEligible(): Promise<WorkItem[]>;
|
|
105
|
+
/**
|
|
106
|
+
* An item blocked by a dependency outside the factory's scope never becomes
|
|
107
|
+
* eligible on its own: claim it (so it leaves the eligible pool and this
|
|
108
|
+
* doesn't repeat every tick), say why, and hand it to a human, the same way
|
|
109
|
+
* `runTick` routes a `blocked` agent outcome.
|
|
110
|
+
*/
|
|
111
|
+
private flagOutOfScopeDependency;
|
|
96
112
|
claim(item: WorkItem): Promise<boolean>;
|
|
97
113
|
comment(item: WorkItem, body: string): Promise<void>;
|
|
98
114
|
listComments(item: WorkItem): Promise<Comment[]>;
|