@neriros/ralphy 3.10.3 → 3.10.5
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/dist/shell/index.js +941 -110
- package/package.json +1 -1
package/dist/shell/index.js
CHANGED
|
@@ -18928,8 +18928,8 @@ import { readFileSync } from "fs";
|
|
|
18928
18928
|
import { resolve } from "path";
|
|
18929
18929
|
function getVersion() {
|
|
18930
18930
|
try {
|
|
18931
|
-
if ("3.10.
|
|
18932
|
-
return "3.10.
|
|
18931
|
+
if ("3.10.5")
|
|
18932
|
+
return "3.10.5";
|
|
18933
18933
|
} catch {}
|
|
18934
18934
|
const dirsToTry = [];
|
|
18935
18935
|
try {
|
|
@@ -80505,7 +80505,21 @@ var init_zod = __esm(() => {
|
|
|
80505
80505
|
});
|
|
80506
80506
|
|
|
80507
80507
|
// packages/workflow/src/schema.ts
|
|
80508
|
-
|
|
80508
|
+
function foldLegacyAssignee(v) {
|
|
80509
|
+
if (!v || typeof v !== "object" || Array.isArray(v))
|
|
80510
|
+
return v;
|
|
80511
|
+
const obj = v;
|
|
80512
|
+
if (!("assignee" in obj))
|
|
80513
|
+
return v;
|
|
80514
|
+
const { assignee, ...rest2 } = obj;
|
|
80515
|
+
if (rest2["filter"] === undefined) {
|
|
80516
|
+
const raw = typeof assignee === "string" ? assignee.trim() : "";
|
|
80517
|
+
const value = raw === "" || raw.toLowerCase() === "unassigned" ? "unassigned" : raw;
|
|
80518
|
+
rest2["filter"] = `assignee = ${value}`;
|
|
80519
|
+
}
|
|
80520
|
+
return rest2;
|
|
80521
|
+
}
|
|
80522
|
+
var CURRENT_WORKFLOW_VERSION = 3, MarkerSchema, SET_INDICATOR_KEYS, GetIndicatorSchema, SetIndicatorSchema, IndicatorsSchema, ProjectSchema, CommandsSchema, DEFAULT_META_ONLY_FILES, BoundariesSchema, WorkflowConfigSchema;
|
|
80509
80523
|
var init_schema = __esm(() => {
|
|
80510
80524
|
init_zod();
|
|
80511
80525
|
MarkerSchema = exports_external.discriminatedUnion("type", [
|
|
@@ -80598,6 +80612,12 @@ var init_schema = __esm(() => {
|
|
|
80598
80612
|
WorkflowConfigSchema = exports_external.object({
|
|
80599
80613
|
version: exports_external.number().int().nonnegative().default(0),
|
|
80600
80614
|
project: ProjectSchema,
|
|
80615
|
+
repo: exports_external.object({
|
|
80616
|
+
remote: exports_external.string().optional(),
|
|
80617
|
+
host: exports_external.string().optional(),
|
|
80618
|
+
owner: exports_external.string().optional(),
|
|
80619
|
+
name: exports_external.string().optional()
|
|
80620
|
+
}).strict().optional(),
|
|
80601
80621
|
commands: CommandsSchema,
|
|
80602
80622
|
rules: exports_external.array(exports_external.string()).default([]),
|
|
80603
80623
|
boundaries: BoundariesSchema,
|
|
@@ -80629,9 +80649,9 @@ var init_schema = __esm(() => {
|
|
|
80629
80649
|
ignoreCiChecks: exports_external.array(exports_external.string()).default([]),
|
|
80630
80650
|
engine: exports_external.enum(["claude", "codex"]).default("claude"),
|
|
80631
80651
|
model: exports_external.enum(["haiku", "sonnet", "opus"]).default("opus"),
|
|
80632
|
-
linear: exports_external.object({
|
|
80652
|
+
linear: exports_external.preprocess(foldLegacyAssignee, exports_external.object({
|
|
80633
80653
|
team: exports_external.string().optional(),
|
|
80634
|
-
|
|
80654
|
+
filter: exports_external.string().default("assignee = me"),
|
|
80635
80655
|
postComments: exports_external.boolean().default(true),
|
|
80636
80656
|
updateEveryIterations: exports_external.number().int().nonnegative().default(10),
|
|
80637
80657
|
mentionTrigger: exports_external.boolean().default(true),
|
|
@@ -80651,7 +80671,8 @@ var init_schema = __esm(() => {
|
|
|
80651
80671
|
maxConfirmationRounds: 3
|
|
80652
80672
|
}),
|
|
80653
80673
|
indicators: IndicatorsSchema.default({})
|
|
80654
|
-
}).strict().default({
|
|
80674
|
+
}).strict()).default({
|
|
80675
|
+
filter: "assignee = me",
|
|
80655
80676
|
postComments: true,
|
|
80656
80677
|
updateEveryIterations: 10,
|
|
80657
80678
|
mentionTrigger: true,
|
|
@@ -80712,8 +80733,9 @@ var init_schema = __esm(() => {
|
|
|
80712
80733
|
advanceMergedToDone: false
|
|
80713
80734
|
}),
|
|
80714
80735
|
metaPrompt: exports_external.object({
|
|
80715
|
-
enabled: exports_external.boolean().default(true)
|
|
80716
|
-
|
|
80736
|
+
enabled: exports_external.boolean().default(true),
|
|
80737
|
+
effort: exports_external.enum(["auto", "light", "standard", "heavy"]).default("auto")
|
|
80738
|
+
}).strict().default({ enabled: true, effort: "auto" }),
|
|
80717
80739
|
openspec: exports_external.object({
|
|
80718
80740
|
reviewPhase: exports_external.object({
|
|
80719
80741
|
enabled: exports_external.boolean().default(false),
|
|
@@ -80739,7 +80761,7 @@ var init_schema = __esm(() => {
|
|
|
80739
80761
|
var FRONTMATTER_RE, DEFAULT_WORKFLOW_MD = `---
|
|
80740
80762
|
# WORKFLOW.md schema version \u2014 managed by \`ralphy init\`. When a newer version
|
|
80741
80763
|
# ships, re-running init migrates this file and fills in the new settings.
|
|
80742
|
-
version:
|
|
80764
|
+
version: 2
|
|
80743
80765
|
|
|
80744
80766
|
project:
|
|
80745
80767
|
name: ralphy
|
|
@@ -80803,6 +80825,7 @@ preExistingErrorCheck:
|
|
|
80803
80825
|
outputCharLimit: 4000
|
|
80804
80826
|
|
|
80805
80827
|
linear:
|
|
80828
|
+
filter: assignee = me
|
|
80806
80829
|
postComments: true
|
|
80807
80830
|
updateEveryIterations: 10
|
|
80808
80831
|
mentionTrigger: true
|
|
@@ -81049,7 +81072,7 @@ function modelOptionValues() {
|
|
|
81049
81072
|
const field = findField("model");
|
|
81050
81073
|
return field && field.spec.kind === "select" ? field.spec.options.map((o) => o.value) : [];
|
|
81051
81074
|
}
|
|
81052
|
-
var PROMPT_BODY_FIELD_ID = "promptBody", yes = () => ({ kind: "confirm", defaultChoice: "confirm" }), no = () => ({ kind: "confirm", defaultChoice: "cancel" }), PROJECT_NAME, LINEAR_TEAM,
|
|
81075
|
+
var PROMPT_BODY_FIELD_ID = "promptBody", REPO_LINK_FIELD_ID = "repo.link", yes = () => ({ kind: "confirm", defaultChoice: "confirm" }), no = () => ({ kind: "confirm", defaultChoice: "cancel" }), PROJECT_NAME, LINEAR_TEAM, REPO_LINK, LINEAR_FILTER, QUICK_FIELDS, isOn = (id) => (answers) => answers[id] === true, CUSTOMIZED_FIELDS, COMMON_CLI_OPTIONS, FIELD_DESCRIPTIONS;
|
|
81053
81076
|
var init_fields = __esm(() => {
|
|
81054
81077
|
PROJECT_NAME = {
|
|
81055
81078
|
id: "project.name",
|
|
@@ -81061,19 +81084,26 @@ var init_fields = __esm(() => {
|
|
|
81061
81084
|
id: "linear.team",
|
|
81062
81085
|
label: "Linear team key",
|
|
81063
81086
|
hint: "e.g. ENG \u2014 leave blank to match all teams",
|
|
81064
|
-
description: "
|
|
81087
|
+
description: "The Linear team this repository is linked to, given by its key (e.g. ENG). Ralphy only picks up issues from this team. Leave blank to watch every team.",
|
|
81065
81088
|
emptyLabel: "all teams",
|
|
81066
81089
|
spec: { kind: "text" }
|
|
81067
81090
|
};
|
|
81068
|
-
|
|
81069
|
-
id: "
|
|
81070
|
-
label: "
|
|
81071
|
-
|
|
81072
|
-
|
|
81073
|
-
|
|
81074
|
-
spec: { kind: "text" }
|
|
81091
|
+
REPO_LINK = {
|
|
81092
|
+
id: "repo.link",
|
|
81093
|
+
label: "Link this repository to the team?",
|
|
81094
|
+
description: "Record the detected git repository in WORKFLOW.md and link it to the Linear team above. Confirm to adopt the detected repo; decline to leave it out.",
|
|
81095
|
+
spec: yes(),
|
|
81096
|
+
when: (answers) => typeof answers["repo.name"] === "string" && answers["repo.name"] !== ""
|
|
81075
81097
|
};
|
|
81076
|
-
|
|
81098
|
+
LINEAR_FILTER = {
|
|
81099
|
+
id: "linear.filter",
|
|
81100
|
+
label: "Linear filter",
|
|
81101
|
+
hint: "e.g. 'assignee = me', 'assignee = any', 'assignee = unassigned', or an email/user-id",
|
|
81102
|
+
description: "Global filter applied to every Linear ticket fetch. The only clause today is 'assignee = <value>', where <value> is 'me' (issues assigned to you), 'any' (regardless of assignee), 'unassigned', a Linear user id, or an email. Blank defaults to 'assignee = me'.",
|
|
81103
|
+
emptyLabel: "assignee = me",
|
|
81104
|
+
spec: { kind: "text", placeholder: "assignee = me" }
|
|
81105
|
+
};
|
|
81106
|
+
QUICK_FIELDS = [PROJECT_NAME, LINEAR_TEAM, REPO_LINK, LINEAR_FILTER];
|
|
81077
81107
|
CUSTOMIZED_FIELDS = [
|
|
81078
81108
|
PROJECT_NAME,
|
|
81079
81109
|
{
|
|
@@ -81321,7 +81351,8 @@ var init_fields = __esm(() => {
|
|
|
81321
81351
|
spec: { kind: "list", placeholder: "dist/**" }
|
|
81322
81352
|
},
|
|
81323
81353
|
LINEAR_TEAM,
|
|
81324
|
-
|
|
81354
|
+
REPO_LINK,
|
|
81355
|
+
LINEAR_FILTER,
|
|
81325
81356
|
{
|
|
81326
81357
|
id: "linear.postComments",
|
|
81327
81358
|
label: "Post progress comments on the Linear issue?",
|
|
@@ -81464,6 +81495,21 @@ var init_fields = __esm(() => {
|
|
|
81464
81495
|
description: "Add Ralphy's task-level 'meta-prompt' layer (extra framing instructions) to each phase. Leave on unless you want raw prompts.",
|
|
81465
81496
|
spec: yes()
|
|
81466
81497
|
},
|
|
81498
|
+
{
|
|
81499
|
+
id: "metaPrompt.effort",
|
|
81500
|
+
label: "Per-ticket effort tier",
|
|
81501
|
+
description: "How much effort the meta-prompt nudges the agent toward per ticket. 'auto' detects it from the ticket; 'light'/'standard'/'heavy' pin every ticket to that tier.",
|
|
81502
|
+
spec: {
|
|
81503
|
+
kind: "select",
|
|
81504
|
+
options: [
|
|
81505
|
+
{ label: "auto", value: "auto" },
|
|
81506
|
+
{ label: "light", value: "light" },
|
|
81507
|
+
{ label: "standard", value: "standard" },
|
|
81508
|
+
{ label: "heavy", value: "heavy" }
|
|
81509
|
+
]
|
|
81510
|
+
},
|
|
81511
|
+
when: isOn("metaPrompt.enabled")
|
|
81512
|
+
},
|
|
81467
81513
|
{
|
|
81468
81514
|
id: "openspec.reviewPhase.enabled",
|
|
81469
81515
|
label: "Enable the OpenSpec review phase?",
|
|
@@ -81695,6 +81741,34 @@ function describeApprovalMarker(indicator) {
|
|
|
81695
81741
|
return `${phrases.slice(0, -1).join(", ")}, or ${phrases[phrases.length - 1]}`;
|
|
81696
81742
|
}
|
|
81697
81743
|
|
|
81744
|
+
// packages/workflow/src/linear-filter.ts
|
|
81745
|
+
function parseLinearFilter(filter2) {
|
|
81746
|
+
const trimmed = filter2.trim();
|
|
81747
|
+
if (trimmed === "")
|
|
81748
|
+
return { assignee: "me" };
|
|
81749
|
+
const eq = trimmed.indexOf("=");
|
|
81750
|
+
if (eq < 0) {
|
|
81751
|
+
throw new Error(`Invalid linear.filter "${filter2}": expected "<key> = <value>" (e.g. "assignee = me").`);
|
|
81752
|
+
}
|
|
81753
|
+
const key = trimmed.slice(0, eq).trim().toLowerCase();
|
|
81754
|
+
const value = trimmed.slice(eq + 1).trim();
|
|
81755
|
+
if (!SUPPORTED_KEYS.has(key)) {
|
|
81756
|
+
throw new Error(`Unrecognized linear.filter key "${key}" in "${filter2}". Supported keys: ${[...SUPPORTED_KEYS].join(", ")}.`);
|
|
81757
|
+
}
|
|
81758
|
+
const lower = value.toLowerCase();
|
|
81759
|
+
if (lower === "any")
|
|
81760
|
+
return { anyAssignee: true };
|
|
81761
|
+
if (lower === "" || lower === "unassigned")
|
|
81762
|
+
return { assignee: "unassigned" };
|
|
81763
|
+
if (lower === "me")
|
|
81764
|
+
return { assignee: "me" };
|
|
81765
|
+
return { assignee: value };
|
|
81766
|
+
}
|
|
81767
|
+
var SUPPORTED_KEYS;
|
|
81768
|
+
var init_linear_filter = __esm(() => {
|
|
81769
|
+
SUPPORTED_KEYS = new Set(["assignee"]);
|
|
81770
|
+
});
|
|
81771
|
+
|
|
81698
81772
|
// packages/workflow/src/workflow.ts
|
|
81699
81773
|
var exports_workflow = {};
|
|
81700
81774
|
__export(exports_workflow, {
|
|
@@ -81703,6 +81777,7 @@ __export(exports_workflow, {
|
|
|
81703
81777
|
renderWorkflowPrompt: () => renderWorkflowPrompt,
|
|
81704
81778
|
renderTemplate: () => renderTemplate,
|
|
81705
81779
|
parseWorkflow: () => parseWorkflow,
|
|
81780
|
+
parseLinearFilter: () => parseLinearFilter,
|
|
81706
81781
|
matchesIndicator: () => matchesIndicator,
|
|
81707
81782
|
loadWorkflow: () => loadWorkflow,
|
|
81708
81783
|
ensureWorkflow: () => ensureWorkflow,
|
|
@@ -81866,9 +81941,55 @@ var init_workflow = __esm(() => {
|
|
|
81866
81941
|
init_wizard();
|
|
81867
81942
|
init_schema();
|
|
81868
81943
|
init_default();
|
|
81944
|
+
init_linear_filter();
|
|
81869
81945
|
import_yaml2 = __toESM(require_dist(), 1);
|
|
81870
81946
|
});
|
|
81871
81947
|
|
|
81948
|
+
// packages/core/src/repo/index.ts
|
|
81949
|
+
function parseRepoIdentity(remoteUrl) {
|
|
81950
|
+
const remote = remoteUrl.trim();
|
|
81951
|
+
if (!remote)
|
|
81952
|
+
return null;
|
|
81953
|
+
const match = remote.includes("://") ? URL_RE.exec(remote) : SCP_RE.exec(remote);
|
|
81954
|
+
if (!match)
|
|
81955
|
+
return null;
|
|
81956
|
+
const host = match[1];
|
|
81957
|
+
let path = match[2];
|
|
81958
|
+
if (!host || !path)
|
|
81959
|
+
return null;
|
|
81960
|
+
path = path.replace(/\/+$/, "").replace(/\.git$/i, "").replace(/\/+$/, "");
|
|
81961
|
+
const segments = path.split("/").filter((segment) => segment.length > 0);
|
|
81962
|
+
if (segments.length < 2)
|
|
81963
|
+
return null;
|
|
81964
|
+
const name = segments[segments.length - 1];
|
|
81965
|
+
const owner = segments.slice(0, -1).join("/");
|
|
81966
|
+
if (!owner || !name)
|
|
81967
|
+
return null;
|
|
81968
|
+
return { remote, host, owner, name };
|
|
81969
|
+
}
|
|
81970
|
+
async function detectRepoIdentity(cwd2) {
|
|
81971
|
+
try {
|
|
81972
|
+
const proc = Bun.spawn({
|
|
81973
|
+
cmd: ["git", "remote", "get-url", "origin"],
|
|
81974
|
+
...cwd2 ? { cwd: cwd2 } : {},
|
|
81975
|
+
stdout: "pipe",
|
|
81976
|
+
stderr: "ignore",
|
|
81977
|
+
timeout: GIT_DETECT_TIMEOUT_MS
|
|
81978
|
+
});
|
|
81979
|
+
const [stdout, exitCode] = await Promise.all([new Response(proc.stdout).text(), proc.exited]);
|
|
81980
|
+
if (exitCode !== 0)
|
|
81981
|
+
return null;
|
|
81982
|
+
return parseRepoIdentity(stdout.trim());
|
|
81983
|
+
} catch {
|
|
81984
|
+
return null;
|
|
81985
|
+
}
|
|
81986
|
+
}
|
|
81987
|
+
var GIT_DETECT_TIMEOUT_MS = 5000, SCP_RE, URL_RE;
|
|
81988
|
+
var init_repo = __esm(() => {
|
|
81989
|
+
SCP_RE = /^(?:[^@/]+@)?([^/:]+):(.+)$/;
|
|
81990
|
+
URL_RE = /^[a-zA-Z][a-zA-Z0-9+.-]*:\/\/(?:[^@/]+@)?([^/:]+)(?::\d+)?\/(.+)$/;
|
|
81991
|
+
});
|
|
81992
|
+
|
|
81872
81993
|
// node_modules/.bun/react@18.3.1/node_modules/react/cjs/react-jsx-dev-runtime.development.js
|
|
81873
81994
|
var require_react_jsx_dev_runtime_development = __commonJS((exports) => {
|
|
81874
81995
|
var React10 = __toESM(require_react());
|
|
@@ -82787,6 +82908,12 @@ function buildFromAnswers(mode, answers, build = buildWorkflowMarkdown) {
|
|
|
82787
82908
|
values2["linear.indicators"] = map3;
|
|
82788
82909
|
}
|
|
82789
82910
|
}
|
|
82911
|
+
const linkRepo = values2[REPO_LINK_FIELD_ID] === true;
|
|
82912
|
+
delete values2[REPO_LINK_FIELD_ID];
|
|
82913
|
+
if (!linkRepo) {
|
|
82914
|
+
for (const id of REPO_ANSWER_IDS)
|
|
82915
|
+
delete values2[id];
|
|
82916
|
+
}
|
|
82790
82917
|
let bodyOverride;
|
|
82791
82918
|
if (PROMPT_BODY_FIELD_ID in values2) {
|
|
82792
82919
|
const body = values2[PROMPT_BODY_FIELD_ID];
|
|
@@ -82868,7 +82995,8 @@ function SetupWizard({
|
|
|
82868
82995
|
initialValues,
|
|
82869
82996
|
buildMarkdown,
|
|
82870
82997
|
onlyFields,
|
|
82871
|
-
initialBody
|
|
82998
|
+
initialBody,
|
|
82999
|
+
detectedRepo
|
|
82872
83000
|
}) {
|
|
82873
83001
|
const { exit } = use_app_default();
|
|
82874
83002
|
const startValues = initialValues ?? {};
|
|
@@ -82944,7 +83072,15 @@ function SetupWizard({
|
|
|
82944
83072
|
setIndex(target);
|
|
82945
83073
|
initEditing(fieldsFor(mode, source)[target], source);
|
|
82946
83074
|
};
|
|
82947
|
-
const valuesToWrite = (source) =>
|
|
83075
|
+
const valuesToWrite = (source) => {
|
|
83076
|
+
if (!onlyFields)
|
|
83077
|
+
return source;
|
|
83078
|
+
const allowed = new Set(onlyFields);
|
|
83079
|
+
if (allowed.has(REPO_LINK_FIELD_ID))
|
|
83080
|
+
for (const id of REPO_ANSWER_IDS)
|
|
83081
|
+
allowed.add(id);
|
|
83082
|
+
return Object.fromEntries(Object.entries(source).filter(([id]) => allowed.has(id)));
|
|
83083
|
+
};
|
|
82948
83084
|
const advance = (source) => {
|
|
82949
83085
|
const nextFields = fieldsFor(mode, source);
|
|
82950
83086
|
if (index >= nextFields.length - 1) {
|
|
@@ -83152,6 +83288,22 @@ ${draft.slice(at2)}`, at2 + 1);
|
|
|
83152
83288
|
marginTop: 1,
|
|
83153
83289
|
flexDirection: "column",
|
|
83154
83290
|
children: [
|
|
83291
|
+
field.id === REPO_LINK_FIELD_ID && detectedRepo ? /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
83292
|
+
children: [
|
|
83293
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
83294
|
+
dimColor: true,
|
|
83295
|
+
children: "Detected repo: "
|
|
83296
|
+
}, undefined, false, undefined, this),
|
|
83297
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
83298
|
+
color: "cyan",
|
|
83299
|
+
children: [
|
|
83300
|
+
detectedRepo.owner,
|
|
83301
|
+
"/",
|
|
83302
|
+
detectedRepo.name
|
|
83303
|
+
]
|
|
83304
|
+
}, undefined, true, undefined, this)
|
|
83305
|
+
]
|
|
83306
|
+
}, undefined, true, undefined, this) : null,
|
|
83155
83307
|
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
83156
83308
|
children: [
|
|
83157
83309
|
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
@@ -83724,13 +83876,14 @@ function IndicatorBuilder({
|
|
|
83724
83876
|
]
|
|
83725
83877
|
}, undefined, true, undefined, this);
|
|
83726
83878
|
}
|
|
83727
|
-
var import_react22, jsx_dev_runtime, MODE_OPTIONS, INDICATOR_OPTIONS, CONFIRM_OPTIONS, EDIT_EXIT_OPTIONS, RECREATE_EXIT_OPTIONS, MIGRATE_OPTIONS, CORE_STATES, CONFIRMATION_STATES, ALL_TYPES;
|
|
83879
|
+
var import_react22, jsx_dev_runtime, REPO_ANSWER_IDS, MODE_OPTIONS, INDICATOR_OPTIONS, CONFIRM_OPTIONS, EDIT_EXIT_OPTIONS, RECREATE_EXIT_OPTIONS, MIGRATE_OPTIONS, CORE_STATES, CONFIRMATION_STATES, ALL_TYPES;
|
|
83728
83880
|
var init_SetupWizard = __esm(async () => {
|
|
83729
83881
|
init_wizard();
|
|
83730
83882
|
init_fields();
|
|
83731
83883
|
await init_build2();
|
|
83732
83884
|
import_react22 = __toESM(require_react(), 1);
|
|
83733
83885
|
jsx_dev_runtime = __toESM(require_jsx_dev_runtime(), 1);
|
|
83886
|
+
REPO_ANSWER_IDS = ["repo.remote", "repo.host", "repo.owner", "repo.name"];
|
|
83734
83887
|
MODE_OPTIONS = [
|
|
83735
83888
|
{ label: "Quick \u2014 sensible defaults, only a few questions", value: "quick" },
|
|
83736
83889
|
{ label: "Permissive \u2014 defaults + auto-PR / auto-merge / CI auto-fix", value: "permissive" },
|
|
@@ -83856,6 +84009,16 @@ var init_migrations = __esm(() => {
|
|
|
83856
84009
|
"openspec.reviewPhase.reviewerModel",
|
|
83857
84010
|
"openspec.reviewPhase.reviewerContextStrategy"
|
|
83858
84011
|
]
|
|
84012
|
+
},
|
|
84013
|
+
{
|
|
84014
|
+
version: 2,
|
|
84015
|
+
description: "Ralphy now detects the current git repo and records it in WORKFLOW.md, " + "linking it to your Linear team. Confirm the detected repo to adopt it.",
|
|
84016
|
+
fields: ["repo.link"]
|
|
84017
|
+
},
|
|
84018
|
+
{
|
|
84019
|
+
version: 3,
|
|
84020
|
+
description: "The per-workflow `linear.assignee` setting is replaced by a global " + "`linear.filter` expression (e.g. `assignee = me`) applied to every " + "ticket fetch. Existing `assignee` values are folded in automatically; " + "note that an empty filter now defaults to `assignee = me` (it previously " + "meant unassigned-only).",
|
|
84021
|
+
fields: ["linear.filter"]
|
|
83859
84022
|
}
|
|
83860
84023
|
];
|
|
83861
84024
|
LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max2, migration) => Math.max(max2, migration.version), 0);
|
|
@@ -83868,6 +84031,18 @@ __export(exports_src, {
|
|
|
83868
84031
|
maybeRunSetupWizard: () => maybeRunSetupWizard,
|
|
83869
84032
|
main: () => main
|
|
83870
84033
|
});
|
|
84034
|
+
function withDetectedRepo(initial2, repo) {
|
|
84035
|
+
if (!repo)
|
|
84036
|
+
return initial2;
|
|
84037
|
+
const values2 = { ...initial2 };
|
|
84038
|
+
values2["repo.remote"] = repo.remote;
|
|
84039
|
+
values2["repo.host"] = repo.host;
|
|
84040
|
+
values2["repo.owner"] = repo.owner;
|
|
84041
|
+
values2["repo.name"] = repo.name;
|
|
84042
|
+
if (!values2["project.name"])
|
|
84043
|
+
values2["project.name"] = repo.name;
|
|
84044
|
+
return values2;
|
|
84045
|
+
}
|
|
83871
84046
|
function clearScreen2() {
|
|
83872
84047
|
if (process.stdout.isTTY)
|
|
83873
84048
|
process.stdout.write("\x1B[2J\x1B[3J\x1B[H");
|
|
@@ -83876,6 +84051,7 @@ async function runSetupWizard(projectRoot, options = {}) {
|
|
|
83876
84051
|
let markdown = null;
|
|
83877
84052
|
const buildMarkdown = options.existing ? (answers, bodyOverride) => applyAnswersToWorkflow(options.existing, answers, bodyOverride) : undefined;
|
|
83878
84053
|
const initialBody = workflowBody(options.existing ?? DEFAULT_WORKFLOW_MD);
|
|
84054
|
+
const initialValues = withDetectedRepo(options.initialValues, options.detectedRepo);
|
|
83879
84055
|
clearScreen2();
|
|
83880
84056
|
const { waitUntilExit } = render_default(import_react23.createElement(SetupWizard, {
|
|
83881
84057
|
onComplete: (md) => {
|
|
@@ -83886,8 +84062,9 @@ async function runSetupWizard(projectRoot, options = {}) {
|
|
|
83886
84062
|
},
|
|
83887
84063
|
initialBody,
|
|
83888
84064
|
...options.initialMode ? { initialMode: options.initialMode } : {},
|
|
83889
|
-
...
|
|
84065
|
+
...initialValues ? { initialValues } : {},
|
|
83890
84066
|
...options.onlyFields ? { onlyFields: options.onlyFields } : {},
|
|
84067
|
+
...options.detectedRepo ? { detectedRepo: { owner: options.detectedRepo.owner, name: options.detectedRepo.name } } : {},
|
|
83891
84068
|
...buildMarkdown ? { buildMarkdown } : {}
|
|
83892
84069
|
}));
|
|
83893
84070
|
await waitUntilExit();
|
|
@@ -83929,8 +84106,8 @@ function initialValuesFromConfig(config2) {
|
|
|
83929
84106
|
values2["useWorktree"] = config2.useWorktree;
|
|
83930
84107
|
if (config2.linear.team)
|
|
83931
84108
|
values2["linear.team"] = config2.linear.team;
|
|
83932
|
-
if (config2.linear.
|
|
83933
|
-
values2["linear.
|
|
84109
|
+
if (config2.linear.filter)
|
|
84110
|
+
values2["linear.filter"] = config2.linear.filter;
|
|
83934
84111
|
return values2;
|
|
83935
84112
|
}
|
|
83936
84113
|
async function promptEditOrExit() {
|
|
@@ -83971,10 +84148,12 @@ async function promptMigrate(fromVersion) {
|
|
|
83971
84148
|
}
|
|
83972
84149
|
async function editExisting(projectRoot, path, config2, onlyFields) {
|
|
83973
84150
|
const existing = await Bun.file(path).text();
|
|
84151
|
+
const detectedRepo = await detectRepoIdentity(projectRoot);
|
|
83974
84152
|
const wrote = await runSetupWizard(projectRoot, {
|
|
83975
84153
|
existing,
|
|
83976
84154
|
initialMode: "customized",
|
|
83977
84155
|
initialValues: initialValuesFromConfig(config2),
|
|
84156
|
+
...detectedRepo ? { detectedRepo } : {},
|
|
83978
84157
|
...onlyFields ? { onlyFields } : {}
|
|
83979
84158
|
});
|
|
83980
84159
|
process.stdout.write(wrote ? `
|
|
@@ -84010,7 +84189,8 @@ async function main(argv) {
|
|
|
84010
84189
|
`);
|
|
84011
84190
|
return 0;
|
|
84012
84191
|
}
|
|
84013
|
-
const
|
|
84192
|
+
const detectedRepo2 = await detectRepoIdentity(projectRoot);
|
|
84193
|
+
const wrote2 = await runSetupWizard(projectRoot, detectedRepo2 ? { detectedRepo: detectedRepo2 } : {});
|
|
84014
84194
|
process.stdout.write(wrote2 ? `
|
|
84015
84195
|
\u2713 Recreated ${path}
|
|
84016
84196
|
` : `
|
|
@@ -84043,7 +84223,8 @@ Setup cancelled \u2014 no file written.
|
|
|
84043
84223
|
`);
|
|
84044
84224
|
return 0;
|
|
84045
84225
|
}
|
|
84046
|
-
const
|
|
84226
|
+
const detectedRepo = await detectRepoIdentity(projectRoot);
|
|
84227
|
+
const wrote = await runSetupWizard(projectRoot, detectedRepo ? { detectedRepo } : {});
|
|
84047
84228
|
process.stdout.write(wrote ? `
|
|
84048
84229
|
\u2713 Created ${path}
|
|
84049
84230
|
` : `
|
|
@@ -84056,6 +84237,7 @@ var init_src4 = __esm(async () => {
|
|
|
84056
84237
|
init_paths();
|
|
84057
84238
|
init_workflow();
|
|
84058
84239
|
init_wizard();
|
|
84240
|
+
init_repo();
|
|
84059
84241
|
init_migrations();
|
|
84060
84242
|
await __promiseAll([
|
|
84061
84243
|
init_build2(),
|
|
@@ -99164,10 +99346,112 @@ var init_tasks_md = __esm(() => {
|
|
|
99164
99346
|
];
|
|
99165
99347
|
});
|
|
99166
99348
|
|
|
99349
|
+
// packages/core/src/prompt/effort.ts
|
|
99350
|
+
function countUnchecked2(tasksContent) {
|
|
99351
|
+
const matches2 = tasksContent.match(/^\s*[-*]\s+\[ \]/gm);
|
|
99352
|
+
return matches2 ? matches2.length : 0;
|
|
99353
|
+
}
|
|
99354
|
+
function clamp2(value, min2, max2) {
|
|
99355
|
+
return Math.max(min2, Math.min(max2, value));
|
|
99356
|
+
}
|
|
99357
|
+
function detectEffort(state, options = {}) {
|
|
99358
|
+
if (options.override)
|
|
99359
|
+
return options.override;
|
|
99360
|
+
const prompt = (state.prompt ?? "").toLowerCase();
|
|
99361
|
+
let keywordScore = 0;
|
|
99362
|
+
for (const kw of HEAVY_KEYWORDS) {
|
|
99363
|
+
if (prompt.includes(kw))
|
|
99364
|
+
keywordScore += HEAVY_WEIGHT;
|
|
99365
|
+
}
|
|
99366
|
+
for (const kw of LIGHT_KEYWORDS) {
|
|
99367
|
+
if (prompt.includes(kw))
|
|
99368
|
+
keywordScore += LIGHT_WEIGHT;
|
|
99369
|
+
}
|
|
99370
|
+
keywordScore = clamp2(keywordScore, -KEYWORD_HIT_CAP, KEYWORD_HIT_CAP);
|
|
99371
|
+
let score = keywordScore;
|
|
99372
|
+
const hasHeavyKeyword = keywordScore > 0;
|
|
99373
|
+
if (prompt.length > 0 && prompt.length < SHORT_PROMPT_CHARS && !hasHeavyKeyword) {
|
|
99374
|
+
score -= 1;
|
|
99375
|
+
} else if (prompt.length > LONG_PROMPT_CHARS) {
|
|
99376
|
+
score += 1;
|
|
99377
|
+
}
|
|
99378
|
+
if (options.tasksContent) {
|
|
99379
|
+
const unchecked = countUnchecked2(options.tasksContent);
|
|
99380
|
+
if (unchecked > 0 && unchecked <= FEW_TASKS) {
|
|
99381
|
+
score -= 2;
|
|
99382
|
+
} else if (unchecked >= MANY_TASKS) {
|
|
99383
|
+
score += 2;
|
|
99384
|
+
}
|
|
99385
|
+
}
|
|
99386
|
+
if (score <= LIGHT_THRESHOLD)
|
|
99387
|
+
return "light";
|
|
99388
|
+
if (score >= HEAVY_THRESHOLD)
|
|
99389
|
+
return "heavy";
|
|
99390
|
+
return "standard";
|
|
99391
|
+
}
|
|
99392
|
+
var HEAVY_KEYWORDS, LIGHT_KEYWORDS, HEAVY_WEIGHT = 2, LIGHT_WEIGHT = -2, KEYWORD_HIT_CAP = 4, SHORT_PROMPT_CHARS = 120, LONG_PROMPT_CHARS = 600, FEW_TASKS = 2, MANY_TASKS = 8, LIGHT_THRESHOLD = -2, HEAVY_THRESHOLD = 2, EFFORT_GUIDANCE;
|
|
99393
|
+
var init_effort = __esm(() => {
|
|
99394
|
+
HEAVY_KEYWORDS = [
|
|
99395
|
+
"migrate",
|
|
99396
|
+
"refactor",
|
|
99397
|
+
"redesign",
|
|
99398
|
+
"re-architect",
|
|
99399
|
+
"architecture",
|
|
99400
|
+
"rewrite",
|
|
99401
|
+
"overhaul",
|
|
99402
|
+
"breaking change",
|
|
99403
|
+
"investigate",
|
|
99404
|
+
"spike",
|
|
99405
|
+
"cross-cutting",
|
|
99406
|
+
"end-to-end"
|
|
99407
|
+
];
|
|
99408
|
+
LIGHT_KEYWORDS = [
|
|
99409
|
+
"typo",
|
|
99410
|
+
"rename",
|
|
99411
|
+
"bump",
|
|
99412
|
+
"tweak",
|
|
99413
|
+
"wording",
|
|
99414
|
+
"copy",
|
|
99415
|
+
"comment",
|
|
99416
|
+
"lint",
|
|
99417
|
+
"docs",
|
|
99418
|
+
"one-liner",
|
|
99419
|
+
"revert",
|
|
99420
|
+
"whitespace"
|
|
99421
|
+
];
|
|
99422
|
+
EFFORT_GUIDANCE = {
|
|
99423
|
+
light: [
|
|
99424
|
+
"This ticket looks **light**. Make the smallest correct change.",
|
|
99425
|
+
"- Skip research/design ceremony \u2014 go straight to the fix",
|
|
99426
|
+
"- Avoid speculative abstraction; do not expand scope",
|
|
99427
|
+
"- Aim to finish in as few iterations as possible"
|
|
99428
|
+
].join(`
|
|
99429
|
+
`),
|
|
99430
|
+
standard: [
|
|
99431
|
+
"This ticket looks **standard**. Balance thoroughness with momentum.",
|
|
99432
|
+
"- Do enough investigation to be confident, but don't over-engineer",
|
|
99433
|
+
"- Keep changes focused on the stated scope",
|
|
99434
|
+
"- Verify with the project's lint and test gates before finishing"
|
|
99435
|
+
].join(`
|
|
99436
|
+
`),
|
|
99437
|
+
heavy: [
|
|
99438
|
+
"This ticket looks **heavy**. Invest up front before changing code.",
|
|
99439
|
+
"- Research the affected areas and write a real design",
|
|
99440
|
+
"- Break the work into small, independently-verifiable tasks",
|
|
99441
|
+
"- Watch for cross-cutting impact and regressions as you go"
|
|
99442
|
+
].join(`
|
|
99443
|
+
`)
|
|
99444
|
+
};
|
|
99445
|
+
});
|
|
99446
|
+
|
|
99167
99447
|
// packages/core/src/prompt/meta-prompt.ts
|
|
99168
99448
|
function buildMetaPrompt(state, phase, options = {}) {
|
|
99169
99449
|
if (options.enabled === false)
|
|
99170
99450
|
return "";
|
|
99451
|
+
const effort = detectEffort(state, {
|
|
99452
|
+
...options.effort !== undefined ? { override: options.effort } : {},
|
|
99453
|
+
...options.tasksContent !== undefined ? { tasksContent: options.tasksContent } : {}
|
|
99454
|
+
});
|
|
99171
99455
|
let out = `---
|
|
99172
99456
|
|
|
99173
99457
|
## Task Context
|
|
@@ -99178,6 +99462,8 @@ function buildMetaPrompt(state, phase, options = {}) {
|
|
|
99178
99462
|
out += `**Engine/Model:** ${state.engine} / ${state.model}
|
|
99179
99463
|
`;
|
|
99180
99464
|
out += `**Phase:** ${phase}
|
|
99465
|
+
`;
|
|
99466
|
+
out += `**Effort:** ${effort}
|
|
99181
99467
|
`;
|
|
99182
99468
|
out += `**Iteration:** ${state.iteration + 1}`;
|
|
99183
99469
|
if (options.maxIterations && options.maxIterations > 0) {
|
|
@@ -99201,6 +99487,12 @@ function buildMetaPrompt(state, phase, options = {}) {
|
|
|
99201
99487
|
`;
|
|
99202
99488
|
out += PHASE_GUIDANCE[phase] + `
|
|
99203
99489
|
|
|
99490
|
+
`;
|
|
99491
|
+
out += `### Effort Guidance
|
|
99492
|
+
|
|
99493
|
+
`;
|
|
99494
|
+
out += EFFORT_GUIDANCE[effort] + `
|
|
99495
|
+
|
|
99204
99496
|
`;
|
|
99205
99497
|
const flags = [];
|
|
99206
99498
|
if (options.useWorktree) {
|
|
@@ -99233,6 +99525,7 @@ function buildMetaPrompt(state, phase, options = {}) {
|
|
|
99233
99525
|
}
|
|
99234
99526
|
var PHASE_GUIDANCE;
|
|
99235
99527
|
var init_meta_prompt = __esm(() => {
|
|
99528
|
+
init_effort();
|
|
99236
99529
|
PHASE_GUIDANCE = {
|
|
99237
99530
|
research: [
|
|
99238
99531
|
"You are in the **research** phase. Your goal is to understand, not to implement.",
|
|
@@ -99706,6 +99999,7 @@ var init_loop = __esm(() => {
|
|
|
99706
99999
|
init_tasks_md();
|
|
99707
100000
|
init_phase();
|
|
99708
100001
|
init_meta_prompt();
|
|
100002
|
+
init_effort();
|
|
99709
100003
|
init_tasks_md();
|
|
99710
100004
|
});
|
|
99711
100005
|
|
|
@@ -99986,7 +100280,10 @@ function useLoop(opts) {
|
|
|
99986
100280
|
design: designContent,
|
|
99987
100281
|
tasks: tasksContent
|
|
99988
100282
|
});
|
|
99989
|
-
const prompt = buildPhasePrompt(routedPhase, currentState, tasksDir, opts.reviewPhase,
|
|
100283
|
+
const prompt = buildPhasePrompt(routedPhase, currentState, tasksDir, opts.reviewPhase, {
|
|
100284
|
+
...opts.metaPrompt,
|
|
100285
|
+
...tasksContent !== null ? { tasksContent } : {}
|
|
100286
|
+
});
|
|
99990
100287
|
const iterStart = new Date().toISOString();
|
|
99991
100288
|
try {
|
|
99992
100289
|
const controller = new AbortController;
|
|
@@ -101157,6 +101454,7 @@ async function parseAgentArgs(argv) {
|
|
|
101157
101454
|
...common2,
|
|
101158
101455
|
mode: "agent",
|
|
101159
101456
|
linearTeam: "",
|
|
101457
|
+
linearFilter: "",
|
|
101160
101458
|
linearAssignee: "",
|
|
101161
101459
|
pollInterval: 0,
|
|
101162
101460
|
concurrency: 0,
|
|
@@ -101172,22 +101470,30 @@ async function parseAgentArgs(argv) {
|
|
|
101172
101470
|
debug: false,
|
|
101173
101471
|
noTmux: false,
|
|
101174
101472
|
checks: false,
|
|
101175
|
-
review: false
|
|
101473
|
+
review: false,
|
|
101474
|
+
ticketTokens: []
|
|
101176
101475
|
};
|
|
101177
101476
|
const state = emptyParseState();
|
|
101178
101477
|
let expectLinearTeam = false;
|
|
101478
|
+
let expectLinearFilter = false;
|
|
101179
101479
|
let expectLinearAssignee = false;
|
|
101180
101480
|
let expectPollInterval = false;
|
|
101181
101481
|
let expectConcurrency = false;
|
|
101182
101482
|
let expectMaxTickets = false;
|
|
101183
101483
|
let expectIndicator = false;
|
|
101184
101484
|
let expectJsonLogFile = false;
|
|
101485
|
+
let expectTicket = false;
|
|
101185
101486
|
for (const arg of argv) {
|
|
101186
101487
|
if (expectLinearTeam) {
|
|
101187
101488
|
result2.linearTeam = arg;
|
|
101188
101489
|
expectLinearTeam = false;
|
|
101189
101490
|
continue;
|
|
101190
101491
|
}
|
|
101492
|
+
if (expectLinearFilter) {
|
|
101493
|
+
result2.linearFilter = arg;
|
|
101494
|
+
expectLinearFilter = false;
|
|
101495
|
+
continue;
|
|
101496
|
+
}
|
|
101191
101497
|
if (expectLinearAssignee) {
|
|
101192
101498
|
result2.linearAssignee = arg;
|
|
101193
101499
|
expectLinearAssignee = false;
|
|
@@ -101219,12 +101525,23 @@ async function parseAgentArgs(argv) {
|
|
|
101219
101525
|
expectJsonLogFile = false;
|
|
101220
101526
|
continue;
|
|
101221
101527
|
}
|
|
101528
|
+
if (expectTicket) {
|
|
101529
|
+
for (const token of arg.split(",").map((t) => t.trim())) {
|
|
101530
|
+
if (token)
|
|
101531
|
+
result2.ticketTokens.push(token);
|
|
101532
|
+
}
|
|
101533
|
+
expectTicket = false;
|
|
101534
|
+
continue;
|
|
101535
|
+
}
|
|
101222
101536
|
if (parseCommonArg(arg, result2, state))
|
|
101223
101537
|
continue;
|
|
101224
101538
|
switch (arg) {
|
|
101225
101539
|
case "--linear-team":
|
|
101226
101540
|
expectLinearTeam = true;
|
|
101227
101541
|
break;
|
|
101542
|
+
case "--linear-filter":
|
|
101543
|
+
expectLinearFilter = true;
|
|
101544
|
+
break;
|
|
101228
101545
|
case "--linear-assignee":
|
|
101229
101546
|
expectLinearAssignee = true;
|
|
101230
101547
|
break;
|
|
@@ -101237,6 +101554,9 @@ async function parseAgentArgs(argv) {
|
|
|
101237
101554
|
case "--max-tickets":
|
|
101238
101555
|
expectMaxTickets = true;
|
|
101239
101556
|
break;
|
|
101557
|
+
case "--ticket":
|
|
101558
|
+
expectTicket = true;
|
|
101559
|
+
break;
|
|
101240
101560
|
case "--worktree":
|
|
101241
101561
|
result2.worktree = true;
|
|
101242
101562
|
break;
|
|
@@ -101346,7 +101666,8 @@ var init_cli2 = __esm(() => {
|
|
|
101346
101666
|
" --log Log raw engine stream",
|
|
101347
101667
|
" --verbose Verbose output",
|
|
101348
101668
|
" --linear-team <key> Linear team key (e.g. ENG)",
|
|
101349
|
-
" --linear-
|
|
101669
|
+
" --linear-filter <expr> Global Linear filter (e.g. 'assignee = me', 'assignee = any')",
|
|
101670
|
+
" --linear-assignee <id> [deprecated] Filter by assignee; use --linear-filter instead",
|
|
101350
101671
|
" --poll-interval <s> Seconds between Linear polls (default: 60)",
|
|
101351
101672
|
" --concurrency <n> Max concurrent task loops (default: 1)",
|
|
101352
101673
|
" --worktree Run each task in its own git worktree",
|
|
@@ -101361,6 +101682,7 @@ var init_cli2 = __esm(() => {
|
|
|
101361
101682
|
" --stack-prs Base the PR on a blocker issue's open-PR head branch when present (needs --create-pr)",
|
|
101362
101683
|
" --code-review Watch open tracked PRs for unresolved review comments",
|
|
101363
101684
|
" --max-tickets <n> Stop picking up new issues after N have been started (0 = unlimited)",
|
|
101685
|
+
" --ticket <id> Restrict issue discovery to specific ticket(s); repeatable or comma-separated (e.g. RLF-208 or 208)",
|
|
101364
101686
|
" --no-tmux Disable tmux session management; run agent in the foreground directly",
|
|
101365
101687
|
" --no-pr-tracker Disable RLF-173 pr-tracker bail / recovery counter for this run",
|
|
101366
101688
|
" --json-output Emit JSONL to stdout instead of the Ink dashboard (for scripting/CI)",
|
|
@@ -101382,6 +101704,11 @@ var init_cli2 = __esm(() => {
|
|
|
101382
101704
|
});
|
|
101383
101705
|
|
|
101384
101706
|
// apps/agent/src/agent/config.ts
|
|
101707
|
+
var exports_config = {};
|
|
101708
|
+
__export(exports_config, {
|
|
101709
|
+
loadRalphyConfig: () => loadRalphyConfig,
|
|
101710
|
+
ensureRalphyConfig: () => ensureRalphyConfig
|
|
101711
|
+
});
|
|
101385
101712
|
async function loadRalphyConfig(projectRoot) {
|
|
101386
101713
|
const { config: config2 } = await loadWorkflow(projectRoot);
|
|
101387
101714
|
return config2;
|
|
@@ -101746,6 +102073,103 @@ function isRalphComment(body) {
|
|
|
101746
102073
|
}
|
|
101747
102074
|
|
|
101748
102075
|
// apps/agent/src/shared/capabilities/linear-client.ts
|
|
102076
|
+
var exports_linear_client = {};
|
|
102077
|
+
__export(exports_linear_client, {
|
|
102078
|
+
upsertRalphyAttachment: () => upsertRalphyAttachment,
|
|
102079
|
+
uploadFileToLinear: () => uploadFileToLinear,
|
|
102080
|
+
updateIssueState: () => updateIssueState,
|
|
102081
|
+
updateIssueDescription: () => updateIssueDescription,
|
|
102082
|
+
updateIssueComment: () => updateIssueComment,
|
|
102083
|
+
updateAttachmentSubtitle: () => updateAttachmentSubtitle,
|
|
102084
|
+
setIssueProject: () => setIssueProject,
|
|
102085
|
+
resolveTicketNumbers: () => resolveTicketNumbers,
|
|
102086
|
+
removeLabelFromIssue: () => removeLabelFromIssue,
|
|
102087
|
+
parseTicketIdentifier: () => parseTicketIdentifier,
|
|
102088
|
+
linearRequestInternals: () => linearRequestInternals,
|
|
102089
|
+
issueMatchesGetIndicator: () => issueMatchesGetIndicator,
|
|
102090
|
+
isRateLimitedError: () => isRateLimitedError,
|
|
102091
|
+
formatTicketError: () => formatTicketError,
|
|
102092
|
+
formatLinearError: () => formatLinearError,
|
|
102093
|
+
findOpenIssueByLabel: () => findOpenIssueByLabel,
|
|
102094
|
+
findIssueAttachmentByTitle: () => findIssueAttachmentByTitle,
|
|
102095
|
+
fetchWorkflowStates: () => fetchWorkflowStates,
|
|
102096
|
+
fetchTeamIdByKey: () => fetchTeamIdByKey,
|
|
102097
|
+
fetchProjectIdByName: () => fetchProjectIdByName,
|
|
102098
|
+
fetchOpenIssues: () => fetchOpenIssues,
|
|
102099
|
+
fetchMentionScanIssues: () => fetchMentionScanIssues,
|
|
102100
|
+
fetchIssueLabels: () => fetchIssueLabels,
|
|
102101
|
+
fetchIssueComments: () => fetchIssueComments,
|
|
102102
|
+
fetchIssueAttachments: () => fetchIssueAttachments,
|
|
102103
|
+
fetchAttachmentsForIssues: () => fetchAttachmentsForIssues,
|
|
102104
|
+
deleteIssueComment: () => deleteIssueComment,
|
|
102105
|
+
deleteAttachment: () => deleteAttachment,
|
|
102106
|
+
createRalphyAttachment: () => createRalphyAttachment,
|
|
102107
|
+
createIssueLabel: () => createIssueLabel,
|
|
102108
|
+
createIssueComment: () => createIssueComment,
|
|
102109
|
+
createIssue: () => createIssue,
|
|
102110
|
+
createAttachmentForUrl: () => createAttachmentForUrl,
|
|
102111
|
+
clauseFromMarkers: () => clauseFromMarkers,
|
|
102112
|
+
buildIssueFilter: () => buildIssueFilter,
|
|
102113
|
+
baseBranchFromLabels: () => baseBranchFromLabels,
|
|
102114
|
+
addReactionToComment: () => addReactionToComment,
|
|
102115
|
+
addLabelToIssue: () => addLabelToIssue,
|
|
102116
|
+
addIssueComment: () => addIssueComment,
|
|
102117
|
+
RALPHY_ATTACHMENT_TITLE: () => RALPHY_ATTACHMENT_TITLE
|
|
102118
|
+
});
|
|
102119
|
+
function parseTicketIdentifier(raw) {
|
|
102120
|
+
const trimmed = raw.trim();
|
|
102121
|
+
if (!trimmed) {
|
|
102122
|
+
throw new Error("--ticket value cannot be empty");
|
|
102123
|
+
}
|
|
102124
|
+
const bare = TICKET_BARE_NUMBER_RE.exec(trimmed);
|
|
102125
|
+
if (bare) {
|
|
102126
|
+
return { teamKey: null, number: Number(bare[1]) };
|
|
102127
|
+
}
|
|
102128
|
+
const match = TICKET_IDENTIFIER_RE.exec(trimmed);
|
|
102129
|
+
if (!match) {
|
|
102130
|
+
const err = new Error("--ticket value is not a Linear ticket (expected e.g. RLF-208 or 208)");
|
|
102131
|
+
err.value = raw;
|
|
102132
|
+
throw err;
|
|
102133
|
+
}
|
|
102134
|
+
return { teamKey: match[1].toUpperCase(), number: Number(match[2]) };
|
|
102135
|
+
}
|
|
102136
|
+
function resolveTicketNumbers(tokens, team) {
|
|
102137
|
+
const teamKey = team?.trim() ? team.trim().toUpperCase() : null;
|
|
102138
|
+
const seen = new Set;
|
|
102139
|
+
const out = [];
|
|
102140
|
+
for (const token of tokens) {
|
|
102141
|
+
const { teamKey: parsedTeam, number: number4 } = parseTicketIdentifier(token);
|
|
102142
|
+
if (parsedTeam !== null) {
|
|
102143
|
+
if (teamKey !== null && parsedTeam !== teamKey) {
|
|
102144
|
+
const err = new Error("--ticket identifier is not in the configured team");
|
|
102145
|
+
err.ticket = token;
|
|
102146
|
+
err.team = team;
|
|
102147
|
+
throw err;
|
|
102148
|
+
}
|
|
102149
|
+
} else if (teamKey === null) {
|
|
102150
|
+
const err = new Error("--ticket bare number needs a configured team; pass --linear-team or set linear.team in config");
|
|
102151
|
+
err.ticket = token;
|
|
102152
|
+
throw err;
|
|
102153
|
+
}
|
|
102154
|
+
if (!seen.has(number4)) {
|
|
102155
|
+
seen.add(number4);
|
|
102156
|
+
out.push(number4);
|
|
102157
|
+
}
|
|
102158
|
+
}
|
|
102159
|
+
return out;
|
|
102160
|
+
}
|
|
102161
|
+
function formatTicketError(err) {
|
|
102162
|
+
if (!(err instanceof Error))
|
|
102163
|
+
return String(err);
|
|
102164
|
+
const e = err;
|
|
102165
|
+
const detail = e.ticket ?? e.value;
|
|
102166
|
+
const parts = [];
|
|
102167
|
+
if (detail)
|
|
102168
|
+
parts.push(`ticket: ${detail}`);
|
|
102169
|
+
if (e.team)
|
|
102170
|
+
parts.push(`configured team: ${e.team}`);
|
|
102171
|
+
return parts.length > 0 ? `${e.message} (${parts.join(", ")})` : e.message;
|
|
102172
|
+
}
|
|
101749
102173
|
function partition2(markers) {
|
|
101750
102174
|
const statuses = [];
|
|
101751
102175
|
const labels = [];
|
|
@@ -101778,6 +102202,9 @@ function buildIssueFilter(spec) {
|
|
|
101778
102202
|
} else {
|
|
101779
102203
|
where.assignee = { null: true };
|
|
101780
102204
|
}
|
|
102205
|
+
if (spec.numbers && spec.numbers.length > 0) {
|
|
102206
|
+
where.number = { in: spec.numbers };
|
|
102207
|
+
}
|
|
101781
102208
|
const inc = spec.include ?? [];
|
|
101782
102209
|
if (inc.length > 0) {
|
|
101783
102210
|
const { statuses, labels, attachmentSubtitles, projects } = partition2(inc);
|
|
@@ -101881,6 +102308,30 @@ function clauseFromMarkers(markers) {
|
|
|
101881
102308
|
parts.project = { name: { in: projects } };
|
|
101882
102309
|
return Object.keys(parts).length > 0 ? parts : null;
|
|
101883
102310
|
}
|
|
102311
|
+
function mapNodeProject(node2) {
|
|
102312
|
+
if (!node2.project)
|
|
102313
|
+
return null;
|
|
102314
|
+
return {
|
|
102315
|
+
id: node2.project.id,
|
|
102316
|
+
name: node2.project.name,
|
|
102317
|
+
...node2.project.priority !== undefined && node2.project.priority !== null ? { priority: node2.project.priority } : {}
|
|
102318
|
+
};
|
|
102319
|
+
}
|
|
102320
|
+
function mapNodeMilestone(node2) {
|
|
102321
|
+
const m = node2.projectMilestone;
|
|
102322
|
+
if (!m)
|
|
102323
|
+
return;
|
|
102324
|
+
return {
|
|
102325
|
+
id: m.id,
|
|
102326
|
+
name: m.name,
|
|
102327
|
+
sortOrder: m.sortOrder,
|
|
102328
|
+
...m.targetDate != null ? { targetDate: m.targetDate } : {}
|
|
102329
|
+
};
|
|
102330
|
+
}
|
|
102331
|
+
function milestoneSpread(node2) {
|
|
102332
|
+
const m = mapNodeMilestone(node2);
|
|
102333
|
+
return m ? { milestone: m } : {};
|
|
102334
|
+
}
|
|
101884
102335
|
async function fetchMentionScanIssues(apiKey, spec) {
|
|
101885
102336
|
const branches = [];
|
|
101886
102337
|
const { getTodo, getInProgress, setDone } = spec.indicators;
|
|
@@ -101901,21 +102352,27 @@ async function fetchMentionScanIssues(apiKey, spec) {
|
|
|
101901
102352
|
const where = branches.length === 1 ? { ...branches[0] } : { or: branches };
|
|
101902
102353
|
if (spec.team)
|
|
101903
102354
|
where.team = { key: { eq: spec.team } };
|
|
101904
|
-
if (spec.assignee) {
|
|
102355
|
+
if (spec.anyAssignee || spec.assignee === "any") {} else if (spec.assignee) {
|
|
101905
102356
|
if (spec.assignee === "me")
|
|
101906
102357
|
where.assignee = { isMe: { eq: true } };
|
|
102358
|
+
else if (spec.assignee === "unassigned")
|
|
102359
|
+
where.assignee = { null: true };
|
|
101907
102360
|
else if (spec.assignee.includes("@"))
|
|
101908
102361
|
where.assignee = { email: { eq: spec.assignee } };
|
|
101909
102362
|
else
|
|
101910
102363
|
where.assignee = { id: { eq: spec.assignee } };
|
|
101911
102364
|
}
|
|
102365
|
+
if (spec.numbers && spec.numbers.length > 0) {
|
|
102366
|
+
where.number = { in: spec.numbers };
|
|
102367
|
+
}
|
|
101912
102368
|
const query = `query MentionScanIssues($filter: IssueFilter) {
|
|
101913
102369
|
issues(filter: $filter, first: 50) {
|
|
101914
102370
|
nodes {
|
|
101915
102371
|
id identifier title description url priority createdAt
|
|
101916
102372
|
state { name type }
|
|
101917
102373
|
assignee { id email name }
|
|
101918
|
-
project { id name }
|
|
102374
|
+
project { id name priority }
|
|
102375
|
+
projectMilestone { id name sortOrder targetDate }
|
|
101919
102376
|
labels { nodes { name } }
|
|
101920
102377
|
relations(first: 50) {
|
|
101921
102378
|
nodes { type relatedIssue { id identifier state { type } } }
|
|
@@ -101938,7 +102395,8 @@ async function fetchMentionScanIssues(apiKey, spec) {
|
|
|
101938
102395
|
url: n.url,
|
|
101939
102396
|
state: n.state,
|
|
101940
102397
|
assignee: n.assignee,
|
|
101941
|
-
project: n
|
|
102398
|
+
project: mapNodeProject(n),
|
|
102399
|
+
...milestoneSpread(n),
|
|
101942
102400
|
labels: n.labels.nodes.map((l) => l.name),
|
|
101943
102401
|
priority: n.priority,
|
|
101944
102402
|
createdAt: n.createdAt ?? "",
|
|
@@ -101959,7 +102417,8 @@ async function fetchOpenIssues(apiKey, spec, options) {
|
|
|
101959
102417
|
id identifier title description url priority createdAt
|
|
101960
102418
|
state { name type }
|
|
101961
102419
|
assignee { id email name }
|
|
101962
|
-
project { id name }
|
|
102420
|
+
project { id name priority }
|
|
102421
|
+
projectMilestone { id name sortOrder targetDate }
|
|
101963
102422
|
labels { nodes { name } }
|
|
101964
102423
|
relations(first: 50) {
|
|
101965
102424
|
nodes {
|
|
@@ -101983,7 +102442,8 @@ async function fetchOpenIssues(apiKey, spec, options) {
|
|
|
101983
102442
|
url: n.url,
|
|
101984
102443
|
state: n.state,
|
|
101985
102444
|
assignee: n.assignee,
|
|
101986
|
-
project: n
|
|
102445
|
+
project: mapNodeProject(n),
|
|
102446
|
+
...milestoneSpread(n),
|
|
101987
102447
|
labels: n.labels.nodes.map((l) => l.name),
|
|
101988
102448
|
priority: n.priority,
|
|
101989
102449
|
createdAt: n.createdAt ?? "",
|
|
@@ -102496,9 +102956,11 @@ async function removeLabelFromIssue(apiKey, issueId, labelId) {
|
|
|
102496
102956
|
labelId
|
|
102497
102957
|
});
|
|
102498
102958
|
}
|
|
102499
|
-
var LINEAR_API = "https://api.linear.app/graphql", RALPHY_ATTACHMENT_TITLE_FILTER = "Ralphy", linearRequestInternals, MAX_LINEAR_ATTEMPTS = 3, MAX_RETRY_AFTER_MS = 2000, BODY_TRUNCATE_CHARS = 512, RALPHY_ATTACHMENT_TITLE = "Ralphy", BRANCH_LABEL_PREFIX = "ralph:branch:";
|
|
102959
|
+
var LINEAR_API = "https://api.linear.app/graphql", TICKET_IDENTIFIER_RE, TICKET_BARE_NUMBER_RE, RALPHY_ATTACHMENT_TITLE_FILTER = "Ralphy", linearRequestInternals, MAX_LINEAR_ATTEMPTS = 3, MAX_RETRY_AFTER_MS = 2000, BODY_TRUNCATE_CHARS = 512, RALPHY_ATTACHMENT_TITLE = "Ralphy", BRANCH_LABEL_PREFIX = "ralph:branch:";
|
|
102500
102960
|
var init_linear_client = __esm(() => {
|
|
102501
102961
|
init_types2();
|
|
102962
|
+
TICKET_IDENTIFIER_RE = /^([A-Za-z]+)-(\d+)(?:-.*)?$/;
|
|
102963
|
+
TICKET_BARE_NUMBER_RE = /^(\d+)$/;
|
|
102502
102964
|
linearRequestInternals = {
|
|
102503
102965
|
sleep: (ms) => Bun.sleep(ms)
|
|
102504
102966
|
};
|
|
@@ -104121,17 +104583,183 @@ var init_post_task = __esm(() => {
|
|
|
104121
104583
|
repoAutoMergeCache = new Map;
|
|
104122
104584
|
});
|
|
104123
104585
|
|
|
104124
|
-
//
|
|
104125
|
-
function
|
|
104126
|
-
return
|
|
104127
|
-
|
|
104128
|
-
|
|
104129
|
-
|
|
104130
|
-
return r;
|
|
104131
|
-
}
|
|
104586
|
+
// packages/core/src/ordering/hierarchical-order.ts
|
|
104587
|
+
function rank(priority) {
|
|
104588
|
+
return !priority ? Number.POSITIVE_INFINITY : priority;
|
|
104589
|
+
}
|
|
104590
|
+
function cmpMaybe(a, b, cmp) {
|
|
104591
|
+
if (a === undefined && b === undefined)
|
|
104132
104592
|
return 0;
|
|
104133
|
-
|
|
104593
|
+
if (a === undefined)
|
|
104594
|
+
return 1;
|
|
104595
|
+
if (b === undefined)
|
|
104596
|
+
return -1;
|
|
104597
|
+
return cmp(a, b);
|
|
104598
|
+
}
|
|
104599
|
+
function cmpString(a, b) {
|
|
104600
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
104134
104601
|
}
|
|
104602
|
+
function cmpNumber(a, b) {
|
|
104603
|
+
return a - b;
|
|
104604
|
+
}
|
|
104605
|
+
function cmpRank(a, b) {
|
|
104606
|
+
return a === b ? 0 : a < b ? -1 : 1;
|
|
104607
|
+
}
|
|
104608
|
+
function orderIssuesHierarchically(issues, opts = {}) {
|
|
104609
|
+
const log3 = opts.log ?? ((message) => console.warn(message));
|
|
104610
|
+
if (issues.length <= 1)
|
|
104611
|
+
return issues.slice();
|
|
104612
|
+
const projectBuckets = new Map;
|
|
104613
|
+
for (const issue2 of issues) {
|
|
104614
|
+
const key = issue2.project?.id ?? NO_PROJECT;
|
|
104615
|
+
const bucket = projectBuckets.get(key);
|
|
104616
|
+
if (bucket)
|
|
104617
|
+
bucket.push(issue2);
|
|
104618
|
+
else
|
|
104619
|
+
projectBuckets.set(key, [issue2]);
|
|
104620
|
+
}
|
|
104621
|
+
const projectKeys = [...projectBuckets.keys()].sort((a, b) => {
|
|
104622
|
+
if (a === NO_PROJECT)
|
|
104623
|
+
return b === NO_PROJECT ? 0 : 1;
|
|
104624
|
+
if (b === NO_PROJECT)
|
|
104625
|
+
return -1;
|
|
104626
|
+
const ba = projectBuckets.get(a);
|
|
104627
|
+
const bb = projectBuckets.get(b);
|
|
104628
|
+
const ra = rank(ba[0]?.project?.priority);
|
|
104629
|
+
const rb = rank(bb[0]?.project?.priority);
|
|
104630
|
+
if (ra !== rb)
|
|
104631
|
+
return cmpRank(ra, rb);
|
|
104632
|
+
if (a !== b)
|
|
104633
|
+
return cmpString(a, b);
|
|
104634
|
+
return cmpString(earliestCreatedAt(ba), earliestCreatedAt(bb));
|
|
104635
|
+
});
|
|
104636
|
+
const ordered = [];
|
|
104637
|
+
for (const projectKey of projectKeys) {
|
|
104638
|
+
orderProjectBucket(projectBuckets.get(projectKey), ordered, log3);
|
|
104639
|
+
}
|
|
104640
|
+
return ordered;
|
|
104641
|
+
}
|
|
104642
|
+
function earliestCreatedAt(bucket) {
|
|
104643
|
+
let earliest = bucket[0].createdAt;
|
|
104644
|
+
for (const issue2 of bucket) {
|
|
104645
|
+
if (issue2.createdAt < earliest)
|
|
104646
|
+
earliest = issue2.createdAt;
|
|
104647
|
+
}
|
|
104648
|
+
return earliest;
|
|
104649
|
+
}
|
|
104650
|
+
function orderProjectBucket(bucket, ordered, log3) {
|
|
104651
|
+
const milestoneBuckets = new Map;
|
|
104652
|
+
for (const issue2 of bucket) {
|
|
104653
|
+
const key = issue2.milestone?.id ?? NO_MILESTONE;
|
|
104654
|
+
const b = milestoneBuckets.get(key);
|
|
104655
|
+
if (b)
|
|
104656
|
+
b.push(issue2);
|
|
104657
|
+
else
|
|
104658
|
+
milestoneBuckets.set(key, [issue2]);
|
|
104659
|
+
}
|
|
104660
|
+
const milestoneOf = new Map;
|
|
104661
|
+
for (const [key, b] of milestoneBuckets) {
|
|
104662
|
+
for (const issue2 of b)
|
|
104663
|
+
milestoneOf.set(issue2.id, key);
|
|
104664
|
+
}
|
|
104665
|
+
const milestonePrereqs = new Map;
|
|
104666
|
+
for (const key of milestoneBuckets.keys())
|
|
104667
|
+
milestonePrereqs.set(key, new Set);
|
|
104668
|
+
for (const issue2 of bucket) {
|
|
104669
|
+
const from = milestoneOf.get(issue2.id);
|
|
104670
|
+
for (const blockerId of issue2.blockedByIds) {
|
|
104671
|
+
const blockerMilestone = milestoneOf.get(blockerId);
|
|
104672
|
+
if (blockerMilestone === undefined)
|
|
104673
|
+
continue;
|
|
104674
|
+
if (blockerMilestone === from)
|
|
104675
|
+
continue;
|
|
104676
|
+
milestonePrereqs.get(from).add(blockerMilestone);
|
|
104677
|
+
}
|
|
104678
|
+
}
|
|
104679
|
+
const milestoneMeta = new Map;
|
|
104680
|
+
for (const [key, b] of milestoneBuckets) {
|
|
104681
|
+
milestoneMeta.set(key, key === NO_MILESTONE ? undefined : b[0].milestone);
|
|
104682
|
+
}
|
|
104683
|
+
const milestoneOrder = topoOrder([...milestoneBuckets.keys()], (key) => milestonePrereqs.get(key), (a, b) => {
|
|
104684
|
+
if (a === NO_MILESTONE)
|
|
104685
|
+
return b === NO_MILESTONE ? 0 : 1;
|
|
104686
|
+
if (b === NO_MILESTONE)
|
|
104687
|
+
return -1;
|
|
104688
|
+
const ma = milestoneMeta.get(a);
|
|
104689
|
+
const mb = milestoneMeta.get(b);
|
|
104690
|
+
const so = cmpNumber(ma?.sortOrder ?? 0, mb?.sortOrder ?? 0);
|
|
104691
|
+
if (so !== 0)
|
|
104692
|
+
return so;
|
|
104693
|
+
const td = cmpMaybe(ma?.targetDate, mb?.targetDate, cmpString);
|
|
104694
|
+
if (td !== 0)
|
|
104695
|
+
return td;
|
|
104696
|
+
return cmpString(a, b);
|
|
104697
|
+
}, (key) => log3(`hierarchical-order: milestone dependency cycle involving "${key}"; breaking by selection key`));
|
|
104698
|
+
for (const milestoneKey of milestoneOrder) {
|
|
104699
|
+
orderMilestoneBucket(milestoneBuckets.get(milestoneKey), ordered, log3);
|
|
104700
|
+
}
|
|
104701
|
+
}
|
|
104702
|
+
function orderMilestoneBucket(bucket, ordered, log3) {
|
|
104703
|
+
const inBucket = new Set(bucket.map((i) => i.id));
|
|
104704
|
+
const byId = new Map(bucket.map((i) => [i.id, i]));
|
|
104705
|
+
const order = topoOrder(bucket.map((i) => i.id), (id) => {
|
|
104706
|
+
const prereqs = new Set;
|
|
104707
|
+
for (const blockerId of byId.get(id).blockedByIds) {
|
|
104708
|
+
if (inBucket.has(blockerId))
|
|
104709
|
+
prereqs.add(blockerId);
|
|
104710
|
+
}
|
|
104711
|
+
return prereqs;
|
|
104712
|
+
}, (a, b) => {
|
|
104713
|
+
const ia = byId.get(a);
|
|
104714
|
+
const ib = byId.get(b);
|
|
104715
|
+
const rp = cmpRank(rank(ia.priority), rank(ib.priority));
|
|
104716
|
+
if (rp !== 0)
|
|
104717
|
+
return rp;
|
|
104718
|
+
const tb = cmpNumber(ia.tiebreak ?? 0, ib.tiebreak ?? 0);
|
|
104719
|
+
if (tb !== 0)
|
|
104720
|
+
return tb;
|
|
104721
|
+
const cc = cmpString(ia.createdAt, ib.createdAt);
|
|
104722
|
+
if (cc !== 0)
|
|
104723
|
+
return cc;
|
|
104724
|
+
return cmpString(a, b);
|
|
104725
|
+
}, (id) => log3(`hierarchical-order: item dependency cycle involving "${id}"; breaking by selection key`));
|
|
104726
|
+
for (const id of order)
|
|
104727
|
+
ordered.push(byId.get(id));
|
|
104728
|
+
}
|
|
104729
|
+
function topoOrder(nodes, prereqsOf, select2, onCycle) {
|
|
104730
|
+
const remaining = new Set(nodes);
|
|
104731
|
+
const placed = new Set;
|
|
104732
|
+
const result2 = [];
|
|
104733
|
+
while (remaining.size > 0) {
|
|
104734
|
+
const eligible = [];
|
|
104735
|
+
for (const node2 of remaining) {
|
|
104736
|
+
let ready = true;
|
|
104737
|
+
for (const prereq of prereqsOf(node2)) {
|
|
104738
|
+
if (remaining.has(prereq) && !placed.has(prereq)) {
|
|
104739
|
+
ready = false;
|
|
104740
|
+
break;
|
|
104741
|
+
}
|
|
104742
|
+
}
|
|
104743
|
+
if (ready)
|
|
104744
|
+
eligible.push(node2);
|
|
104745
|
+
}
|
|
104746
|
+
let pick3;
|
|
104747
|
+
if (eligible.length > 0) {
|
|
104748
|
+
pick3 = eligible.sort(select2)[0];
|
|
104749
|
+
} else {
|
|
104750
|
+
pick3 = [...remaining].sort(select2)[0];
|
|
104751
|
+
onCycle(pick3);
|
|
104752
|
+
}
|
|
104753
|
+
result2.push(pick3);
|
|
104754
|
+
placed.add(pick3);
|
|
104755
|
+
remaining.delete(pick3);
|
|
104756
|
+
}
|
|
104757
|
+
return result2;
|
|
104758
|
+
}
|
|
104759
|
+
var NO_PROJECT = "\x00no-project", NO_MILESTONE = "\x00no-milestone";
|
|
104760
|
+
|
|
104761
|
+
// packages/core/src/ordering/index.ts
|
|
104762
|
+
var init_ordering = () => {};
|
|
104135
104763
|
|
|
104136
104764
|
// apps/agent/src/queue/queue-order.ts
|
|
104137
104765
|
function defaultPriorityFor(trigger) {
|
|
@@ -104148,21 +104776,70 @@ function defaultPriorityFor(trigger) {
|
|
|
104148
104776
|
return 4;
|
|
104149
104777
|
}
|
|
104150
104778
|
}
|
|
104151
|
-
function
|
|
104152
|
-
|
|
104153
|
-
|
|
104154
|
-
|
|
104155
|
-
|
|
104156
|
-
|
|
104157
|
-
|
|
104158
|
-
|
|
104159
|
-
|
|
104160
|
-
|
|
104161
|
-
|
|
104162
|
-
|
|
104163
|
-
|
|
104779
|
+
function isAutoMergeBoost(e, getAutoMerge) {
|
|
104780
|
+
return e.trigger === "conflict-fix" && issueMatchesGetIndicator(e.issue, getAutoMerge);
|
|
104781
|
+
}
|
|
104782
|
+
function linearIssueToOrderable(issue2, tiebreak) {
|
|
104783
|
+
return {
|
|
104784
|
+
id: issue2.id,
|
|
104785
|
+
...issue2.project ? {
|
|
104786
|
+
project: {
|
|
104787
|
+
id: issue2.project.id,
|
|
104788
|
+
...issue2.project.priority !== undefined ? { priority: issue2.project.priority } : {}
|
|
104789
|
+
}
|
|
104790
|
+
} : {},
|
|
104791
|
+
...issue2.milestone ? {
|
|
104792
|
+
milestone: {
|
|
104793
|
+
id: issue2.milestone.id,
|
|
104794
|
+
sortOrder: issue2.milestone.sortOrder,
|
|
104795
|
+
...issue2.milestone.targetDate ? { targetDate: issue2.milestone.targetDate } : {}
|
|
104796
|
+
}
|
|
104797
|
+
} : {},
|
|
104798
|
+
priority: issue2.priority,
|
|
104799
|
+
...tiebreak !== undefined ? { tiebreak } : {},
|
|
104800
|
+
blockedByIds: issue2.blockedByIds,
|
|
104801
|
+
createdAt: issue2.createdAt
|
|
104802
|
+
};
|
|
104803
|
+
}
|
|
104804
|
+
function toOrderable(entry) {
|
|
104805
|
+
return { ...linearIssueToOrderable(entry.issue, entry.priority), entry };
|
|
104806
|
+
}
|
|
104807
|
+
function orderEntries(entries) {
|
|
104808
|
+
if (entries.length <= 1)
|
|
104809
|
+
return entries.slice();
|
|
104810
|
+
const repByIssue = new Map;
|
|
104811
|
+
for (const entry of entries) {
|
|
104812
|
+
const orderable = toOrderable(entry);
|
|
104813
|
+
const existing = repByIssue.get(orderable.id);
|
|
104814
|
+
if (!existing || orderable.tiebreak < existing.tiebreak) {
|
|
104815
|
+
repByIssue.set(orderable.id, orderable);
|
|
104816
|
+
}
|
|
104817
|
+
}
|
|
104818
|
+
const rankOf = new Map;
|
|
104819
|
+
orderIssuesHierarchically([...repByIssue.values()]).forEach((o, i) => rankOf.set(o.id, i));
|
|
104820
|
+
return entries.map((entry, index) => ({ entry, index })).sort((a, b) => {
|
|
104821
|
+
const ra = rankOf.get(a.entry.issue.id);
|
|
104822
|
+
const rb = rankOf.get(b.entry.issue.id);
|
|
104823
|
+
if (ra !== rb)
|
|
104824
|
+
return ra - rb;
|
|
104825
|
+
if (a.entry.priority !== b.entry.priority)
|
|
104826
|
+
return a.entry.priority - b.entry.priority;
|
|
104827
|
+
return a.index - b.index;
|
|
104828
|
+
}).map((x) => x.entry);
|
|
104829
|
+
}
|
|
104830
|
+
function orderQueueEntries(entries, getAutoMerge) {
|
|
104831
|
+
const boosted = [];
|
|
104832
|
+
const rest2 = [];
|
|
104833
|
+
for (const e of entries) {
|
|
104834
|
+
if (isAutoMergeBoost(e, getAutoMerge))
|
|
104835
|
+
boosted.push(e);
|
|
104836
|
+
else
|
|
104837
|
+
rest2.push(e);
|
|
104838
|
+
}
|
|
104839
|
+
return [...orderEntries(boosted), ...orderEntries(rest2)];
|
|
104164
104840
|
}
|
|
104165
104841
|
var init_queue_order = __esm(() => {
|
|
104842
|
+
init_ordering();
|
|
104166
104843
|
init_linear();
|
|
104167
104844
|
});
|
|
104168
104845
|
|
|
@@ -104280,6 +104957,7 @@ class AgentCoordinator {
|
|
|
104280
104957
|
ciFailed: 0,
|
|
104281
104958
|
review: 0,
|
|
104282
104959
|
mentions: mentions.length,
|
|
104960
|
+
quarantined: 0,
|
|
104283
104961
|
awaiting: awaitingCount
|
|
104284
104962
|
};
|
|
104285
104963
|
const found2 = buckets2.todo + buckets2.inProgress + buckets2.mentions + buckets2.awaiting;
|
|
@@ -104362,7 +105040,7 @@ class AgentCoordinator {
|
|
|
104362
105040
|
}
|
|
104363
105041
|
const prStatus = await this.scanPrMergeStates();
|
|
104364
105042
|
if (this.queue.length > 0) {
|
|
104365
|
-
this.queue
|
|
105043
|
+
this.queue = orderQueueEntries(this.queue, this.opts.getAutoMerge);
|
|
104366
105044
|
}
|
|
104367
105045
|
this.spawnNext();
|
|
104368
105046
|
await this.reportProgress();
|
|
@@ -104374,6 +105052,7 @@ class AgentCoordinator {
|
|
|
104374
105052
|
ciFailed: prStatus.ciFailed,
|
|
104375
105053
|
review: 0,
|
|
104376
105054
|
mentions: mentions.length,
|
|
105055
|
+
quarantined: prStatus.quarantined,
|
|
104377
105056
|
awaiting: awaitingCount
|
|
104378
105057
|
};
|
|
104379
105058
|
const found = buckets.todo + buckets.inProgress + buckets.conflicted + buckets.ciFailed + buckets.mentions + buckets.awaiting;
|
|
@@ -104569,6 +105248,7 @@ class AgentCoordinator {
|
|
|
104569
105248
|
return counts;
|
|
104570
105249
|
const preQueue = this.queue.map((q) => ({ id: q.issue.id, trigger: q.trigger }));
|
|
104571
105250
|
const preWorkers = this.workers.map((w) => ({ id: w.issueId, trigger: w.trigger }));
|
|
105251
|
+
const tracker = this.opts.prTracker;
|
|
104572
105252
|
for (const issue2 of candidates) {
|
|
104573
105253
|
if (this.workers.some((w) => w.issueId === issue2.id))
|
|
104574
105254
|
continue;
|
|
@@ -104576,6 +105256,13 @@ class AgentCoordinator {
|
|
|
104576
105256
|
continue;
|
|
104577
105257
|
if (this.queue.some((q) => q.issue.id === issue2.id))
|
|
104578
105258
|
continue;
|
|
105259
|
+
if (tracker?.isBailed(issue2.identifier) && this.errorMarkerCleared(issue2)) {
|
|
105260
|
+
await tracker.clear(issue2.identifier).catch(() => {});
|
|
105261
|
+
this.conflictNotified.delete(issue2.id);
|
|
105262
|
+
this.ciFailedNotified.delete(issue2.id);
|
|
105263
|
+
this.conflictPromoted.delete(issue2.id);
|
|
105264
|
+
this.deps.onLog(` ${issue2.identifier}: pr-tracker bail cleared (ticket back in Todo) \u2014 retrying recovery`, "cyan");
|
|
105265
|
+
}
|
|
104579
105266
|
let pr;
|
|
104580
105267
|
try {
|
|
104581
105268
|
pr = await this.deps.checkPrStatus(issue2);
|
|
@@ -104595,10 +105282,18 @@ class AgentCoordinator {
|
|
|
104595
105282
|
}
|
|
104596
105283
|
}
|
|
104597
105284
|
if (pr.status === "conflicted") {
|
|
105285
|
+
if (tracker?.isBailed(issue2.identifier)) {
|
|
105286
|
+
counts.quarantined += 1;
|
|
105287
|
+
continue;
|
|
105288
|
+
}
|
|
105289
|
+
counts.conflicted += 1;
|
|
104598
105290
|
if (this.conflictNotified.has(issue2.id))
|
|
104599
105291
|
continue;
|
|
104600
|
-
if (await this.prTrackerBail(issue2, pr.url, "conflicting"))
|
|
105292
|
+
if (await this.prTrackerBail(issue2, pr.url, "conflicting")) {
|
|
105293
|
+
counts.conflicted -= 1;
|
|
105294
|
+
counts.quarantined += 1;
|
|
104601
105295
|
continue;
|
|
105296
|
+
}
|
|
104602
105297
|
emitCapture(this.bus, "agent_conflict_detected", { issue_identifier: issue2.identifier });
|
|
104603
105298
|
this.conflictNotified.add(issue2.id);
|
|
104604
105299
|
this.deps.onLog(` ${issue2.identifier}: PR ${pr.url} conflicting \u2014 queued (conflict-fix)`, "yellow");
|
|
@@ -104617,14 +105312,21 @@ class AgentCoordinator {
|
|
|
104617
105312
|
trigger: "conflict-fix",
|
|
104618
105313
|
priority: defaultPriorityFor("conflict-fix")
|
|
104619
105314
|
});
|
|
104620
|
-
counts.conflicted += 1;
|
|
104621
105315
|
continue;
|
|
104622
105316
|
}
|
|
104623
105317
|
if (pr.status === "ci_failed") {
|
|
105318
|
+
if (tracker?.isBailed(issue2.identifier)) {
|
|
105319
|
+
counts.quarantined += 1;
|
|
105320
|
+
continue;
|
|
105321
|
+
}
|
|
105322
|
+
counts.ciFailed += 1;
|
|
104624
105323
|
if (this.ciFailedNotified.has(issue2.id))
|
|
104625
105324
|
continue;
|
|
104626
|
-
if (await this.prTrackerBail(issue2, pr.url, "ci_failed"))
|
|
105325
|
+
if (await this.prTrackerBail(issue2, pr.url, "ci_failed")) {
|
|
105326
|
+
counts.ciFailed -= 1;
|
|
105327
|
+
counts.quarantined += 1;
|
|
104627
105328
|
continue;
|
|
105329
|
+
}
|
|
104628
105330
|
emitCapture(this.bus, "agent_ci_failed_detected", { issue_identifier: issue2.identifier });
|
|
104629
105331
|
this.ciFailedNotified.add(issue2.id);
|
|
104630
105332
|
this.deps.onLog(` ${issue2.identifier}: PR ${pr.url} CI failing \u2014 queued (ci-fix)`, "yellow");
|
|
@@ -104643,7 +105345,6 @@ class AgentCoordinator {
|
|
|
104643
105345
|
trigger: "ci-fix",
|
|
104644
105346
|
priority: defaultPriorityFor("ci-fix")
|
|
104645
105347
|
});
|
|
104646
|
-
counts.ciFailed += 1;
|
|
104647
105348
|
}
|
|
104648
105349
|
}
|
|
104649
105350
|
for (const q of preQueue) {
|
|
@@ -104660,6 +105361,16 @@ class AgentCoordinator {
|
|
|
104660
105361
|
}
|
|
104661
105362
|
return counts;
|
|
104662
105363
|
}
|
|
105364
|
+
errorMarkerCleared(issue2) {
|
|
105365
|
+
const se = this.opts.setError;
|
|
105366
|
+
if (!se)
|
|
105367
|
+
return false;
|
|
105368
|
+
const wantLabels = markersOf(se).filter((m) => m.type === "label").map((m) => m.value.toLowerCase());
|
|
105369
|
+
if (wantLabels.length === 0)
|
|
105370
|
+
return false;
|
|
105371
|
+
const have = new Set(issue2.labels.map((l) => l.toLowerCase()));
|
|
105372
|
+
return !wantLabels.some((v) => have.has(v));
|
|
105373
|
+
}
|
|
104663
105374
|
async prTrackerBail(issue2, prUrl, reason) {
|
|
104664
105375
|
const tracker = this.opts.prTracker;
|
|
104665
105376
|
if (!tracker)
|
|
@@ -105039,7 +105750,12 @@ function triggerToFlowId(trigger) {
|
|
|
105039
105750
|
return "review-followup";
|
|
105040
105751
|
return "implement";
|
|
105041
105752
|
}
|
|
105042
|
-
var emptyPrStatus = () => ({
|
|
105753
|
+
var emptyPrStatus = () => ({
|
|
105754
|
+
mergeable: 0,
|
|
105755
|
+
conflicted: 0,
|
|
105756
|
+
ciFailed: 0,
|
|
105757
|
+
quarantined: 0
|
|
105758
|
+
}), emptyPollResult = () => ({
|
|
105043
105759
|
found: 0,
|
|
105044
105760
|
added: 0,
|
|
105045
105761
|
buckets: {
|
|
@@ -105049,6 +105765,7 @@ var emptyPrStatus = () => ({ mergeable: 0, conflicted: 0, ciFailed: 0 }), emptyP
|
|
|
105049
105765
|
ciFailed: 0,
|
|
105050
105766
|
review: 0,
|
|
105051
105767
|
mentions: 0,
|
|
105768
|
+
quarantined: 0,
|
|
105052
105769
|
awaiting: 0
|
|
105053
105770
|
},
|
|
105054
105771
|
prStatus: emptyPrStatus(),
|
|
@@ -105056,6 +105773,7 @@ var emptyPrStatus = () => ({ mergeable: 0, conflicted: 0, ciFailed: 0 }), emptyP
|
|
|
105056
105773
|
flow: {}
|
|
105057
105774
|
});
|
|
105058
105775
|
var init_coordinator = __esm(() => {
|
|
105776
|
+
init_types2();
|
|
105059
105777
|
init_post_task();
|
|
105060
105778
|
init_queue_order();
|
|
105061
105779
|
init_src();
|
|
@@ -105937,10 +106655,10 @@ function unionMarkers(...sets) {
|
|
|
105937
106655
|
}
|
|
105938
106656
|
return out;
|
|
105939
106657
|
}
|
|
105940
|
-
function describeIndicators(indicators, team, assignee) {
|
|
106658
|
+
function describeIndicators(indicators, team, assignee, anyAssignee) {
|
|
105941
106659
|
const parts = [];
|
|
105942
106660
|
parts.push(`team=${team ?? "*"}`);
|
|
105943
|
-
parts.push(`assignee=${assignee ?? "*"}`);
|
|
106661
|
+
parts.push(`assignee=${anyAssignee ? "any" : assignee ?? "*"}`);
|
|
105944
106662
|
if (indicators.getTodo) {
|
|
105945
106663
|
parts.push(`todo=[${indicators.getTodo.filter.map((m) => `${m.type}:${m.value}`).join(",")}]`);
|
|
105946
106664
|
}
|
|
@@ -105955,7 +106673,8 @@ var init_indicators = __esm(() => {
|
|
|
105955
106673
|
|
|
105956
106674
|
// apps/agent/src/agent/wire/linear-resolvers.ts
|
|
105957
106675
|
function createLinearResolvers(input) {
|
|
105958
|
-
const { apiKey, team, assignee, diag } = input;
|
|
106676
|
+
const { apiKey, team, assignee, anyAssignee, diag } = input;
|
|
106677
|
+
const ticketNumbers = input.ticketNumbers ?? [];
|
|
105959
106678
|
const stateCache = new Map;
|
|
105960
106679
|
const labelCache = new Map;
|
|
105961
106680
|
const teamIdCache = new Map;
|
|
@@ -106067,7 +106786,14 @@ function createLinearResolvers(input) {
|
|
|
106067
106786
|
if (include.length === 0)
|
|
106068
106787
|
return [];
|
|
106069
106788
|
const hasCommentMarker = include.some((m) => m.type === "comment");
|
|
106070
|
-
const spec = {
|
|
106789
|
+
const spec = {
|
|
106790
|
+
team,
|
|
106791
|
+
assignee,
|
|
106792
|
+
anyAssignee,
|
|
106793
|
+
include,
|
|
106794
|
+
exclude: excl,
|
|
106795
|
+
...ticketNumbers.length > 0 ? { numbers: ticketNumbers } : {}
|
|
106796
|
+
};
|
|
106071
106797
|
const fetched = await fetchOpenIssues(apiKey, spec, hasCommentMarker ? { includeComments: true } : undefined);
|
|
106072
106798
|
if (!hasCommentMarker)
|
|
106073
106799
|
return fetched;
|
|
@@ -106086,7 +106812,7 @@ function createLinearResolvers(input) {
|
|
|
106086
106812
|
resolveLabelIdForTeam
|
|
106087
106813
|
};
|
|
106088
106814
|
}
|
|
106089
|
-
async function fetchDoneCandidatesWith(apiKey, team, _assignee, indicators) {
|
|
106815
|
+
async function fetchDoneCandidatesWith(apiKey, team, _assignee, indicators, ticketNumbers) {
|
|
106090
106816
|
const getIndicators = [
|
|
106091
106817
|
indicators.getTodo,
|
|
106092
106818
|
indicators.getInProgress,
|
|
@@ -106109,7 +106835,8 @@ async function fetchDoneCandidatesWith(apiKey, team, _assignee, indicators) {
|
|
|
106109
106835
|
team,
|
|
106110
106836
|
anyAssignee: true,
|
|
106111
106837
|
include,
|
|
106112
|
-
exclude: []
|
|
106838
|
+
exclude: [],
|
|
106839
|
+
...ticketNumbers && ticketNumbers.length > 0 ? { numbers: ticketNumbers } : {}
|
|
106113
106840
|
});
|
|
106114
106841
|
for (const issue2 of issues) {
|
|
106115
106842
|
if (!seen.has(issue2.id)) {
|
|
@@ -106598,7 +107325,7 @@ async function fetchPrReviewState(prUrl, cmdRunner, projectRoot, onLog) {
|
|
|
106598
107325
|
reviewRequests(first:5){nodes{requestedReviewer{... on User{login}}}}
|
|
106599
107326
|
latestReviews(first:5){nodes{author{login} state submittedAt}}
|
|
106600
107327
|
reviewThreads(first:50){nodes{
|
|
106601
|
-
isResolved path line
|
|
107328
|
+
isResolved subjectType path line
|
|
106602
107329
|
comments(first:20){nodes{body author{login} createdAt url}}
|
|
106603
107330
|
}}
|
|
106604
107331
|
}
|
|
@@ -106631,6 +107358,7 @@ async function fetchPrReviewState(prUrl, cmdRunner, projectRoot, onLog) {
|
|
|
106631
107358
|
approved: pr2.reviewDecision === "APPROVED",
|
|
106632
107359
|
threads: (pr2.reviewThreads?.nodes ?? []).map((t) => ({
|
|
106633
107360
|
isResolved: t.isResolved,
|
|
107361
|
+
isFileLevel: t.subjectType === "FILE",
|
|
106634
107362
|
...t.path ? { path: t.path } : {},
|
|
106635
107363
|
...t.line != null ? { line: t.line } : {},
|
|
106636
107364
|
comments: t.comments.nodes.map((c) => ({
|
|
@@ -106697,7 +107425,7 @@ async function scanCodeReview(issue2, prUrl, lastRalphPickup, deps) {
|
|
|
106697
107425
|
const effectiveLastHandled = lastRalphPickup && lastHandled ? lastRalphPickup > lastHandled ? lastRalphPickup : lastHandled : lastRalphPickup ?? lastHandled;
|
|
106698
107426
|
if (!effectiveLastHandled || newestReviewerActivity > effectiveLastHandled) {
|
|
106699
107427
|
const body = unresolved.map((t) => {
|
|
106700
|
-
const head3 = t.path ? `_${t.path}${t.line ? `:${t.line}` : ""}_` : "_(general)_";
|
|
107428
|
+
const head3 = t.path ? t.isFileLevel ? `_${t.path} (whole file)_` : `_${t.path}${t.line ? `:${t.line}` : ""}_` : "_(general)_";
|
|
106701
107429
|
const lines = t.comments.map((c) => `> **${c.author ?? "reviewer"}** (${c.createdAt})
|
|
106702
107430
|
>
|
|
106703
107431
|
> ${c.body.trim().replace(/\n/g, `
|
|
@@ -106795,6 +107523,7 @@ function createMentionScanner(input) {
|
|
|
106795
107523
|
cfg,
|
|
106796
107524
|
team,
|
|
106797
107525
|
assignee,
|
|
107526
|
+
anyAssignee,
|
|
106798
107527
|
indicators,
|
|
106799
107528
|
projectRoot,
|
|
106800
107529
|
useWorktree,
|
|
@@ -106802,6 +107531,7 @@ function createMentionScanner(input) {
|
|
|
106802
107531
|
onLog,
|
|
106803
107532
|
diag,
|
|
106804
107533
|
cwdByChange,
|
|
107534
|
+
ticketNumbers,
|
|
106805
107535
|
stalePingedAt,
|
|
106806
107536
|
lastHandledReviewActivity,
|
|
106807
107537
|
resolvePrUrlForIssue
|
|
@@ -106817,6 +107547,8 @@ function createMentionScanner(input) {
|
|
|
106817
107547
|
candidates = await fetchMentionScanIssues(apiKey, {
|
|
106818
107548
|
team,
|
|
106819
107549
|
assignee,
|
|
107550
|
+
anyAssignee,
|
|
107551
|
+
...ticketNumbers && ticketNumbers.length > 0 ? { numbers: ticketNumbers } : {},
|
|
106820
107552
|
indicators: {
|
|
106821
107553
|
...indicators.getTodo !== undefined ? { getTodo: indicators.getTodo } : {},
|
|
106822
107554
|
...indicators.getInProgress !== undefined ? { getInProgress: indicators.getInProgress } : {},
|
|
@@ -239295,9 +240027,9 @@ class $50c7aac9316f2948$export$2e2bcd8739ae039 {
|
|
|
239295
240027
|
|
|
239296
240028
|
class $55f71433a605c87d$export$2e2bcd8739ae039 {
|
|
239297
240029
|
process(glyphs, features = {}) {
|
|
239298
|
-
for (let
|
|
239299
|
-
let flags =
|
|
239300
|
-
for (let feature of
|
|
240030
|
+
for (let chain of this.morx.chains) {
|
|
240031
|
+
let flags = chain.defaultFlags;
|
|
240032
|
+
for (let feature of chain.features) {
|
|
239301
240033
|
let f2;
|
|
239302
240034
|
if (f2 = features[feature.featureType]) {
|
|
239303
240035
|
if (f2[feature.featureSetting]) {
|
|
@@ -239309,7 +240041,7 @@ class $55f71433a605c87d$export$2e2bcd8739ae039 {
|
|
|
239309
240041
|
}
|
|
239310
240042
|
}
|
|
239311
240043
|
}
|
|
239312
|
-
for (let subtable of
|
|
240044
|
+
for (let subtable of chain.subtables)
|
|
239313
240045
|
if (subtable.subFeatureFlags & flags)
|
|
239314
240046
|
this.processSubtable(subtable, glyphs);
|
|
239315
240047
|
}
|
|
@@ -239456,8 +240188,8 @@ class $55f71433a605c87d$export$2e2bcd8739ae039 {
|
|
|
239456
240188
|
}
|
|
239457
240189
|
getSupportedFeatures() {
|
|
239458
240190
|
let features = [];
|
|
239459
|
-
for (let
|
|
239460
|
-
for (let feature of
|
|
240191
|
+
for (let chain of this.morx.chains)
|
|
240192
|
+
for (let feature of chain.features)
|
|
239461
240193
|
features.push([
|
|
239462
240194
|
feature.featureType,
|
|
239463
240195
|
feature.featureSetting
|
|
@@ -239471,9 +240203,9 @@ class $55f71433a605c87d$export$2e2bcd8739ae039 {
|
|
|
239471
240203
|
}
|
|
239472
240204
|
generateInputCache() {
|
|
239473
240205
|
this.inputCache = {};
|
|
239474
|
-
for (let
|
|
239475
|
-
let flags =
|
|
239476
|
-
for (let subtable of
|
|
240206
|
+
for (let chain of this.morx.chains) {
|
|
240207
|
+
let flags = chain.defaultFlags;
|
|
240208
|
+
for (let subtable of chain.subtables)
|
|
239477
240209
|
if (subtable.subFeatureFlags & flags)
|
|
239478
240210
|
this.generateInputsForSubtable(subtable);
|
|
239479
240211
|
}
|
|
@@ -260555,7 +261287,9 @@ function buildAgentCoordinator(input) {
|
|
|
260555
261287
|
const pollInterval = args.pollInterval || cfg.pollIntervalSeconds;
|
|
260556
261288
|
const indicators = mergeIndicators(cfg.linear.indicators, args.indicators);
|
|
260557
261289
|
const team = args.linearTeam || cfg.linear.team;
|
|
260558
|
-
const assignee = args.linearAssignee || cfg.linear.
|
|
261290
|
+
const effectiveFilter = args.linearFilter || (args.linearAssignee ? `assignee = ${args.linearAssignee}` : "") || cfg.linear.filter;
|
|
261291
|
+
const { assignee, anyAssignee } = parseLinearFilter(effectiveFilter);
|
|
261292
|
+
const ticketNumbers = resolveTicketNumbers(args.ticketTokens, team);
|
|
260559
261293
|
const excludeFromTodo = unionMarkers(indicators.setDone, indicators.setError);
|
|
260560
261294
|
const gitRunner = input.runners?.git ?? bunGitRunner;
|
|
260561
261295
|
const cmdRunner = input.runners?.cmd ?? bunCmdRunner;
|
|
@@ -260587,7 +261321,20 @@ function buildAgentCoordinator(input) {
|
|
|
260587
261321
|
}
|
|
260588
261322
|
return code;
|
|
260589
261323
|
});
|
|
260590
|
-
const resolvers = createLinearResolvers({
|
|
261324
|
+
const resolvers = createLinearResolvers({
|
|
261325
|
+
apiKey,
|
|
261326
|
+
team,
|
|
261327
|
+
assignee,
|
|
261328
|
+
anyAssignee,
|
|
261329
|
+
diag,
|
|
261330
|
+
...ticketNumbers.length > 0 ? { ticketNumbers } : {}
|
|
261331
|
+
});
|
|
261332
|
+
if (ticketNumbers.length > 0) {
|
|
261333
|
+
const hasGetIndicator = [indicators.getTodo, indicators.getInProgress].some((ind) => ind && ind.filter.length > 0);
|
|
261334
|
+
if (!hasGetIndicator) {
|
|
261335
|
+
diag("ticket", `! --ticket set (${ticketNumbers.join(", ")}) but no getTodo/getInProgress indicator is configured \u2014 nothing will be picked up`, "yellow");
|
|
261336
|
+
}
|
|
261337
|
+
}
|
|
260591
261338
|
const prDiscovery = createPrDiscovery({
|
|
260592
261339
|
apiKey,
|
|
260593
261340
|
projectRoot,
|
|
@@ -260616,6 +261363,7 @@ function buildAgentCoordinator(input) {
|
|
|
260616
261363
|
cfg,
|
|
260617
261364
|
team,
|
|
260618
261365
|
assignee,
|
|
261366
|
+
anyAssignee,
|
|
260619
261367
|
indicators,
|
|
260620
261368
|
projectRoot,
|
|
260621
261369
|
useWorktree,
|
|
@@ -260623,6 +261371,7 @@ function buildAgentCoordinator(input) {
|
|
|
260623
261371
|
onLog,
|
|
260624
261372
|
diag,
|
|
260625
261373
|
cwdByChange,
|
|
261374
|
+
...ticketNumbers.length > 0 ? { ticketNumbers } : {},
|
|
260626
261375
|
stalePingedAt,
|
|
260627
261376
|
lastHandledReviewActivity,
|
|
260628
261377
|
resolvePrUrlForIssue: prDiscovery.resolvePrUrlForIssue
|
|
@@ -260719,7 +261468,7 @@ function buildAgentCoordinator(input) {
|
|
|
260719
261468
|
fetchTodo: () => resolvers.fetchByGet(indicators.getTodo, excludeFromTodo),
|
|
260720
261469
|
fetchInProgress: () => resolvers.fetchByGet(indicators.getInProgress, unionMarkers(indicators.setError)),
|
|
260721
261470
|
fetchMentions,
|
|
260722
|
-
fetchDoneCandidates: () => fetchDoneCandidatesWith(apiKey, team, assignee, indicators),
|
|
261471
|
+
fetchDoneCandidates: () => fetchDoneCandidatesWith(apiKey, team, assignee, indicators, ticketNumbers.length > 0 ? ticketNumbers : undefined),
|
|
260723
261472
|
prepare: prep.prepare,
|
|
260724
261473
|
prepareTaskForTrigger: prep.prepareTaskForTrigger,
|
|
260725
261474
|
spawnWorker,
|
|
@@ -260758,7 +261507,7 @@ function buildAgentCoordinator(input) {
|
|
|
260758
261507
|
...prTracker ? { prTracker } : {}
|
|
260759
261508
|
});
|
|
260760
261509
|
coordRef.current = coord;
|
|
260761
|
-
const filterDesc = describeIndicators(indicators, team, assignee);
|
|
261510
|
+
const filterDesc = describeIndicators(indicators, team, assignee, anyAssignee);
|
|
260762
261511
|
const runBaselineGateOnce = createBaselineGateRunner({
|
|
260763
261512
|
args,
|
|
260764
261513
|
cfg,
|
|
@@ -260794,6 +261543,7 @@ function buildAgentCoordinator(input) {
|
|
|
260794
261543
|
};
|
|
260795
261544
|
}
|
|
260796
261545
|
var init_wire = __esm(() => {
|
|
261546
|
+
init_workflow();
|
|
260797
261547
|
init_src2();
|
|
260798
261548
|
init_coordinator2();
|
|
260799
261549
|
init_linear();
|
|
@@ -260805,6 +261555,7 @@ var init_wire = __esm(() => {
|
|
|
260805
261555
|
init_indicators();
|
|
260806
261556
|
init_task_bodies();
|
|
260807
261557
|
init_linear_resolvers();
|
|
261558
|
+
init_linear_client();
|
|
260808
261559
|
init_prepare();
|
|
260809
261560
|
init_pr_discovery();
|
|
260810
261561
|
init_mention_scan();
|
|
@@ -260820,7 +261571,7 @@ import { dirname as dirname15 } from "path";
|
|
|
260820
261571
|
function createJsonLogFileSink(path) {
|
|
260821
261572
|
if (!path)
|
|
260822
261573
|
return { emit: () => {} };
|
|
260823
|
-
let
|
|
261574
|
+
let chain = (async () => {
|
|
260824
261575
|
try {
|
|
260825
261576
|
await mkdir12(dirname15(path), { recursive: true });
|
|
260826
261577
|
await Bun.write(path, "");
|
|
@@ -260830,7 +261581,7 @@ function createJsonLogFileSink(path) {
|
|
|
260830
261581
|
emit(event) {
|
|
260831
261582
|
const line = JSON.stringify({ ts: Date.now(), v: VERSION, ...event }) + `
|
|
260832
261583
|
`;
|
|
260833
|
-
|
|
261584
|
+
chain = chain.then(async () => {
|
|
260834
261585
|
try {
|
|
260835
261586
|
await appendFile2(path, line);
|
|
260836
261587
|
} catch {}
|
|
@@ -262114,6 +262865,19 @@ function AgentMode({
|
|
|
262114
262865
|
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
262115
262866
|
color: pollStatus.lastPrStatus.ciFailed > 0 ? "red" : "white",
|
|
262116
262867
|
children: pollStatus.lastPrStatus.ciFailed
|
|
262868
|
+
}, undefined, false, undefined, this),
|
|
262869
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
262870
|
+
dimColor: true,
|
|
262871
|
+
children: "\xB7"
|
|
262872
|
+
}, undefined, false, undefined, this),
|
|
262873
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
262874
|
+
dimColor: true,
|
|
262875
|
+
children: "quarantined"
|
|
262876
|
+
}, undefined, false, undefined, this),
|
|
262877
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
262878
|
+
color: pollStatus.lastPrStatus.quarantined > 0 ? "magenta" : "white",
|
|
262879
|
+
bold: true,
|
|
262880
|
+
children: pollStatus.lastPrStatus.quarantined
|
|
262117
262881
|
}, undefined, false, undefined, this)
|
|
262118
262882
|
]
|
|
262119
262883
|
}, undefined, true, undefined, this)
|
|
@@ -262938,6 +263702,18 @@ var init_tmux = __esm(() => {
|
|
|
262938
263702
|
decoder = new TextDecoder;
|
|
262939
263703
|
});
|
|
262940
263704
|
|
|
263705
|
+
// apps/agent/src/sort/compare.ts
|
|
263706
|
+
function chain(...comparators) {
|
|
263707
|
+
return (a, b2) => {
|
|
263708
|
+
for (const c of comparators) {
|
|
263709
|
+
const r = c(a, b2);
|
|
263710
|
+
if (r !== 0)
|
|
263711
|
+
return r;
|
|
263712
|
+
}
|
|
263713
|
+
return 0;
|
|
263714
|
+
};
|
|
263715
|
+
}
|
|
263716
|
+
|
|
262941
263717
|
// apps/agent/src/list-sort.ts
|
|
262942
263718
|
function assignTier(status) {
|
|
262943
263719
|
if (status === null || status.kind === "error")
|
|
@@ -262960,7 +263736,7 @@ function createdAtOf(status) {
|
|
|
262960
263736
|
return "";
|
|
262961
263737
|
}
|
|
262962
263738
|
function sortRows(rows) {
|
|
262963
|
-
const cmp = chain((a, b2) => assignTier(a.status) - assignTier(b2.status), (a, b2) => {
|
|
263739
|
+
const cmp = chain((a, b2) => assignTier(a.status) - assignTier(b2.status), (a, b2) => a.bucketOrder - b2.bucketOrder, (a, b2) => {
|
|
262964
263740
|
const ia = a.issueCreatedAt;
|
|
262965
263741
|
const ib = b2.issueCreatedAt;
|
|
262966
263742
|
if (ia === ib)
|
|
@@ -262976,7 +263752,7 @@ function sortRows(rows) {
|
|
|
262976
263752
|
if (ca === cb)
|
|
262977
263753
|
return 0;
|
|
262978
263754
|
return ca < cb ? -1 : 1;
|
|
262979
|
-
}, (a, b2) => a.
|
|
263755
|
+
}, (a, b2) => a.identifier.localeCompare(b2.identifier));
|
|
262980
263756
|
return [...rows].sort(cmp);
|
|
262981
263757
|
}
|
|
262982
263758
|
var init_list_sort = () => {};
|
|
@@ -263025,7 +263801,8 @@ __export(exports_list, {
|
|
|
263025
263801
|
formatReviewCell: () => formatReviewCell,
|
|
263026
263802
|
formatPrStatusMarker: () => formatPrStatusMarker,
|
|
263027
263803
|
formatBlockedCell: () => formatBlockedCell,
|
|
263028
|
-
buildBuckets: () => buildBuckets
|
|
263804
|
+
buildBuckets: () => buildBuckets,
|
|
263805
|
+
backlogRankByIssueId: () => backlogRankByIssueId
|
|
263029
263806
|
});
|
|
263030
263807
|
import { join as join36 } from "path";
|
|
263031
263808
|
function countTaskItems(content) {
|
|
@@ -263127,17 +263904,23 @@ function buildBuckets(indicators) {
|
|
|
263127
263904
|
{ label: "auto-merge", indicator: indicators.getAutoMerge, exclude: [] }
|
|
263128
263905
|
];
|
|
263129
263906
|
}
|
|
263130
|
-
async function fetchBucketIssues(apiKey, bucket, team, assignee) {
|
|
263907
|
+
async function fetchBucketIssues(apiKey, bucket, team, assignee, anyAssignee, ticketNumbers) {
|
|
263131
263908
|
if (!bucket.indicator || bucket.indicator.filter.length === 0)
|
|
263132
263909
|
return [];
|
|
263133
263910
|
const spec = {
|
|
263134
263911
|
team,
|
|
263135
263912
|
assignee,
|
|
263913
|
+
anyAssignee,
|
|
263136
263914
|
include: bucket.indicator.filter,
|
|
263137
|
-
exclude: bucket.exclude
|
|
263915
|
+
exclude: bucket.exclude,
|
|
263916
|
+
...ticketNumbers.length > 0 ? { numbers: ticketNumbers } : {}
|
|
263138
263917
|
};
|
|
263139
263918
|
return fetchOpenIssues(apiKey, spec);
|
|
263140
263919
|
}
|
|
263920
|
+
function resolveLinearFilter(filterOverride, assigneeOverride, configFilter) {
|
|
263921
|
+
const effective = filterOverride || (assigneeOverride ? `assignee = ${assigneeOverride}` : "") || configFilter;
|
|
263922
|
+
return parseLinearFilter(effective);
|
|
263923
|
+
}
|
|
263141
263924
|
function formatReviewCell(prUrl, count) {
|
|
263142
263925
|
if (!prUrl)
|
|
263143
263926
|
return "-";
|
|
@@ -263178,13 +263961,19 @@ function formatPrStatusMarker(status, failedCheckNames) {
|
|
|
263178
263961
|
return "ok";
|
|
263179
263962
|
return parts.join(" ");
|
|
263180
263963
|
}
|
|
263181
|
-
|
|
263964
|
+
function backlogRankByIssueId(issues) {
|
|
263965
|
+
const ordered = orderIssuesHierarchically(issues.map((issue2) => linearIssueToOrderable(issue2)));
|
|
263966
|
+
const rankById = new Map;
|
|
263967
|
+
ordered.forEach((o, i) => rankById.set(o.id, i));
|
|
263968
|
+
return rankById;
|
|
263969
|
+
}
|
|
263970
|
+
async function fetchAndPrintLinear(apiKey, buckets, team, assignee, anyAssignee, cwd2, runner, ignoreCiChecks = [], checks3 = false, review = false, ticketNumbers = []) {
|
|
263182
263971
|
const bucketResults = await Promise.all(buckets.map(async (bucket) => {
|
|
263183
263972
|
if (!bucket.indicator || bucket.indicator.filter.length === 0) {
|
|
263184
263973
|
return { bucket, issues: [], error: null };
|
|
263185
263974
|
}
|
|
263186
263975
|
try {
|
|
263187
|
-
const issues = await fetchBucketIssues(apiKey, bucket, team, assignee);
|
|
263976
|
+
const issues = await fetchBucketIssues(apiKey, bucket, team, assignee, anyAssignee, ticketNumbers);
|
|
263188
263977
|
return { bucket, issues, error: null };
|
|
263189
263978
|
} catch (err) {
|
|
263190
263979
|
return {
|
|
@@ -263202,16 +263991,17 @@ ${bucket.label}: error fetching from Linear \u2014 ${error48}
|
|
|
263202
263991
|
}
|
|
263203
263992
|
}
|
|
263204
263993
|
const seen = new Map;
|
|
263205
|
-
|
|
263994
|
+
const issueById = new Map;
|
|
263206
263995
|
for (const { bucket, issues } of bucketResults) {
|
|
263207
263996
|
for (const issue2 of issues) {
|
|
263208
263997
|
if (seen.has(issue2.id))
|
|
263209
263998
|
continue;
|
|
263999
|
+
issueById.set(issue2.id, issue2);
|
|
263210
264000
|
seen.set(issue2.id, {
|
|
263211
264001
|
issueId: issue2.id,
|
|
263212
264002
|
identifier: issue2.identifier,
|
|
263213
264003
|
status: null,
|
|
263214
|
-
bucketOrder:
|
|
264004
|
+
bucketOrder: 0,
|
|
263215
264005
|
issueCreatedAt: issue2.createdAt,
|
|
263216
264006
|
bucketLabel: bucket.label,
|
|
263217
264007
|
stateName: issue2.state.name,
|
|
@@ -263222,6 +264012,9 @@ ${bucket.label}: error fetching from Linear \u2014 ${error48}
|
|
|
263222
264012
|
}
|
|
263223
264013
|
}
|
|
263224
264014
|
const rows = [...seen.values()];
|
|
264015
|
+
const rankById = backlogRankByIssueId([...issueById.values()]);
|
|
264016
|
+
for (const row of rows)
|
|
264017
|
+
row.bucketOrder = rankById.get(row.issueId) ?? 0;
|
|
263225
264018
|
try {
|
|
263226
264019
|
const attachmentsByIssue = await fetchAttachmentsForIssues(apiKey, rows.map((r) => r.issueId));
|
|
263227
264020
|
for (const row of rows) {
|
|
@@ -263306,6 +264099,7 @@ async function runList(input) {
|
|
|
263306
264099
|
identifier: name,
|
|
263307
264100
|
projectRoot,
|
|
263308
264101
|
linearTeamOverride: input.linearTeamOverride,
|
|
264102
|
+
linearFilterOverride: input.linearFilterOverride,
|
|
263309
264103
|
linearAssigneeOverride: input.linearAssigneeOverride
|
|
263310
264104
|
});
|
|
263311
264105
|
return;
|
|
@@ -263316,7 +264110,7 @@ async function runList(input) {
|
|
|
263316
264110
|
const apiKey = process.env["LINEAR_API_KEY"];
|
|
263317
264111
|
const indicators = cfg.linear.indicators;
|
|
263318
264112
|
const team = input.linearTeamOverride || cfg.linear.team;
|
|
263319
|
-
const assignee = input.linearAssigneeOverride
|
|
264113
|
+
const { assignee, anyAssignee } = resolveLinearFilter(input.linearFilterOverride, input.linearAssigneeOverride, cfg.linear.filter);
|
|
263320
264114
|
const buckets = buildBuckets(indicators);
|
|
263321
264115
|
const anyConfigured = buckets.some((b2) => b2.indicator && b2.indicator.filter.length > 0);
|
|
263322
264116
|
if (!anyConfigured) {
|
|
@@ -263338,20 +264132,36 @@ Linear: LINEAR_API_KEY not set \u2014 cannot fetch tickets. Configured buckets:
|
|
|
263338
264132
|
}
|
|
263339
264133
|
return;
|
|
263340
264134
|
}
|
|
264135
|
+
let ticketNumbers = [];
|
|
264136
|
+
try {
|
|
264137
|
+
ticketNumbers = resolveTicketNumbers(input.ticketTokens ?? [], team);
|
|
264138
|
+
} catch (err) {
|
|
264139
|
+
process.stderr.write(`Error: ${formatTicketError(err)}
|
|
264140
|
+
`);
|
|
264141
|
+
process.exitCode = 1;
|
|
264142
|
+
return;
|
|
264143
|
+
}
|
|
263341
264144
|
if (team)
|
|
263342
264145
|
process.stdout.write(`
|
|
263343
264146
|
team: ${team}
|
|
263344
264147
|
`);
|
|
263345
|
-
|
|
263346
|
-
|
|
264148
|
+
process.stdout.write(`assignee: ${anyAssignee ? "any" : assignee ?? "*"}
|
|
264149
|
+
`);
|
|
264150
|
+
if (ticketNumbers.length > 0)
|
|
264151
|
+
process.stdout.write(`ticket: ${ticketNumbers.join(", ")}
|
|
263347
264152
|
`);
|
|
263348
|
-
await fetchAndPrintLinear(apiKey, buckets, team, assignee, projectRoot, localCmdRunner, cfg.ignoreCiChecks, input.checks, input.review);
|
|
264153
|
+
await fetchAndPrintLinear(apiKey, buckets, team, assignee, anyAssignee, projectRoot, localCmdRunner, cfg.ignoreCiChecks, input.checks, input.review, ticketNumbers);
|
|
263349
264154
|
}
|
|
263350
264155
|
function normalizeIdentifier(input) {
|
|
263351
|
-
|
|
263352
|
-
|
|
264156
|
+
let parsed;
|
|
264157
|
+
try {
|
|
264158
|
+
parsed = parseTicketIdentifier(input);
|
|
264159
|
+
} catch {
|
|
263353
264160
|
return null;
|
|
263354
|
-
|
|
264161
|
+
}
|
|
264162
|
+
if (parsed.teamKey === null)
|
|
264163
|
+
return null;
|
|
264164
|
+
return `${parsed.teamKey}-${parsed.number}`;
|
|
263355
264165
|
}
|
|
263356
264166
|
async function fetchIssueByIdentifier(apiKey, identifier) {
|
|
263357
264167
|
const match = identifier.match(/^([A-Z]+)-(\d+)$/);
|
|
@@ -263397,8 +264207,10 @@ function markerMatches(issue2, marker) {
|
|
|
263397
264207
|
}
|
|
263398
264208
|
return false;
|
|
263399
264209
|
}
|
|
263400
|
-
function assigneeMatches(issue2, assignee) {
|
|
263401
|
-
if (
|
|
264210
|
+
function assigneeMatches(issue2, assignee, anyAssignee) {
|
|
264211
|
+
if (anyAssignee)
|
|
264212
|
+
return true;
|
|
264213
|
+
if (!assignee || assignee === "unassigned")
|
|
263402
264214
|
return issue2.assignee === null;
|
|
263403
264215
|
const a = issue2.assignee;
|
|
263404
264216
|
if (!a)
|
|
@@ -263421,7 +264233,8 @@ async function runListDebug(input) {
|
|
|
263421
264233
|
const cfg = await loadRalphyConfig(projectRoot);
|
|
263422
264234
|
const indicators = cfg.linear.indicators;
|
|
263423
264235
|
const team = input.linearTeamOverride || cfg.linear.team;
|
|
263424
|
-
const assignee = input.linearAssigneeOverride
|
|
264236
|
+
const { assignee, anyAssignee } = resolveLinearFilter(input.linearFilterOverride, input.linearAssigneeOverride, cfg.linear.filter);
|
|
264237
|
+
const assigneeLabel = anyAssignee ? "any" : assignee ?? "*";
|
|
263425
264238
|
const normalized = normalizeIdentifier(identifier);
|
|
263426
264239
|
if (!normalized) {
|
|
263427
264240
|
process.stdout.write(`Error: '${identifier}' does not look like a Linear identifier (expected e.g. DOO-6, or a local change name beginning with one).
|
|
@@ -263461,8 +264274,8 @@ Per-bucket diagnostics:
|
|
|
263461
264274
|
if (team && issue2.team?.key && issue2.team.key !== team) {
|
|
263462
264275
|
reasons.push(`team mismatch: issue=${issue2.team.key}, config=${team}`);
|
|
263463
264276
|
}
|
|
263464
|
-
if (!assigneeMatches(issue2, assignee)) {
|
|
263465
|
-
reasons.push(`assignee mismatch: issue=${issue2.assignee ? issue2.assignee.email ?? issue2.assignee.id : "unassigned"}, config=${
|
|
264277
|
+
if (!assigneeMatches(issue2, assignee, anyAssignee)) {
|
|
264278
|
+
reasons.push(`assignee mismatch: issue=${issue2.assignee ? issue2.assignee.email ?? issue2.assignee.id : "unassigned"}, config=${assigneeLabel}`);
|
|
263466
264279
|
}
|
|
263467
264280
|
const includeMatches = bucket.indicator.filter.some((m2) => markerMatches(issue2, m2));
|
|
263468
264281
|
if (!includeMatches) {
|
|
@@ -263495,12 +264308,15 @@ Per-bucket diagnostics:
|
|
|
263495
264308
|
var localCmdRunner;
|
|
263496
264309
|
var init_list = __esm(() => {
|
|
263497
264310
|
init_context();
|
|
264311
|
+
init_workflow();
|
|
263498
264312
|
init_worktree();
|
|
263499
264313
|
init_config();
|
|
263500
264314
|
init_linear();
|
|
263501
264315
|
init_pr_status();
|
|
263502
264316
|
init_pr_url();
|
|
263503
264317
|
init_list_sort();
|
|
264318
|
+
init_ordering();
|
|
264319
|
+
init_queue_order();
|
|
263504
264320
|
init_ci();
|
|
263505
264321
|
init_linear_client();
|
|
263506
264322
|
init_indicators();
|
|
@@ -263806,11 +264622,13 @@ async function main3(argv) {
|
|
|
263806
264622
|
await runWithContext(createDefaultContext({ layout, args }), async () => {
|
|
263807
264623
|
await runList2({
|
|
263808
264624
|
linearTeamOverride: args.linearTeam,
|
|
264625
|
+
linearFilterOverride: args.linearFilter,
|
|
263809
264626
|
linearAssigneeOverride: args.linearAssignee,
|
|
263810
264627
|
debug: args.debug,
|
|
263811
264628
|
name: args.name,
|
|
263812
264629
|
checks: args.checks,
|
|
263813
|
-
review: args.review
|
|
264630
|
+
review: args.review,
|
|
264631
|
+
ticketTokens: args.ticketTokens
|
|
263814
264632
|
});
|
|
263815
264633
|
});
|
|
263816
264634
|
return typeof process.exitCode === "number" ? process.exitCode : 0;
|
|
@@ -263830,6 +264648,19 @@ async function main3(argv) {
|
|
|
263830
264648
|
`);
|
|
263831
264649
|
return 0;
|
|
263832
264650
|
}
|
|
264651
|
+
if (args.ticketTokens.length > 0) {
|
|
264652
|
+
const { loadRalphyConfig: loadRalphyConfig2 } = await Promise.resolve().then(() => (init_config(), exports_config));
|
|
264653
|
+
const { resolveTicketNumbers: resolveTicketNumbers2, formatTicketError: formatTicketError2 } = await Promise.resolve().then(() => (init_linear_client(), exports_linear_client));
|
|
264654
|
+
const cfg = await loadRalphyConfig2(projectRoot);
|
|
264655
|
+
const team = args.linearTeam || cfg.linear.team;
|
|
264656
|
+
try {
|
|
264657
|
+
resolveTicketNumbers2(args.ticketTokens, team);
|
|
264658
|
+
} catch (err) {
|
|
264659
|
+
process.stderr.write(formatTicketError2(err) + `
|
|
264660
|
+
`);
|
|
264661
|
+
return 1;
|
|
264662
|
+
}
|
|
264663
|
+
}
|
|
263833
264664
|
await mkdir15(statesDir, { recursive: true });
|
|
263834
264665
|
await mkdir15(tasksDir, { recursive: true });
|
|
263835
264666
|
await mkdir15(join39(projectRoot, ".ralph"), { recursive: true });
|