@neriros/ralphy 3.10.2 → 3.10.4
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 +803 -88
- package/package.json +3 -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.4")
|
|
18932
|
+
return "3.10.4";
|
|
18933
18933
|
} catch {}
|
|
18934
18934
|
const dirsToTry = [];
|
|
18935
18935
|
try {
|
|
@@ -80505,7 +80505,7 @@ var init_zod = __esm(() => {
|
|
|
80505
80505
|
});
|
|
80506
80506
|
|
|
80507
80507
|
// packages/workflow/src/schema.ts
|
|
80508
|
-
var CURRENT_WORKFLOW_VERSION =
|
|
80508
|
+
var CURRENT_WORKFLOW_VERSION = 2, MarkerSchema, SET_INDICATOR_KEYS, GetIndicatorSchema, SetIndicatorSchema, IndicatorsSchema, ProjectSchema, CommandsSchema, DEFAULT_META_ONLY_FILES, BoundariesSchema, WorkflowConfigSchema;
|
|
80509
80509
|
var init_schema = __esm(() => {
|
|
80510
80510
|
init_zod();
|
|
80511
80511
|
MarkerSchema = exports_external.discriminatedUnion("type", [
|
|
@@ -80598,6 +80598,12 @@ var init_schema = __esm(() => {
|
|
|
80598
80598
|
WorkflowConfigSchema = exports_external.object({
|
|
80599
80599
|
version: exports_external.number().int().nonnegative().default(0),
|
|
80600
80600
|
project: ProjectSchema,
|
|
80601
|
+
repo: exports_external.object({
|
|
80602
|
+
remote: exports_external.string().optional(),
|
|
80603
|
+
host: exports_external.string().optional(),
|
|
80604
|
+
owner: exports_external.string().optional(),
|
|
80605
|
+
name: exports_external.string().optional()
|
|
80606
|
+
}).strict().optional(),
|
|
80601
80607
|
commands: CommandsSchema,
|
|
80602
80608
|
rules: exports_external.array(exports_external.string()).default([]),
|
|
80603
80609
|
boundaries: BoundariesSchema,
|
|
@@ -80712,8 +80718,9 @@ var init_schema = __esm(() => {
|
|
|
80712
80718
|
advanceMergedToDone: false
|
|
80713
80719
|
}),
|
|
80714
80720
|
metaPrompt: exports_external.object({
|
|
80715
|
-
enabled: exports_external.boolean().default(true)
|
|
80716
|
-
|
|
80721
|
+
enabled: exports_external.boolean().default(true),
|
|
80722
|
+
effort: exports_external.enum(["auto", "light", "standard", "heavy"]).default("auto")
|
|
80723
|
+
}).strict().default({ enabled: true, effort: "auto" }),
|
|
80717
80724
|
openspec: exports_external.object({
|
|
80718
80725
|
reviewPhase: exports_external.object({
|
|
80719
80726
|
enabled: exports_external.boolean().default(false),
|
|
@@ -81049,7 +81056,7 @@ function modelOptionValues() {
|
|
|
81049
81056
|
const field = findField("model");
|
|
81050
81057
|
return field && field.spec.kind === "select" ? field.spec.options.map((o) => o.value) : [];
|
|
81051
81058
|
}
|
|
81052
|
-
var PROMPT_BODY_FIELD_ID = "promptBody", yes = () => ({ kind: "confirm", defaultChoice: "confirm" }), no = () => ({ kind: "confirm", defaultChoice: "cancel" }), PROJECT_NAME, LINEAR_TEAM, LINEAR_ASSIGNEE, QUICK_FIELDS, isOn = (id) => (answers) => answers[id] === true, CUSTOMIZED_FIELDS, COMMON_CLI_OPTIONS, FIELD_DESCRIPTIONS;
|
|
81059
|
+
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_ASSIGNEE, QUICK_FIELDS, isOn = (id) => (answers) => answers[id] === true, CUSTOMIZED_FIELDS, COMMON_CLI_OPTIONS, FIELD_DESCRIPTIONS;
|
|
81053
81060
|
var init_fields = __esm(() => {
|
|
81054
81061
|
PROJECT_NAME = {
|
|
81055
81062
|
id: "project.name",
|
|
@@ -81061,10 +81068,17 @@ var init_fields = __esm(() => {
|
|
|
81061
81068
|
id: "linear.team",
|
|
81062
81069
|
label: "Linear team key",
|
|
81063
81070
|
hint: "e.g. ENG \u2014 leave blank to match all teams",
|
|
81064
|
-
description: "
|
|
81071
|
+
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
81072
|
emptyLabel: "all teams",
|
|
81066
81073
|
spec: { kind: "text" }
|
|
81067
81074
|
};
|
|
81075
|
+
REPO_LINK = {
|
|
81076
|
+
id: "repo.link",
|
|
81077
|
+
label: "Link this repository to the team?",
|
|
81078
|
+
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.",
|
|
81079
|
+
spec: yes(),
|
|
81080
|
+
when: (answers) => typeof answers["repo.name"] === "string" && answers["repo.name"] !== ""
|
|
81081
|
+
};
|
|
81068
81082
|
LINEAR_ASSIGNEE = {
|
|
81069
81083
|
id: "linear.assignee",
|
|
81070
81084
|
label: "Linear assignee",
|
|
@@ -81073,7 +81087,7 @@ var init_fields = __esm(() => {
|
|
|
81073
81087
|
emptyLabel: "unassigned",
|
|
81074
81088
|
spec: { kind: "text" }
|
|
81075
81089
|
};
|
|
81076
|
-
QUICK_FIELDS = [PROJECT_NAME, LINEAR_TEAM, LINEAR_ASSIGNEE];
|
|
81090
|
+
QUICK_FIELDS = [PROJECT_NAME, LINEAR_TEAM, REPO_LINK, LINEAR_ASSIGNEE];
|
|
81077
81091
|
CUSTOMIZED_FIELDS = [
|
|
81078
81092
|
PROJECT_NAME,
|
|
81079
81093
|
{
|
|
@@ -81321,6 +81335,7 @@ var init_fields = __esm(() => {
|
|
|
81321
81335
|
spec: { kind: "list", placeholder: "dist/**" }
|
|
81322
81336
|
},
|
|
81323
81337
|
LINEAR_TEAM,
|
|
81338
|
+
REPO_LINK,
|
|
81324
81339
|
LINEAR_ASSIGNEE,
|
|
81325
81340
|
{
|
|
81326
81341
|
id: "linear.postComments",
|
|
@@ -81464,6 +81479,21 @@ var init_fields = __esm(() => {
|
|
|
81464
81479
|
description: "Add Ralphy's task-level 'meta-prompt' layer (extra framing instructions) to each phase. Leave on unless you want raw prompts.",
|
|
81465
81480
|
spec: yes()
|
|
81466
81481
|
},
|
|
81482
|
+
{
|
|
81483
|
+
id: "metaPrompt.effort",
|
|
81484
|
+
label: "Per-ticket effort tier",
|
|
81485
|
+
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.",
|
|
81486
|
+
spec: {
|
|
81487
|
+
kind: "select",
|
|
81488
|
+
options: [
|
|
81489
|
+
{ label: "auto", value: "auto" },
|
|
81490
|
+
{ label: "light", value: "light" },
|
|
81491
|
+
{ label: "standard", value: "standard" },
|
|
81492
|
+
{ label: "heavy", value: "heavy" }
|
|
81493
|
+
]
|
|
81494
|
+
},
|
|
81495
|
+
when: isOn("metaPrompt.enabled")
|
|
81496
|
+
},
|
|
81467
81497
|
{
|
|
81468
81498
|
id: "openspec.reviewPhase.enabled",
|
|
81469
81499
|
label: "Enable the OpenSpec review phase?",
|
|
@@ -81869,6 +81899,51 @@ var init_workflow = __esm(() => {
|
|
|
81869
81899
|
import_yaml2 = __toESM(require_dist(), 1);
|
|
81870
81900
|
});
|
|
81871
81901
|
|
|
81902
|
+
// packages/core/src/repo/index.ts
|
|
81903
|
+
function parseRepoIdentity(remoteUrl) {
|
|
81904
|
+
const remote = remoteUrl.trim();
|
|
81905
|
+
if (!remote)
|
|
81906
|
+
return null;
|
|
81907
|
+
const match = remote.includes("://") ? URL_RE.exec(remote) : SCP_RE.exec(remote);
|
|
81908
|
+
if (!match)
|
|
81909
|
+
return null;
|
|
81910
|
+
const host = match[1];
|
|
81911
|
+
let path = match[2];
|
|
81912
|
+
if (!host || !path)
|
|
81913
|
+
return null;
|
|
81914
|
+
path = path.replace(/\/+$/, "").replace(/\.git$/i, "").replace(/\/+$/, "");
|
|
81915
|
+
const segments = path.split("/").filter((segment) => segment.length > 0);
|
|
81916
|
+
if (segments.length < 2)
|
|
81917
|
+
return null;
|
|
81918
|
+
const name = segments[segments.length - 1];
|
|
81919
|
+
const owner = segments.slice(0, -1).join("/");
|
|
81920
|
+
if (!owner || !name)
|
|
81921
|
+
return null;
|
|
81922
|
+
return { remote, host, owner, name };
|
|
81923
|
+
}
|
|
81924
|
+
async function detectRepoIdentity(cwd2) {
|
|
81925
|
+
try {
|
|
81926
|
+
const proc = Bun.spawn({
|
|
81927
|
+
cmd: ["git", "remote", "get-url", "origin"],
|
|
81928
|
+
...cwd2 ? { cwd: cwd2 } : {},
|
|
81929
|
+
stdout: "pipe",
|
|
81930
|
+
stderr: "ignore",
|
|
81931
|
+
timeout: GIT_DETECT_TIMEOUT_MS
|
|
81932
|
+
});
|
|
81933
|
+
const [stdout, exitCode] = await Promise.all([new Response(proc.stdout).text(), proc.exited]);
|
|
81934
|
+
if (exitCode !== 0)
|
|
81935
|
+
return null;
|
|
81936
|
+
return parseRepoIdentity(stdout.trim());
|
|
81937
|
+
} catch {
|
|
81938
|
+
return null;
|
|
81939
|
+
}
|
|
81940
|
+
}
|
|
81941
|
+
var GIT_DETECT_TIMEOUT_MS = 5000, SCP_RE, URL_RE;
|
|
81942
|
+
var init_repo = __esm(() => {
|
|
81943
|
+
SCP_RE = /^(?:[^@/]+@)?([^/:]+):(.+)$/;
|
|
81944
|
+
URL_RE = /^[a-zA-Z][a-zA-Z0-9+.-]*:\/\/(?:[^@/]+@)?([^/:]+)(?::\d+)?\/(.+)$/;
|
|
81945
|
+
});
|
|
81946
|
+
|
|
81872
81947
|
// node_modules/.bun/react@18.3.1/node_modules/react/cjs/react-jsx-dev-runtime.development.js
|
|
81873
81948
|
var require_react_jsx_dev_runtime_development = __commonJS((exports) => {
|
|
81874
81949
|
var React10 = __toESM(require_react());
|
|
@@ -82787,6 +82862,12 @@ function buildFromAnswers(mode, answers, build = buildWorkflowMarkdown) {
|
|
|
82787
82862
|
values2["linear.indicators"] = map3;
|
|
82788
82863
|
}
|
|
82789
82864
|
}
|
|
82865
|
+
const linkRepo = values2[REPO_LINK_FIELD_ID] === true;
|
|
82866
|
+
delete values2[REPO_LINK_FIELD_ID];
|
|
82867
|
+
if (!linkRepo) {
|
|
82868
|
+
for (const id of REPO_ANSWER_IDS)
|
|
82869
|
+
delete values2[id];
|
|
82870
|
+
}
|
|
82790
82871
|
let bodyOverride;
|
|
82791
82872
|
if (PROMPT_BODY_FIELD_ID in values2) {
|
|
82792
82873
|
const body = values2[PROMPT_BODY_FIELD_ID];
|
|
@@ -82868,7 +82949,8 @@ function SetupWizard({
|
|
|
82868
82949
|
initialValues,
|
|
82869
82950
|
buildMarkdown,
|
|
82870
82951
|
onlyFields,
|
|
82871
|
-
initialBody
|
|
82952
|
+
initialBody,
|
|
82953
|
+
detectedRepo
|
|
82872
82954
|
}) {
|
|
82873
82955
|
const { exit } = use_app_default();
|
|
82874
82956
|
const startValues = initialValues ?? {};
|
|
@@ -82944,7 +83026,15 @@ function SetupWizard({
|
|
|
82944
83026
|
setIndex(target);
|
|
82945
83027
|
initEditing(fieldsFor(mode, source)[target], source);
|
|
82946
83028
|
};
|
|
82947
|
-
const valuesToWrite = (source) =>
|
|
83029
|
+
const valuesToWrite = (source) => {
|
|
83030
|
+
if (!onlyFields)
|
|
83031
|
+
return source;
|
|
83032
|
+
const allowed = new Set(onlyFields);
|
|
83033
|
+
if (allowed.has(REPO_LINK_FIELD_ID))
|
|
83034
|
+
for (const id of REPO_ANSWER_IDS)
|
|
83035
|
+
allowed.add(id);
|
|
83036
|
+
return Object.fromEntries(Object.entries(source).filter(([id]) => allowed.has(id)));
|
|
83037
|
+
};
|
|
82948
83038
|
const advance = (source) => {
|
|
82949
83039
|
const nextFields = fieldsFor(mode, source);
|
|
82950
83040
|
if (index >= nextFields.length - 1) {
|
|
@@ -83152,6 +83242,22 @@ ${draft.slice(at2)}`, at2 + 1);
|
|
|
83152
83242
|
marginTop: 1,
|
|
83153
83243
|
flexDirection: "column",
|
|
83154
83244
|
children: [
|
|
83245
|
+
field.id === REPO_LINK_FIELD_ID && detectedRepo ? /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
83246
|
+
children: [
|
|
83247
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
83248
|
+
dimColor: true,
|
|
83249
|
+
children: "Detected repo: "
|
|
83250
|
+
}, undefined, false, undefined, this),
|
|
83251
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
83252
|
+
color: "cyan",
|
|
83253
|
+
children: [
|
|
83254
|
+
detectedRepo.owner,
|
|
83255
|
+
"/",
|
|
83256
|
+
detectedRepo.name
|
|
83257
|
+
]
|
|
83258
|
+
}, undefined, true, undefined, this)
|
|
83259
|
+
]
|
|
83260
|
+
}, undefined, true, undefined, this) : null,
|
|
83155
83261
|
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
83156
83262
|
children: [
|
|
83157
83263
|
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
@@ -83724,13 +83830,14 @@ function IndicatorBuilder({
|
|
|
83724
83830
|
]
|
|
83725
83831
|
}, undefined, true, undefined, this);
|
|
83726
83832
|
}
|
|
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;
|
|
83833
|
+
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
83834
|
var init_SetupWizard = __esm(async () => {
|
|
83729
83835
|
init_wizard();
|
|
83730
83836
|
init_fields();
|
|
83731
83837
|
await init_build2();
|
|
83732
83838
|
import_react22 = __toESM(require_react(), 1);
|
|
83733
83839
|
jsx_dev_runtime = __toESM(require_jsx_dev_runtime(), 1);
|
|
83840
|
+
REPO_ANSWER_IDS = ["repo.remote", "repo.host", "repo.owner", "repo.name"];
|
|
83734
83841
|
MODE_OPTIONS = [
|
|
83735
83842
|
{ label: "Quick \u2014 sensible defaults, only a few questions", value: "quick" },
|
|
83736
83843
|
{ label: "Permissive \u2014 defaults + auto-PR / auto-merge / CI auto-fix", value: "permissive" },
|
|
@@ -83856,6 +83963,11 @@ var init_migrations = __esm(() => {
|
|
|
83856
83963
|
"openspec.reviewPhase.reviewerModel",
|
|
83857
83964
|
"openspec.reviewPhase.reviewerContextStrategy"
|
|
83858
83965
|
]
|
|
83966
|
+
},
|
|
83967
|
+
{
|
|
83968
|
+
version: 2,
|
|
83969
|
+
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.",
|
|
83970
|
+
fields: ["repo.link"]
|
|
83859
83971
|
}
|
|
83860
83972
|
];
|
|
83861
83973
|
LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max2, migration) => Math.max(max2, migration.version), 0);
|
|
@@ -83868,6 +83980,18 @@ __export(exports_src, {
|
|
|
83868
83980
|
maybeRunSetupWizard: () => maybeRunSetupWizard,
|
|
83869
83981
|
main: () => main
|
|
83870
83982
|
});
|
|
83983
|
+
function withDetectedRepo(initial2, repo) {
|
|
83984
|
+
if (!repo)
|
|
83985
|
+
return initial2;
|
|
83986
|
+
const values2 = { ...initial2 };
|
|
83987
|
+
values2["repo.remote"] = repo.remote;
|
|
83988
|
+
values2["repo.host"] = repo.host;
|
|
83989
|
+
values2["repo.owner"] = repo.owner;
|
|
83990
|
+
values2["repo.name"] = repo.name;
|
|
83991
|
+
if (!values2["project.name"])
|
|
83992
|
+
values2["project.name"] = repo.name;
|
|
83993
|
+
return values2;
|
|
83994
|
+
}
|
|
83871
83995
|
function clearScreen2() {
|
|
83872
83996
|
if (process.stdout.isTTY)
|
|
83873
83997
|
process.stdout.write("\x1B[2J\x1B[3J\x1B[H");
|
|
@@ -83876,6 +84000,7 @@ async function runSetupWizard(projectRoot, options = {}) {
|
|
|
83876
84000
|
let markdown = null;
|
|
83877
84001
|
const buildMarkdown = options.existing ? (answers, bodyOverride) => applyAnswersToWorkflow(options.existing, answers, bodyOverride) : undefined;
|
|
83878
84002
|
const initialBody = workflowBody(options.existing ?? DEFAULT_WORKFLOW_MD);
|
|
84003
|
+
const initialValues = withDetectedRepo(options.initialValues, options.detectedRepo);
|
|
83879
84004
|
clearScreen2();
|
|
83880
84005
|
const { waitUntilExit } = render_default(import_react23.createElement(SetupWizard, {
|
|
83881
84006
|
onComplete: (md) => {
|
|
@@ -83886,8 +84011,9 @@ async function runSetupWizard(projectRoot, options = {}) {
|
|
|
83886
84011
|
},
|
|
83887
84012
|
initialBody,
|
|
83888
84013
|
...options.initialMode ? { initialMode: options.initialMode } : {},
|
|
83889
|
-
...
|
|
84014
|
+
...initialValues ? { initialValues } : {},
|
|
83890
84015
|
...options.onlyFields ? { onlyFields: options.onlyFields } : {},
|
|
84016
|
+
...options.detectedRepo ? { detectedRepo: { owner: options.detectedRepo.owner, name: options.detectedRepo.name } } : {},
|
|
83891
84017
|
...buildMarkdown ? { buildMarkdown } : {}
|
|
83892
84018
|
}));
|
|
83893
84019
|
await waitUntilExit();
|
|
@@ -83971,10 +84097,12 @@ async function promptMigrate(fromVersion) {
|
|
|
83971
84097
|
}
|
|
83972
84098
|
async function editExisting(projectRoot, path, config2, onlyFields) {
|
|
83973
84099
|
const existing = await Bun.file(path).text();
|
|
84100
|
+
const detectedRepo = await detectRepoIdentity(projectRoot);
|
|
83974
84101
|
const wrote = await runSetupWizard(projectRoot, {
|
|
83975
84102
|
existing,
|
|
83976
84103
|
initialMode: "customized",
|
|
83977
84104
|
initialValues: initialValuesFromConfig(config2),
|
|
84105
|
+
...detectedRepo ? { detectedRepo } : {},
|
|
83978
84106
|
...onlyFields ? { onlyFields } : {}
|
|
83979
84107
|
});
|
|
83980
84108
|
process.stdout.write(wrote ? `
|
|
@@ -84010,7 +84138,8 @@ async function main(argv) {
|
|
|
84010
84138
|
`);
|
|
84011
84139
|
return 0;
|
|
84012
84140
|
}
|
|
84013
|
-
const
|
|
84141
|
+
const detectedRepo2 = await detectRepoIdentity(projectRoot);
|
|
84142
|
+
const wrote2 = await runSetupWizard(projectRoot, detectedRepo2 ? { detectedRepo: detectedRepo2 } : {});
|
|
84014
84143
|
process.stdout.write(wrote2 ? `
|
|
84015
84144
|
\u2713 Recreated ${path}
|
|
84016
84145
|
` : `
|
|
@@ -84043,7 +84172,8 @@ Setup cancelled \u2014 no file written.
|
|
|
84043
84172
|
`);
|
|
84044
84173
|
return 0;
|
|
84045
84174
|
}
|
|
84046
|
-
const
|
|
84175
|
+
const detectedRepo = await detectRepoIdentity(projectRoot);
|
|
84176
|
+
const wrote = await runSetupWizard(projectRoot, detectedRepo ? { detectedRepo } : {});
|
|
84047
84177
|
process.stdout.write(wrote ? `
|
|
84048
84178
|
\u2713 Created ${path}
|
|
84049
84179
|
` : `
|
|
@@ -84056,6 +84186,7 @@ var init_src4 = __esm(async () => {
|
|
|
84056
84186
|
init_paths();
|
|
84057
84187
|
init_workflow();
|
|
84058
84188
|
init_wizard();
|
|
84189
|
+
init_repo();
|
|
84059
84190
|
init_migrations();
|
|
84060
84191
|
await __promiseAll([
|
|
84061
84192
|
init_build2(),
|
|
@@ -99057,12 +99188,20 @@ var init_loop_machine = __esm(() => {
|
|
|
99057
99188
|
});
|
|
99058
99189
|
});
|
|
99059
99190
|
|
|
99191
|
+
// packages/core/src/machines/mcp-registry.ts
|
|
99192
|
+
var init_mcp_registry = __esm(() => {
|
|
99193
|
+
init_example_machine();
|
|
99194
|
+
init_flow_machine();
|
|
99195
|
+
init_loop_machine();
|
|
99196
|
+
});
|
|
99197
|
+
|
|
99060
99198
|
// packages/core/src/machines/index.ts
|
|
99061
99199
|
var init_machines = __esm(() => {
|
|
99062
99200
|
init_example_machine();
|
|
99063
99201
|
init_flow_machine();
|
|
99064
99202
|
init_flow_actor_store();
|
|
99065
99203
|
init_loop_machine();
|
|
99204
|
+
init_mcp_registry();
|
|
99066
99205
|
});
|
|
99067
99206
|
|
|
99068
99207
|
// packages/core/src/tasks-md.ts
|
|
@@ -99156,10 +99295,112 @@ var init_tasks_md = __esm(() => {
|
|
|
99156
99295
|
];
|
|
99157
99296
|
});
|
|
99158
99297
|
|
|
99298
|
+
// packages/core/src/prompt/effort.ts
|
|
99299
|
+
function countUnchecked2(tasksContent) {
|
|
99300
|
+
const matches2 = tasksContent.match(/^\s*[-*]\s+\[ \]/gm);
|
|
99301
|
+
return matches2 ? matches2.length : 0;
|
|
99302
|
+
}
|
|
99303
|
+
function clamp2(value, min2, max2) {
|
|
99304
|
+
return Math.max(min2, Math.min(max2, value));
|
|
99305
|
+
}
|
|
99306
|
+
function detectEffort(state, options = {}) {
|
|
99307
|
+
if (options.override)
|
|
99308
|
+
return options.override;
|
|
99309
|
+
const prompt = (state.prompt ?? "").toLowerCase();
|
|
99310
|
+
let keywordScore = 0;
|
|
99311
|
+
for (const kw of HEAVY_KEYWORDS) {
|
|
99312
|
+
if (prompt.includes(kw))
|
|
99313
|
+
keywordScore += HEAVY_WEIGHT;
|
|
99314
|
+
}
|
|
99315
|
+
for (const kw of LIGHT_KEYWORDS) {
|
|
99316
|
+
if (prompt.includes(kw))
|
|
99317
|
+
keywordScore += LIGHT_WEIGHT;
|
|
99318
|
+
}
|
|
99319
|
+
keywordScore = clamp2(keywordScore, -KEYWORD_HIT_CAP, KEYWORD_HIT_CAP);
|
|
99320
|
+
let score = keywordScore;
|
|
99321
|
+
const hasHeavyKeyword = keywordScore > 0;
|
|
99322
|
+
if (prompt.length > 0 && prompt.length < SHORT_PROMPT_CHARS && !hasHeavyKeyword) {
|
|
99323
|
+
score -= 1;
|
|
99324
|
+
} else if (prompt.length > LONG_PROMPT_CHARS) {
|
|
99325
|
+
score += 1;
|
|
99326
|
+
}
|
|
99327
|
+
if (options.tasksContent) {
|
|
99328
|
+
const unchecked = countUnchecked2(options.tasksContent);
|
|
99329
|
+
if (unchecked > 0 && unchecked <= FEW_TASKS) {
|
|
99330
|
+
score -= 2;
|
|
99331
|
+
} else if (unchecked >= MANY_TASKS) {
|
|
99332
|
+
score += 2;
|
|
99333
|
+
}
|
|
99334
|
+
}
|
|
99335
|
+
if (score <= LIGHT_THRESHOLD)
|
|
99336
|
+
return "light";
|
|
99337
|
+
if (score >= HEAVY_THRESHOLD)
|
|
99338
|
+
return "heavy";
|
|
99339
|
+
return "standard";
|
|
99340
|
+
}
|
|
99341
|
+
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;
|
|
99342
|
+
var init_effort = __esm(() => {
|
|
99343
|
+
HEAVY_KEYWORDS = [
|
|
99344
|
+
"migrate",
|
|
99345
|
+
"refactor",
|
|
99346
|
+
"redesign",
|
|
99347
|
+
"re-architect",
|
|
99348
|
+
"architecture",
|
|
99349
|
+
"rewrite",
|
|
99350
|
+
"overhaul",
|
|
99351
|
+
"breaking change",
|
|
99352
|
+
"investigate",
|
|
99353
|
+
"spike",
|
|
99354
|
+
"cross-cutting",
|
|
99355
|
+
"end-to-end"
|
|
99356
|
+
];
|
|
99357
|
+
LIGHT_KEYWORDS = [
|
|
99358
|
+
"typo",
|
|
99359
|
+
"rename",
|
|
99360
|
+
"bump",
|
|
99361
|
+
"tweak",
|
|
99362
|
+
"wording",
|
|
99363
|
+
"copy",
|
|
99364
|
+
"comment",
|
|
99365
|
+
"lint",
|
|
99366
|
+
"docs",
|
|
99367
|
+
"one-liner",
|
|
99368
|
+
"revert",
|
|
99369
|
+
"whitespace"
|
|
99370
|
+
];
|
|
99371
|
+
EFFORT_GUIDANCE = {
|
|
99372
|
+
light: [
|
|
99373
|
+
"This ticket looks **light**. Make the smallest correct change.",
|
|
99374
|
+
"- Skip research/design ceremony \u2014 go straight to the fix",
|
|
99375
|
+
"- Avoid speculative abstraction; do not expand scope",
|
|
99376
|
+
"- Aim to finish in as few iterations as possible"
|
|
99377
|
+
].join(`
|
|
99378
|
+
`),
|
|
99379
|
+
standard: [
|
|
99380
|
+
"This ticket looks **standard**. Balance thoroughness with momentum.",
|
|
99381
|
+
"- Do enough investigation to be confident, but don't over-engineer",
|
|
99382
|
+
"- Keep changes focused on the stated scope",
|
|
99383
|
+
"- Verify with the project's lint and test gates before finishing"
|
|
99384
|
+
].join(`
|
|
99385
|
+
`),
|
|
99386
|
+
heavy: [
|
|
99387
|
+
"This ticket looks **heavy**. Invest up front before changing code.",
|
|
99388
|
+
"- Research the affected areas and write a real design",
|
|
99389
|
+
"- Break the work into small, independently-verifiable tasks",
|
|
99390
|
+
"- Watch for cross-cutting impact and regressions as you go"
|
|
99391
|
+
].join(`
|
|
99392
|
+
`)
|
|
99393
|
+
};
|
|
99394
|
+
});
|
|
99395
|
+
|
|
99159
99396
|
// packages/core/src/prompt/meta-prompt.ts
|
|
99160
99397
|
function buildMetaPrompt(state, phase, options = {}) {
|
|
99161
99398
|
if (options.enabled === false)
|
|
99162
99399
|
return "";
|
|
99400
|
+
const effort = detectEffort(state, {
|
|
99401
|
+
...options.effort !== undefined ? { override: options.effort } : {},
|
|
99402
|
+
...options.tasksContent !== undefined ? { tasksContent: options.tasksContent } : {}
|
|
99403
|
+
});
|
|
99163
99404
|
let out = `---
|
|
99164
99405
|
|
|
99165
99406
|
## Task Context
|
|
@@ -99170,6 +99411,8 @@ function buildMetaPrompt(state, phase, options = {}) {
|
|
|
99170
99411
|
out += `**Engine/Model:** ${state.engine} / ${state.model}
|
|
99171
99412
|
`;
|
|
99172
99413
|
out += `**Phase:** ${phase}
|
|
99414
|
+
`;
|
|
99415
|
+
out += `**Effort:** ${effort}
|
|
99173
99416
|
`;
|
|
99174
99417
|
out += `**Iteration:** ${state.iteration + 1}`;
|
|
99175
99418
|
if (options.maxIterations && options.maxIterations > 0) {
|
|
@@ -99193,6 +99436,12 @@ function buildMetaPrompt(state, phase, options = {}) {
|
|
|
99193
99436
|
`;
|
|
99194
99437
|
out += PHASE_GUIDANCE[phase] + `
|
|
99195
99438
|
|
|
99439
|
+
`;
|
|
99440
|
+
out += `### Effort Guidance
|
|
99441
|
+
|
|
99442
|
+
`;
|
|
99443
|
+
out += EFFORT_GUIDANCE[effort] + `
|
|
99444
|
+
|
|
99196
99445
|
`;
|
|
99197
99446
|
const flags = [];
|
|
99198
99447
|
if (options.useWorktree) {
|
|
@@ -99225,6 +99474,7 @@ function buildMetaPrompt(state, phase, options = {}) {
|
|
|
99225
99474
|
}
|
|
99226
99475
|
var PHASE_GUIDANCE;
|
|
99227
99476
|
var init_meta_prompt = __esm(() => {
|
|
99477
|
+
init_effort();
|
|
99228
99478
|
PHASE_GUIDANCE = {
|
|
99229
99479
|
research: [
|
|
99230
99480
|
"You are in the **research** phase. Your goal is to understand, not to implement.",
|
|
@@ -99698,6 +99948,7 @@ var init_loop = __esm(() => {
|
|
|
99698
99948
|
init_tasks_md();
|
|
99699
99949
|
init_phase();
|
|
99700
99950
|
init_meta_prompt();
|
|
99951
|
+
init_effort();
|
|
99701
99952
|
init_tasks_md();
|
|
99702
99953
|
});
|
|
99703
99954
|
|
|
@@ -99978,7 +100229,10 @@ function useLoop(opts) {
|
|
|
99978
100229
|
design: designContent,
|
|
99979
100230
|
tasks: tasksContent
|
|
99980
100231
|
});
|
|
99981
|
-
const prompt = buildPhasePrompt(routedPhase, currentState, tasksDir, opts.reviewPhase,
|
|
100232
|
+
const prompt = buildPhasePrompt(routedPhase, currentState, tasksDir, opts.reviewPhase, {
|
|
100233
|
+
...opts.metaPrompt,
|
|
100234
|
+
...tasksContent !== null ? { tasksContent } : {}
|
|
100235
|
+
});
|
|
99982
100236
|
const iterStart = new Date().toISOString();
|
|
99983
100237
|
try {
|
|
99984
100238
|
const controller = new AbortController;
|
|
@@ -101164,7 +101418,8 @@ async function parseAgentArgs(argv) {
|
|
|
101164
101418
|
debug: false,
|
|
101165
101419
|
noTmux: false,
|
|
101166
101420
|
checks: false,
|
|
101167
|
-
review: false
|
|
101421
|
+
review: false,
|
|
101422
|
+
ticketTokens: []
|
|
101168
101423
|
};
|
|
101169
101424
|
const state = emptyParseState();
|
|
101170
101425
|
let expectLinearTeam = false;
|
|
@@ -101174,6 +101429,7 @@ async function parseAgentArgs(argv) {
|
|
|
101174
101429
|
let expectMaxTickets = false;
|
|
101175
101430
|
let expectIndicator = false;
|
|
101176
101431
|
let expectJsonLogFile = false;
|
|
101432
|
+
let expectTicket = false;
|
|
101177
101433
|
for (const arg of argv) {
|
|
101178
101434
|
if (expectLinearTeam) {
|
|
101179
101435
|
result2.linearTeam = arg;
|
|
@@ -101211,6 +101467,14 @@ async function parseAgentArgs(argv) {
|
|
|
101211
101467
|
expectJsonLogFile = false;
|
|
101212
101468
|
continue;
|
|
101213
101469
|
}
|
|
101470
|
+
if (expectTicket) {
|
|
101471
|
+
for (const token of arg.split(",").map((t) => t.trim())) {
|
|
101472
|
+
if (token)
|
|
101473
|
+
result2.ticketTokens.push(token);
|
|
101474
|
+
}
|
|
101475
|
+
expectTicket = false;
|
|
101476
|
+
continue;
|
|
101477
|
+
}
|
|
101214
101478
|
if (parseCommonArg(arg, result2, state))
|
|
101215
101479
|
continue;
|
|
101216
101480
|
switch (arg) {
|
|
@@ -101229,6 +101493,9 @@ async function parseAgentArgs(argv) {
|
|
|
101229
101493
|
case "--max-tickets":
|
|
101230
101494
|
expectMaxTickets = true;
|
|
101231
101495
|
break;
|
|
101496
|
+
case "--ticket":
|
|
101497
|
+
expectTicket = true;
|
|
101498
|
+
break;
|
|
101232
101499
|
case "--worktree":
|
|
101233
101500
|
result2.worktree = true;
|
|
101234
101501
|
break;
|
|
@@ -101353,6 +101620,7 @@ var init_cli2 = __esm(() => {
|
|
|
101353
101620
|
" --stack-prs Base the PR on a blocker issue's open-PR head branch when present (needs --create-pr)",
|
|
101354
101621
|
" --code-review Watch open tracked PRs for unresolved review comments",
|
|
101355
101622
|
" --max-tickets <n> Stop picking up new issues after N have been started (0 = unlimited)",
|
|
101623
|
+
" --ticket <id> Restrict issue discovery to specific ticket(s); repeatable or comma-separated (e.g. RLF-208 or 208)",
|
|
101356
101624
|
" --no-tmux Disable tmux session management; run agent in the foreground directly",
|
|
101357
101625
|
" --no-pr-tracker Disable RLF-173 pr-tracker bail / recovery counter for this run",
|
|
101358
101626
|
" --json-output Emit JSONL to stdout instead of the Ink dashboard (for scripting/CI)",
|
|
@@ -101374,6 +101642,11 @@ var init_cli2 = __esm(() => {
|
|
|
101374
101642
|
});
|
|
101375
101643
|
|
|
101376
101644
|
// apps/agent/src/agent/config.ts
|
|
101645
|
+
var exports_config = {};
|
|
101646
|
+
__export(exports_config, {
|
|
101647
|
+
loadRalphyConfig: () => loadRalphyConfig,
|
|
101648
|
+
ensureRalphyConfig: () => ensureRalphyConfig
|
|
101649
|
+
});
|
|
101377
101650
|
async function loadRalphyConfig(projectRoot) {
|
|
101378
101651
|
const { config: config2 } = await loadWorkflow(projectRoot);
|
|
101379
101652
|
return config2;
|
|
@@ -101734,10 +102007,107 @@ function findBoundaryViolations(changedFiles, patterns) {
|
|
|
101734
102007
|
// apps/agent/src/shared/utils/ralph-comment.ts
|
|
101735
102008
|
function isRalphComment(body) {
|
|
101736
102009
|
const trimmed = body.trimStart();
|
|
101737
|
-
return /^(\uD83E\uDD16|\uD83D\uDD04|\u2705|\u2717|\u26A0|\uD83D\uDD01|\uD83D\uDCCB)\s*Ralphy?\b/.test(trimmed);
|
|
102010
|
+
return /^(\uD83E\uDD16|\uD83D\uDD04|\u2705|\u2717|\u274C|\u26A0|\uD83D\uDD01|\uD83D\uDCCB|\u23F0)\s*Ralphy?\b/.test(trimmed);
|
|
101738
102011
|
}
|
|
101739
102012
|
|
|
101740
102013
|
// apps/agent/src/shared/capabilities/linear-client.ts
|
|
102014
|
+
var exports_linear_client = {};
|
|
102015
|
+
__export(exports_linear_client, {
|
|
102016
|
+
upsertRalphyAttachment: () => upsertRalphyAttachment,
|
|
102017
|
+
uploadFileToLinear: () => uploadFileToLinear,
|
|
102018
|
+
updateIssueState: () => updateIssueState,
|
|
102019
|
+
updateIssueDescription: () => updateIssueDescription,
|
|
102020
|
+
updateIssueComment: () => updateIssueComment,
|
|
102021
|
+
updateAttachmentSubtitle: () => updateAttachmentSubtitle,
|
|
102022
|
+
setIssueProject: () => setIssueProject,
|
|
102023
|
+
resolveTicketNumbers: () => resolveTicketNumbers,
|
|
102024
|
+
removeLabelFromIssue: () => removeLabelFromIssue,
|
|
102025
|
+
parseTicketIdentifier: () => parseTicketIdentifier,
|
|
102026
|
+
linearRequestInternals: () => linearRequestInternals,
|
|
102027
|
+
issueMatchesGetIndicator: () => issueMatchesGetIndicator,
|
|
102028
|
+
isRateLimitedError: () => isRateLimitedError,
|
|
102029
|
+
formatTicketError: () => formatTicketError,
|
|
102030
|
+
formatLinearError: () => formatLinearError,
|
|
102031
|
+
findOpenIssueByLabel: () => findOpenIssueByLabel,
|
|
102032
|
+
findIssueAttachmentByTitle: () => findIssueAttachmentByTitle,
|
|
102033
|
+
fetchWorkflowStates: () => fetchWorkflowStates,
|
|
102034
|
+
fetchTeamIdByKey: () => fetchTeamIdByKey,
|
|
102035
|
+
fetchProjectIdByName: () => fetchProjectIdByName,
|
|
102036
|
+
fetchOpenIssues: () => fetchOpenIssues,
|
|
102037
|
+
fetchMentionScanIssues: () => fetchMentionScanIssues,
|
|
102038
|
+
fetchIssueLabels: () => fetchIssueLabels,
|
|
102039
|
+
fetchIssueComments: () => fetchIssueComments,
|
|
102040
|
+
fetchIssueAttachments: () => fetchIssueAttachments,
|
|
102041
|
+
fetchAttachmentsForIssues: () => fetchAttachmentsForIssues,
|
|
102042
|
+
deleteIssueComment: () => deleteIssueComment,
|
|
102043
|
+
deleteAttachment: () => deleteAttachment,
|
|
102044
|
+
createRalphyAttachment: () => createRalphyAttachment,
|
|
102045
|
+
createIssueLabel: () => createIssueLabel,
|
|
102046
|
+
createIssueComment: () => createIssueComment,
|
|
102047
|
+
createIssue: () => createIssue,
|
|
102048
|
+
createAttachmentForUrl: () => createAttachmentForUrl,
|
|
102049
|
+
clauseFromMarkers: () => clauseFromMarkers,
|
|
102050
|
+
buildIssueFilter: () => buildIssueFilter,
|
|
102051
|
+
baseBranchFromLabels: () => baseBranchFromLabels,
|
|
102052
|
+
addReactionToComment: () => addReactionToComment,
|
|
102053
|
+
addLabelToIssue: () => addLabelToIssue,
|
|
102054
|
+
addIssueComment: () => addIssueComment,
|
|
102055
|
+
RALPHY_ATTACHMENT_TITLE: () => RALPHY_ATTACHMENT_TITLE
|
|
102056
|
+
});
|
|
102057
|
+
function parseTicketIdentifier(raw) {
|
|
102058
|
+
const trimmed = raw.trim();
|
|
102059
|
+
if (!trimmed) {
|
|
102060
|
+
throw new Error("--ticket value cannot be empty");
|
|
102061
|
+
}
|
|
102062
|
+
const bare = TICKET_BARE_NUMBER_RE.exec(trimmed);
|
|
102063
|
+
if (bare) {
|
|
102064
|
+
return { teamKey: null, number: Number(bare[1]) };
|
|
102065
|
+
}
|
|
102066
|
+
const match = TICKET_IDENTIFIER_RE.exec(trimmed);
|
|
102067
|
+
if (!match) {
|
|
102068
|
+
const err = new Error("--ticket value is not a Linear ticket (expected e.g. RLF-208 or 208)");
|
|
102069
|
+
err.value = raw;
|
|
102070
|
+
throw err;
|
|
102071
|
+
}
|
|
102072
|
+
return { teamKey: match[1].toUpperCase(), number: Number(match[2]) };
|
|
102073
|
+
}
|
|
102074
|
+
function resolveTicketNumbers(tokens, team) {
|
|
102075
|
+
const teamKey = team?.trim() ? team.trim().toUpperCase() : null;
|
|
102076
|
+
const seen = new Set;
|
|
102077
|
+
const out = [];
|
|
102078
|
+
for (const token of tokens) {
|
|
102079
|
+
const { teamKey: parsedTeam, number: number4 } = parseTicketIdentifier(token);
|
|
102080
|
+
if (parsedTeam !== null) {
|
|
102081
|
+
if (teamKey !== null && parsedTeam !== teamKey) {
|
|
102082
|
+
const err = new Error("--ticket identifier is not in the configured team");
|
|
102083
|
+
err.ticket = token;
|
|
102084
|
+
err.team = team;
|
|
102085
|
+
throw err;
|
|
102086
|
+
}
|
|
102087
|
+
} else if (teamKey === null) {
|
|
102088
|
+
const err = new Error("--ticket bare number needs a configured team; pass --linear-team or set linear.team in config");
|
|
102089
|
+
err.ticket = token;
|
|
102090
|
+
throw err;
|
|
102091
|
+
}
|
|
102092
|
+
if (!seen.has(number4)) {
|
|
102093
|
+
seen.add(number4);
|
|
102094
|
+
out.push(number4);
|
|
102095
|
+
}
|
|
102096
|
+
}
|
|
102097
|
+
return out;
|
|
102098
|
+
}
|
|
102099
|
+
function formatTicketError(err) {
|
|
102100
|
+
if (!(err instanceof Error))
|
|
102101
|
+
return String(err);
|
|
102102
|
+
const e = err;
|
|
102103
|
+
const detail = e.ticket ?? e.value;
|
|
102104
|
+
const parts = [];
|
|
102105
|
+
if (detail)
|
|
102106
|
+
parts.push(`ticket: ${detail}`);
|
|
102107
|
+
if (e.team)
|
|
102108
|
+
parts.push(`configured team: ${e.team}`);
|
|
102109
|
+
return parts.length > 0 ? `${e.message} (${parts.join(", ")})` : e.message;
|
|
102110
|
+
}
|
|
101741
102111
|
function partition2(markers) {
|
|
101742
102112
|
const statuses = [];
|
|
101743
102113
|
const labels = [];
|
|
@@ -101770,6 +102140,9 @@ function buildIssueFilter(spec) {
|
|
|
101770
102140
|
} else {
|
|
101771
102141
|
where.assignee = { null: true };
|
|
101772
102142
|
}
|
|
102143
|
+
if (spec.numbers && spec.numbers.length > 0) {
|
|
102144
|
+
where.number = { in: spec.numbers };
|
|
102145
|
+
}
|
|
101773
102146
|
const inc = spec.include ?? [];
|
|
101774
102147
|
if (inc.length > 0) {
|
|
101775
102148
|
const { statuses, labels, attachmentSubtitles, projects } = partition2(inc);
|
|
@@ -101873,6 +102246,30 @@ function clauseFromMarkers(markers) {
|
|
|
101873
102246
|
parts.project = { name: { in: projects } };
|
|
101874
102247
|
return Object.keys(parts).length > 0 ? parts : null;
|
|
101875
102248
|
}
|
|
102249
|
+
function mapNodeProject(node2) {
|
|
102250
|
+
if (!node2.project)
|
|
102251
|
+
return null;
|
|
102252
|
+
return {
|
|
102253
|
+
id: node2.project.id,
|
|
102254
|
+
name: node2.project.name,
|
|
102255
|
+
...node2.project.priority !== undefined && node2.project.priority !== null ? { priority: node2.project.priority } : {}
|
|
102256
|
+
};
|
|
102257
|
+
}
|
|
102258
|
+
function mapNodeMilestone(node2) {
|
|
102259
|
+
const m = node2.projectMilestone;
|
|
102260
|
+
if (!m)
|
|
102261
|
+
return;
|
|
102262
|
+
return {
|
|
102263
|
+
id: m.id,
|
|
102264
|
+
name: m.name,
|
|
102265
|
+
sortOrder: m.sortOrder,
|
|
102266
|
+
...m.targetDate != null ? { targetDate: m.targetDate } : {}
|
|
102267
|
+
};
|
|
102268
|
+
}
|
|
102269
|
+
function milestoneSpread(node2) {
|
|
102270
|
+
const m = mapNodeMilestone(node2);
|
|
102271
|
+
return m ? { milestone: m } : {};
|
|
102272
|
+
}
|
|
101876
102273
|
async function fetchMentionScanIssues(apiKey, spec) {
|
|
101877
102274
|
const branches = [];
|
|
101878
102275
|
const { getTodo, getInProgress, setDone } = spec.indicators;
|
|
@@ -101901,13 +102298,17 @@ async function fetchMentionScanIssues(apiKey, spec) {
|
|
|
101901
102298
|
else
|
|
101902
102299
|
where.assignee = { id: { eq: spec.assignee } };
|
|
101903
102300
|
}
|
|
102301
|
+
if (spec.numbers && spec.numbers.length > 0) {
|
|
102302
|
+
where.number = { in: spec.numbers };
|
|
102303
|
+
}
|
|
101904
102304
|
const query = `query MentionScanIssues($filter: IssueFilter) {
|
|
101905
102305
|
issues(filter: $filter, first: 50) {
|
|
101906
102306
|
nodes {
|
|
101907
102307
|
id identifier title description url priority createdAt
|
|
101908
102308
|
state { name type }
|
|
101909
102309
|
assignee { id email name }
|
|
101910
|
-
project { id name }
|
|
102310
|
+
project { id name priority }
|
|
102311
|
+
projectMilestone { id name sortOrder targetDate }
|
|
101911
102312
|
labels { nodes { name } }
|
|
101912
102313
|
relations(first: 50) {
|
|
101913
102314
|
nodes { type relatedIssue { id identifier state { type } } }
|
|
@@ -101930,7 +102331,8 @@ async function fetchMentionScanIssues(apiKey, spec) {
|
|
|
101930
102331
|
url: n.url,
|
|
101931
102332
|
state: n.state,
|
|
101932
102333
|
assignee: n.assignee,
|
|
101933
|
-
project: n
|
|
102334
|
+
project: mapNodeProject(n),
|
|
102335
|
+
...milestoneSpread(n),
|
|
101934
102336
|
labels: n.labels.nodes.map((l) => l.name),
|
|
101935
102337
|
priority: n.priority,
|
|
101936
102338
|
createdAt: n.createdAt ?? "",
|
|
@@ -101951,7 +102353,8 @@ async function fetchOpenIssues(apiKey, spec, options) {
|
|
|
101951
102353
|
id identifier title description url priority createdAt
|
|
101952
102354
|
state { name type }
|
|
101953
102355
|
assignee { id email name }
|
|
101954
|
-
project { id name }
|
|
102356
|
+
project { id name priority }
|
|
102357
|
+
projectMilestone { id name sortOrder targetDate }
|
|
101955
102358
|
labels { nodes { name } }
|
|
101956
102359
|
relations(first: 50) {
|
|
101957
102360
|
nodes {
|
|
@@ -101975,7 +102378,8 @@ async function fetchOpenIssues(apiKey, spec, options) {
|
|
|
101975
102378
|
url: n.url,
|
|
101976
102379
|
state: n.state,
|
|
101977
102380
|
assignee: n.assignee,
|
|
101978
|
-
project: n
|
|
102381
|
+
project: mapNodeProject(n),
|
|
102382
|
+
...milestoneSpread(n),
|
|
101979
102383
|
labels: n.labels.nodes.map((l) => l.name),
|
|
101980
102384
|
priority: n.priority,
|
|
101981
102385
|
createdAt: n.createdAt ?? "",
|
|
@@ -102488,9 +102892,11 @@ async function removeLabelFromIssue(apiKey, issueId, labelId) {
|
|
|
102488
102892
|
labelId
|
|
102489
102893
|
});
|
|
102490
102894
|
}
|
|
102491
|
-
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:";
|
|
102895
|
+
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:";
|
|
102492
102896
|
var init_linear_client = __esm(() => {
|
|
102493
102897
|
init_types2();
|
|
102898
|
+
TICKET_IDENTIFIER_RE = /^([A-Za-z]+)-(\d+)(?:-.*)?$/;
|
|
102899
|
+
TICKET_BARE_NUMBER_RE = /^(\d+)$/;
|
|
102494
102900
|
linearRequestInternals = {
|
|
102495
102901
|
sleep: (ms) => Bun.sleep(ms)
|
|
102496
102902
|
};
|
|
@@ -104113,17 +104519,183 @@ var init_post_task = __esm(() => {
|
|
|
104113
104519
|
repoAutoMergeCache = new Map;
|
|
104114
104520
|
});
|
|
104115
104521
|
|
|
104116
|
-
//
|
|
104117
|
-
function
|
|
104118
|
-
return
|
|
104119
|
-
|
|
104120
|
-
|
|
104121
|
-
|
|
104122
|
-
return r;
|
|
104123
|
-
}
|
|
104522
|
+
// packages/core/src/ordering/hierarchical-order.ts
|
|
104523
|
+
function rank(priority) {
|
|
104524
|
+
return !priority ? Number.POSITIVE_INFINITY : priority;
|
|
104525
|
+
}
|
|
104526
|
+
function cmpMaybe(a, b, cmp) {
|
|
104527
|
+
if (a === undefined && b === undefined)
|
|
104124
104528
|
return 0;
|
|
104125
|
-
|
|
104529
|
+
if (a === undefined)
|
|
104530
|
+
return 1;
|
|
104531
|
+
if (b === undefined)
|
|
104532
|
+
return -1;
|
|
104533
|
+
return cmp(a, b);
|
|
104126
104534
|
}
|
|
104535
|
+
function cmpString(a, b) {
|
|
104536
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
104537
|
+
}
|
|
104538
|
+
function cmpNumber(a, b) {
|
|
104539
|
+
return a - b;
|
|
104540
|
+
}
|
|
104541
|
+
function cmpRank(a, b) {
|
|
104542
|
+
return a === b ? 0 : a < b ? -1 : 1;
|
|
104543
|
+
}
|
|
104544
|
+
function orderIssuesHierarchically(issues, opts = {}) {
|
|
104545
|
+
const log3 = opts.log ?? ((message) => console.warn(message));
|
|
104546
|
+
if (issues.length <= 1)
|
|
104547
|
+
return issues.slice();
|
|
104548
|
+
const projectBuckets = new Map;
|
|
104549
|
+
for (const issue2 of issues) {
|
|
104550
|
+
const key = issue2.project?.id ?? NO_PROJECT;
|
|
104551
|
+
const bucket = projectBuckets.get(key);
|
|
104552
|
+
if (bucket)
|
|
104553
|
+
bucket.push(issue2);
|
|
104554
|
+
else
|
|
104555
|
+
projectBuckets.set(key, [issue2]);
|
|
104556
|
+
}
|
|
104557
|
+
const projectKeys = [...projectBuckets.keys()].sort((a, b) => {
|
|
104558
|
+
if (a === NO_PROJECT)
|
|
104559
|
+
return b === NO_PROJECT ? 0 : 1;
|
|
104560
|
+
if (b === NO_PROJECT)
|
|
104561
|
+
return -1;
|
|
104562
|
+
const ba = projectBuckets.get(a);
|
|
104563
|
+
const bb = projectBuckets.get(b);
|
|
104564
|
+
const ra = rank(ba[0]?.project?.priority);
|
|
104565
|
+
const rb = rank(bb[0]?.project?.priority);
|
|
104566
|
+
if (ra !== rb)
|
|
104567
|
+
return cmpRank(ra, rb);
|
|
104568
|
+
if (a !== b)
|
|
104569
|
+
return cmpString(a, b);
|
|
104570
|
+
return cmpString(earliestCreatedAt(ba), earliestCreatedAt(bb));
|
|
104571
|
+
});
|
|
104572
|
+
const ordered = [];
|
|
104573
|
+
for (const projectKey of projectKeys) {
|
|
104574
|
+
orderProjectBucket(projectBuckets.get(projectKey), ordered, log3);
|
|
104575
|
+
}
|
|
104576
|
+
return ordered;
|
|
104577
|
+
}
|
|
104578
|
+
function earliestCreatedAt(bucket) {
|
|
104579
|
+
let earliest = bucket[0].createdAt;
|
|
104580
|
+
for (const issue2 of bucket) {
|
|
104581
|
+
if (issue2.createdAt < earliest)
|
|
104582
|
+
earliest = issue2.createdAt;
|
|
104583
|
+
}
|
|
104584
|
+
return earliest;
|
|
104585
|
+
}
|
|
104586
|
+
function orderProjectBucket(bucket, ordered, log3) {
|
|
104587
|
+
const milestoneBuckets = new Map;
|
|
104588
|
+
for (const issue2 of bucket) {
|
|
104589
|
+
const key = issue2.milestone?.id ?? NO_MILESTONE;
|
|
104590
|
+
const b = milestoneBuckets.get(key);
|
|
104591
|
+
if (b)
|
|
104592
|
+
b.push(issue2);
|
|
104593
|
+
else
|
|
104594
|
+
milestoneBuckets.set(key, [issue2]);
|
|
104595
|
+
}
|
|
104596
|
+
const milestoneOf = new Map;
|
|
104597
|
+
for (const [key, b] of milestoneBuckets) {
|
|
104598
|
+
for (const issue2 of b)
|
|
104599
|
+
milestoneOf.set(issue2.id, key);
|
|
104600
|
+
}
|
|
104601
|
+
const milestonePrereqs = new Map;
|
|
104602
|
+
for (const key of milestoneBuckets.keys())
|
|
104603
|
+
milestonePrereqs.set(key, new Set);
|
|
104604
|
+
for (const issue2 of bucket) {
|
|
104605
|
+
const from = milestoneOf.get(issue2.id);
|
|
104606
|
+
for (const blockerId of issue2.blockedByIds) {
|
|
104607
|
+
const blockerMilestone = milestoneOf.get(blockerId);
|
|
104608
|
+
if (blockerMilestone === undefined)
|
|
104609
|
+
continue;
|
|
104610
|
+
if (blockerMilestone === from)
|
|
104611
|
+
continue;
|
|
104612
|
+
milestonePrereqs.get(from).add(blockerMilestone);
|
|
104613
|
+
}
|
|
104614
|
+
}
|
|
104615
|
+
const milestoneMeta = new Map;
|
|
104616
|
+
for (const [key, b] of milestoneBuckets) {
|
|
104617
|
+
milestoneMeta.set(key, key === NO_MILESTONE ? undefined : b[0].milestone);
|
|
104618
|
+
}
|
|
104619
|
+
const milestoneOrder = topoOrder([...milestoneBuckets.keys()], (key) => milestonePrereqs.get(key), (a, b) => {
|
|
104620
|
+
if (a === NO_MILESTONE)
|
|
104621
|
+
return b === NO_MILESTONE ? 0 : 1;
|
|
104622
|
+
if (b === NO_MILESTONE)
|
|
104623
|
+
return -1;
|
|
104624
|
+
const ma = milestoneMeta.get(a);
|
|
104625
|
+
const mb = milestoneMeta.get(b);
|
|
104626
|
+
const so = cmpNumber(ma?.sortOrder ?? 0, mb?.sortOrder ?? 0);
|
|
104627
|
+
if (so !== 0)
|
|
104628
|
+
return so;
|
|
104629
|
+
const td = cmpMaybe(ma?.targetDate, mb?.targetDate, cmpString);
|
|
104630
|
+
if (td !== 0)
|
|
104631
|
+
return td;
|
|
104632
|
+
return cmpString(a, b);
|
|
104633
|
+
}, (key) => log3(`hierarchical-order: milestone dependency cycle involving "${key}"; breaking by selection key`));
|
|
104634
|
+
for (const milestoneKey of milestoneOrder) {
|
|
104635
|
+
orderMilestoneBucket(milestoneBuckets.get(milestoneKey), ordered, log3);
|
|
104636
|
+
}
|
|
104637
|
+
}
|
|
104638
|
+
function orderMilestoneBucket(bucket, ordered, log3) {
|
|
104639
|
+
const inBucket = new Set(bucket.map((i) => i.id));
|
|
104640
|
+
const byId = new Map(bucket.map((i) => [i.id, i]));
|
|
104641
|
+
const order = topoOrder(bucket.map((i) => i.id), (id) => {
|
|
104642
|
+
const prereqs = new Set;
|
|
104643
|
+
for (const blockerId of byId.get(id).blockedByIds) {
|
|
104644
|
+
if (inBucket.has(blockerId))
|
|
104645
|
+
prereqs.add(blockerId);
|
|
104646
|
+
}
|
|
104647
|
+
return prereqs;
|
|
104648
|
+
}, (a, b) => {
|
|
104649
|
+
const ia = byId.get(a);
|
|
104650
|
+
const ib = byId.get(b);
|
|
104651
|
+
const rp = cmpRank(rank(ia.priority), rank(ib.priority));
|
|
104652
|
+
if (rp !== 0)
|
|
104653
|
+
return rp;
|
|
104654
|
+
const tb = cmpNumber(ia.tiebreak ?? 0, ib.tiebreak ?? 0);
|
|
104655
|
+
if (tb !== 0)
|
|
104656
|
+
return tb;
|
|
104657
|
+
const cc = cmpString(ia.createdAt, ib.createdAt);
|
|
104658
|
+
if (cc !== 0)
|
|
104659
|
+
return cc;
|
|
104660
|
+
return cmpString(a, b);
|
|
104661
|
+
}, (id) => log3(`hierarchical-order: item dependency cycle involving "${id}"; breaking by selection key`));
|
|
104662
|
+
for (const id of order)
|
|
104663
|
+
ordered.push(byId.get(id));
|
|
104664
|
+
}
|
|
104665
|
+
function topoOrder(nodes, prereqsOf, select2, onCycle) {
|
|
104666
|
+
const remaining = new Set(nodes);
|
|
104667
|
+
const placed = new Set;
|
|
104668
|
+
const result2 = [];
|
|
104669
|
+
while (remaining.size > 0) {
|
|
104670
|
+
const eligible = [];
|
|
104671
|
+
for (const node2 of remaining) {
|
|
104672
|
+
let ready = true;
|
|
104673
|
+
for (const prereq of prereqsOf(node2)) {
|
|
104674
|
+
if (remaining.has(prereq) && !placed.has(prereq)) {
|
|
104675
|
+
ready = false;
|
|
104676
|
+
break;
|
|
104677
|
+
}
|
|
104678
|
+
}
|
|
104679
|
+
if (ready)
|
|
104680
|
+
eligible.push(node2);
|
|
104681
|
+
}
|
|
104682
|
+
let pick3;
|
|
104683
|
+
if (eligible.length > 0) {
|
|
104684
|
+
pick3 = eligible.sort(select2)[0];
|
|
104685
|
+
} else {
|
|
104686
|
+
pick3 = [...remaining].sort(select2)[0];
|
|
104687
|
+
onCycle(pick3);
|
|
104688
|
+
}
|
|
104689
|
+
result2.push(pick3);
|
|
104690
|
+
placed.add(pick3);
|
|
104691
|
+
remaining.delete(pick3);
|
|
104692
|
+
}
|
|
104693
|
+
return result2;
|
|
104694
|
+
}
|
|
104695
|
+
var NO_PROJECT = "\x00no-project", NO_MILESTONE = "\x00no-milestone";
|
|
104696
|
+
|
|
104697
|
+
// packages/core/src/ordering/index.ts
|
|
104698
|
+
var init_ordering = () => {};
|
|
104127
104699
|
|
|
104128
104700
|
// apps/agent/src/queue/queue-order.ts
|
|
104129
104701
|
function defaultPriorityFor(trigger) {
|
|
@@ -104140,21 +104712,70 @@ function defaultPriorityFor(trigger) {
|
|
|
104140
104712
|
return 4;
|
|
104141
104713
|
}
|
|
104142
104714
|
}
|
|
104143
|
-
function
|
|
104144
|
-
|
|
104145
|
-
|
|
104146
|
-
|
|
104147
|
-
|
|
104148
|
-
|
|
104149
|
-
|
|
104150
|
-
|
|
104151
|
-
|
|
104152
|
-
|
|
104153
|
-
|
|
104154
|
-
|
|
104155
|
-
|
|
104715
|
+
function isAutoMergeBoost(e, getAutoMerge) {
|
|
104716
|
+
return e.trigger === "conflict-fix" && issueMatchesGetIndicator(e.issue, getAutoMerge);
|
|
104717
|
+
}
|
|
104718
|
+
function linearIssueToOrderable(issue2, tiebreak) {
|
|
104719
|
+
return {
|
|
104720
|
+
id: issue2.id,
|
|
104721
|
+
...issue2.project ? {
|
|
104722
|
+
project: {
|
|
104723
|
+
id: issue2.project.id,
|
|
104724
|
+
...issue2.project.priority !== undefined ? { priority: issue2.project.priority } : {}
|
|
104725
|
+
}
|
|
104726
|
+
} : {},
|
|
104727
|
+
...issue2.milestone ? {
|
|
104728
|
+
milestone: {
|
|
104729
|
+
id: issue2.milestone.id,
|
|
104730
|
+
sortOrder: issue2.milestone.sortOrder,
|
|
104731
|
+
...issue2.milestone.targetDate ? { targetDate: issue2.milestone.targetDate } : {}
|
|
104732
|
+
}
|
|
104733
|
+
} : {},
|
|
104734
|
+
priority: issue2.priority,
|
|
104735
|
+
...tiebreak !== undefined ? { tiebreak } : {},
|
|
104736
|
+
blockedByIds: issue2.blockedByIds,
|
|
104737
|
+
createdAt: issue2.createdAt
|
|
104738
|
+
};
|
|
104739
|
+
}
|
|
104740
|
+
function toOrderable(entry) {
|
|
104741
|
+
return { ...linearIssueToOrderable(entry.issue, entry.priority), entry };
|
|
104742
|
+
}
|
|
104743
|
+
function orderEntries(entries) {
|
|
104744
|
+
if (entries.length <= 1)
|
|
104745
|
+
return entries.slice();
|
|
104746
|
+
const repByIssue = new Map;
|
|
104747
|
+
for (const entry of entries) {
|
|
104748
|
+
const orderable = toOrderable(entry);
|
|
104749
|
+
const existing = repByIssue.get(orderable.id);
|
|
104750
|
+
if (!existing || orderable.tiebreak < existing.tiebreak) {
|
|
104751
|
+
repByIssue.set(orderable.id, orderable);
|
|
104752
|
+
}
|
|
104753
|
+
}
|
|
104754
|
+
const rankOf = new Map;
|
|
104755
|
+
orderIssuesHierarchically([...repByIssue.values()]).forEach((o, i) => rankOf.set(o.id, i));
|
|
104756
|
+
return entries.map((entry, index) => ({ entry, index })).sort((a, b) => {
|
|
104757
|
+
const ra = rankOf.get(a.entry.issue.id);
|
|
104758
|
+
const rb = rankOf.get(b.entry.issue.id);
|
|
104759
|
+
if (ra !== rb)
|
|
104760
|
+
return ra - rb;
|
|
104761
|
+
if (a.entry.priority !== b.entry.priority)
|
|
104762
|
+
return a.entry.priority - b.entry.priority;
|
|
104763
|
+
return a.index - b.index;
|
|
104764
|
+
}).map((x) => x.entry);
|
|
104765
|
+
}
|
|
104766
|
+
function orderQueueEntries(entries, getAutoMerge) {
|
|
104767
|
+
const boosted = [];
|
|
104768
|
+
const rest2 = [];
|
|
104769
|
+
for (const e of entries) {
|
|
104770
|
+
if (isAutoMergeBoost(e, getAutoMerge))
|
|
104771
|
+
boosted.push(e);
|
|
104772
|
+
else
|
|
104773
|
+
rest2.push(e);
|
|
104774
|
+
}
|
|
104775
|
+
return [...orderEntries(boosted), ...orderEntries(rest2)];
|
|
104156
104776
|
}
|
|
104157
104777
|
var init_queue_order = __esm(() => {
|
|
104778
|
+
init_ordering();
|
|
104158
104779
|
init_linear();
|
|
104159
104780
|
});
|
|
104160
104781
|
|
|
@@ -104354,7 +104975,7 @@ class AgentCoordinator {
|
|
|
104354
104975
|
}
|
|
104355
104976
|
const prStatus = await this.scanPrMergeStates();
|
|
104356
104977
|
if (this.queue.length > 0) {
|
|
104357
|
-
this.queue
|
|
104978
|
+
this.queue = orderQueueEntries(this.queue, this.opts.getAutoMerge);
|
|
104358
104979
|
}
|
|
104359
104980
|
this.spawnNext();
|
|
104360
104981
|
await this.reportProgress();
|
|
@@ -105580,6 +106201,10 @@ async function releaseAwaitingMarker(issue2, statePath, deps) {
|
|
|
105580
106201
|
deps.onLog(`! persist cleared awaitingMarkerAppliedAt for ${issue2.identifier}: ${err.message}`, "yellow");
|
|
105581
106202
|
}
|
|
105582
106203
|
}
|
|
106204
|
+
function confirmationUsesCommentIndicator(cfg) {
|
|
106205
|
+
const { getApproved, getAutoApprove, getConfirmGate } = cfg.linear.indicators;
|
|
106206
|
+
return [getApproved, getAutoApprove, getConfirmGate].some((g) => g?.filter.some((m) => m.type === "comment"));
|
|
106207
|
+
}
|
|
105583
106208
|
async function processAwaitingForIssue(issue2, deps) {
|
|
105584
106209
|
try {
|
|
105585
106210
|
const { cfg, apiKey, indicators } = deps;
|
|
@@ -105600,10 +106225,26 @@ async function processAwaitingForIssue(issue2, deps) {
|
|
|
105600
106225
|
const tasks2 = await readTextOrNull(join24(changeDir, "tasks.md"));
|
|
105601
106226
|
const proposal = await readTextOrNull(join24(changeDir, "proposal.md"));
|
|
105602
106227
|
const design = await readTextOrNull(join24(changeDir, "design.md"));
|
|
106228
|
+
let commentsCache = null;
|
|
106229
|
+
const getComments = async () => {
|
|
106230
|
+
if (commentsCache)
|
|
106231
|
+
return commentsCache;
|
|
106232
|
+
if (!apiKey)
|
|
106233
|
+
return commentsCache = [];
|
|
106234
|
+
try {
|
|
106235
|
+
const cs = await fetchIssueComments(apiKey, issue2.id);
|
|
106236
|
+
commentsCache = cs.map((c) => ({ id: c.id, body: c.body, createdAt: c.createdAt }));
|
|
106237
|
+
} catch {
|
|
106238
|
+
commentsCache = [];
|
|
106239
|
+
}
|
|
106240
|
+
return commentsCache;
|
|
106241
|
+
};
|
|
106242
|
+
const commentBodies = confirmationUsesCommentIndicator(cfg) ? (await getComments()).filter((c) => !isRalphComment(c.body)).map((c) => c.body) : undefined;
|
|
105603
106243
|
const ticketView = {
|
|
105604
106244
|
labels: issue2.labels,
|
|
105605
106245
|
state: issue2.state,
|
|
105606
|
-
project: issue2.project
|
|
106246
|
+
project: issue2.project,
|
|
106247
|
+
...commentBodies ? { commentBodies } : {}
|
|
105607
106248
|
};
|
|
105608
106249
|
const { approved: approvalMatches, confirmationGated } = computeConfirmationFlags(cfg, ticketView);
|
|
105609
106250
|
const { stateObj, confirmation } = await readConfirmationState(statePath);
|
|
@@ -105675,16 +106316,7 @@ async function processAwaitingForIssue(issue2, deps) {
|
|
|
105675
106316
|
postComments: cfg.linear.postComments !== false && Boolean(apiKey)
|
|
105676
106317
|
}, {
|
|
105677
106318
|
approvalMatches,
|
|
105678
|
-
fetchComments:
|
|
105679
|
-
if (!apiKey)
|
|
105680
|
-
return [];
|
|
105681
|
-
try {
|
|
105682
|
-
const cs = await fetchIssueComments(apiKey, issue2.id);
|
|
105683
|
-
return cs.map((c) => ({ id: c.id, body: c.body, createdAt: c.createdAt }));
|
|
105684
|
-
} catch {
|
|
105685
|
-
return [];
|
|
105686
|
-
}
|
|
105687
|
-
},
|
|
106319
|
+
fetchComments: getComments,
|
|
105688
106320
|
...indicators.clearApproved ? { clearApproved: indicators.clearApproved } : {},
|
|
105689
106321
|
applyIndicator: (ind) => deps.applyIndicator(issue2, ind),
|
|
105690
106322
|
postComment: async (body) => {
|
|
@@ -105937,6 +106569,7 @@ var init_indicators = __esm(() => {
|
|
|
105937
106569
|
// apps/agent/src/agent/wire/linear-resolvers.ts
|
|
105938
106570
|
function createLinearResolvers(input) {
|
|
105939
106571
|
const { apiKey, team, assignee, diag } = input;
|
|
106572
|
+
const ticketNumbers = input.ticketNumbers ?? [];
|
|
105940
106573
|
const stateCache = new Map;
|
|
105941
106574
|
const labelCache = new Map;
|
|
105942
106575
|
const teamIdCache = new Map;
|
|
@@ -106048,7 +106681,13 @@ function createLinearResolvers(input) {
|
|
|
106048
106681
|
if (include.length === 0)
|
|
106049
106682
|
return [];
|
|
106050
106683
|
const hasCommentMarker = include.some((m) => m.type === "comment");
|
|
106051
|
-
const spec = {
|
|
106684
|
+
const spec = {
|
|
106685
|
+
team,
|
|
106686
|
+
assignee,
|
|
106687
|
+
include,
|
|
106688
|
+
exclude: excl,
|
|
106689
|
+
...ticketNumbers.length > 0 ? { numbers: ticketNumbers } : {}
|
|
106690
|
+
};
|
|
106052
106691
|
const fetched = await fetchOpenIssues(apiKey, spec, hasCommentMarker ? { includeComments: true } : undefined);
|
|
106053
106692
|
if (!hasCommentMarker)
|
|
106054
106693
|
return fetched;
|
|
@@ -106067,7 +106706,7 @@ function createLinearResolvers(input) {
|
|
|
106067
106706
|
resolveLabelIdForTeam
|
|
106068
106707
|
};
|
|
106069
106708
|
}
|
|
106070
|
-
async function fetchDoneCandidatesWith(apiKey, team, _assignee, indicators) {
|
|
106709
|
+
async function fetchDoneCandidatesWith(apiKey, team, _assignee, indicators, ticketNumbers) {
|
|
106071
106710
|
const getIndicators = [
|
|
106072
106711
|
indicators.getTodo,
|
|
106073
106712
|
indicators.getInProgress,
|
|
@@ -106090,7 +106729,8 @@ async function fetchDoneCandidatesWith(apiKey, team, _assignee, indicators) {
|
|
|
106090
106729
|
team,
|
|
106091
106730
|
anyAssignee: true,
|
|
106092
106731
|
include,
|
|
106093
|
-
exclude: []
|
|
106732
|
+
exclude: [],
|
|
106733
|
+
...ticketNumbers && ticketNumbers.length > 0 ? { numbers: ticketNumbers } : {}
|
|
106094
106734
|
});
|
|
106095
106735
|
for (const issue2 of issues) {
|
|
106096
106736
|
if (!seen.has(issue2.id)) {
|
|
@@ -106579,7 +107219,7 @@ async function fetchPrReviewState(prUrl, cmdRunner, projectRoot, onLog) {
|
|
|
106579
107219
|
reviewRequests(first:5){nodes{requestedReviewer{... on User{login}}}}
|
|
106580
107220
|
latestReviews(first:5){nodes{author{login} state submittedAt}}
|
|
106581
107221
|
reviewThreads(first:50){nodes{
|
|
106582
|
-
isResolved path line
|
|
107222
|
+
isResolved subjectType path line
|
|
106583
107223
|
comments(first:20){nodes{body author{login} createdAt url}}
|
|
106584
107224
|
}}
|
|
106585
107225
|
}
|
|
@@ -106612,6 +107252,7 @@ async function fetchPrReviewState(prUrl, cmdRunner, projectRoot, onLog) {
|
|
|
106612
107252
|
approved: pr2.reviewDecision === "APPROVED",
|
|
106613
107253
|
threads: (pr2.reviewThreads?.nodes ?? []).map((t) => ({
|
|
106614
107254
|
isResolved: t.isResolved,
|
|
107255
|
+
isFileLevel: t.subjectType === "FILE",
|
|
106615
107256
|
...t.path ? { path: t.path } : {},
|
|
106616
107257
|
...t.line != null ? { line: t.line } : {},
|
|
106617
107258
|
comments: t.comments.nodes.map((c) => ({
|
|
@@ -106678,7 +107319,7 @@ async function scanCodeReview(issue2, prUrl, lastRalphPickup, deps) {
|
|
|
106678
107319
|
const effectiveLastHandled = lastRalphPickup && lastHandled ? lastRalphPickup > lastHandled ? lastRalphPickup : lastHandled : lastRalphPickup ?? lastHandled;
|
|
106679
107320
|
if (!effectiveLastHandled || newestReviewerActivity > effectiveLastHandled) {
|
|
106680
107321
|
const body = unresolved.map((t) => {
|
|
106681
|
-
const head3 = t.path ? `_${t.path}${t.line ? `:${t.line}` : ""}_` : "_(general)_";
|
|
107322
|
+
const head3 = t.path ? t.isFileLevel ? `_${t.path} (whole file)_` : `_${t.path}${t.line ? `:${t.line}` : ""}_` : "_(general)_";
|
|
106682
107323
|
const lines = t.comments.map((c) => `> **${c.author ?? "reviewer"}** (${c.createdAt})
|
|
106683
107324
|
>
|
|
106684
107325
|
> ${c.body.trim().replace(/\n/g, `
|
|
@@ -106783,6 +107424,7 @@ function createMentionScanner(input) {
|
|
|
106783
107424
|
onLog,
|
|
106784
107425
|
diag,
|
|
106785
107426
|
cwdByChange,
|
|
107427
|
+
ticketNumbers,
|
|
106786
107428
|
stalePingedAt,
|
|
106787
107429
|
lastHandledReviewActivity,
|
|
106788
107430
|
resolvePrUrlForIssue
|
|
@@ -106798,6 +107440,7 @@ function createMentionScanner(input) {
|
|
|
106798
107440
|
candidates = await fetchMentionScanIssues(apiKey, {
|
|
106799
107441
|
team,
|
|
106800
107442
|
assignee,
|
|
107443
|
+
...ticketNumbers && ticketNumbers.length > 0 ? { numbers: ticketNumbers } : {},
|
|
106801
107444
|
indicators: {
|
|
106802
107445
|
...indicators.getTodo !== undefined ? { getTodo: indicators.getTodo } : {},
|
|
106803
107446
|
...indicators.getInProgress !== undefined ? { getInProgress: indicators.getInProgress } : {},
|
|
@@ -239276,9 +239919,9 @@ class $50c7aac9316f2948$export$2e2bcd8739ae039 {
|
|
|
239276
239919
|
|
|
239277
239920
|
class $55f71433a605c87d$export$2e2bcd8739ae039 {
|
|
239278
239921
|
process(glyphs, features = {}) {
|
|
239279
|
-
for (let
|
|
239280
|
-
let flags =
|
|
239281
|
-
for (let feature of
|
|
239922
|
+
for (let chain of this.morx.chains) {
|
|
239923
|
+
let flags = chain.defaultFlags;
|
|
239924
|
+
for (let feature of chain.features) {
|
|
239282
239925
|
let f2;
|
|
239283
239926
|
if (f2 = features[feature.featureType]) {
|
|
239284
239927
|
if (f2[feature.featureSetting]) {
|
|
@@ -239290,7 +239933,7 @@ class $55f71433a605c87d$export$2e2bcd8739ae039 {
|
|
|
239290
239933
|
}
|
|
239291
239934
|
}
|
|
239292
239935
|
}
|
|
239293
|
-
for (let subtable of
|
|
239936
|
+
for (let subtable of chain.subtables)
|
|
239294
239937
|
if (subtable.subFeatureFlags & flags)
|
|
239295
239938
|
this.processSubtable(subtable, glyphs);
|
|
239296
239939
|
}
|
|
@@ -239437,8 +240080,8 @@ class $55f71433a605c87d$export$2e2bcd8739ae039 {
|
|
|
239437
240080
|
}
|
|
239438
240081
|
getSupportedFeatures() {
|
|
239439
240082
|
let features = [];
|
|
239440
|
-
for (let
|
|
239441
|
-
for (let feature of
|
|
240083
|
+
for (let chain of this.morx.chains)
|
|
240084
|
+
for (let feature of chain.features)
|
|
239442
240085
|
features.push([
|
|
239443
240086
|
feature.featureType,
|
|
239444
240087
|
feature.featureSetting
|
|
@@ -239452,9 +240095,9 @@ class $55f71433a605c87d$export$2e2bcd8739ae039 {
|
|
|
239452
240095
|
}
|
|
239453
240096
|
generateInputCache() {
|
|
239454
240097
|
this.inputCache = {};
|
|
239455
|
-
for (let
|
|
239456
|
-
let flags =
|
|
239457
|
-
for (let subtable of
|
|
240098
|
+
for (let chain of this.morx.chains) {
|
|
240099
|
+
let flags = chain.defaultFlags;
|
|
240100
|
+
for (let subtable of chain.subtables)
|
|
239458
240101
|
if (subtable.subFeatureFlags & flags)
|
|
239459
240102
|
this.generateInputsForSubtable(subtable);
|
|
239460
240103
|
}
|
|
@@ -260537,6 +261180,7 @@ function buildAgentCoordinator(input) {
|
|
|
260537
261180
|
const indicators = mergeIndicators(cfg.linear.indicators, args.indicators);
|
|
260538
261181
|
const team = args.linearTeam || cfg.linear.team;
|
|
260539
261182
|
const assignee = args.linearAssignee || cfg.linear.assignee;
|
|
261183
|
+
const ticketNumbers = resolveTicketNumbers(args.ticketTokens, team);
|
|
260540
261184
|
const excludeFromTodo = unionMarkers(indicators.setDone, indicators.setError);
|
|
260541
261185
|
const gitRunner = input.runners?.git ?? bunGitRunner;
|
|
260542
261186
|
const cmdRunner = input.runners?.cmd ?? bunCmdRunner;
|
|
@@ -260568,7 +261212,19 @@ function buildAgentCoordinator(input) {
|
|
|
260568
261212
|
}
|
|
260569
261213
|
return code;
|
|
260570
261214
|
});
|
|
260571
|
-
const resolvers = createLinearResolvers({
|
|
261215
|
+
const resolvers = createLinearResolvers({
|
|
261216
|
+
apiKey,
|
|
261217
|
+
team,
|
|
261218
|
+
assignee,
|
|
261219
|
+
diag,
|
|
261220
|
+
...ticketNumbers.length > 0 ? { ticketNumbers } : {}
|
|
261221
|
+
});
|
|
261222
|
+
if (ticketNumbers.length > 0) {
|
|
261223
|
+
const hasGetIndicator = [indicators.getTodo, indicators.getInProgress].some((ind) => ind && ind.filter.length > 0);
|
|
261224
|
+
if (!hasGetIndicator) {
|
|
261225
|
+
diag("ticket", `! --ticket set (${ticketNumbers.join(", ")}) but no getTodo/getInProgress indicator is configured \u2014 nothing will be picked up`, "yellow");
|
|
261226
|
+
}
|
|
261227
|
+
}
|
|
260572
261228
|
const prDiscovery = createPrDiscovery({
|
|
260573
261229
|
apiKey,
|
|
260574
261230
|
projectRoot,
|
|
@@ -260604,6 +261260,7 @@ function buildAgentCoordinator(input) {
|
|
|
260604
261260
|
onLog,
|
|
260605
261261
|
diag,
|
|
260606
261262
|
cwdByChange,
|
|
261263
|
+
...ticketNumbers.length > 0 ? { ticketNumbers } : {},
|
|
260607
261264
|
stalePingedAt,
|
|
260608
261265
|
lastHandledReviewActivity,
|
|
260609
261266
|
resolvePrUrlForIssue: prDiscovery.resolvePrUrlForIssue
|
|
@@ -260700,7 +261357,7 @@ function buildAgentCoordinator(input) {
|
|
|
260700
261357
|
fetchTodo: () => resolvers.fetchByGet(indicators.getTodo, excludeFromTodo),
|
|
260701
261358
|
fetchInProgress: () => resolvers.fetchByGet(indicators.getInProgress, unionMarkers(indicators.setError)),
|
|
260702
261359
|
fetchMentions,
|
|
260703
|
-
fetchDoneCandidates: () => fetchDoneCandidatesWith(apiKey, team, assignee, indicators),
|
|
261360
|
+
fetchDoneCandidates: () => fetchDoneCandidatesWith(apiKey, team, assignee, indicators, ticketNumbers.length > 0 ? ticketNumbers : undefined),
|
|
260704
261361
|
prepare: prep.prepare,
|
|
260705
261362
|
prepareTaskForTrigger: prep.prepareTaskForTrigger,
|
|
260706
261363
|
spawnWorker,
|
|
@@ -260786,6 +261443,7 @@ var init_wire = __esm(() => {
|
|
|
260786
261443
|
init_indicators();
|
|
260787
261444
|
init_task_bodies();
|
|
260788
261445
|
init_linear_resolvers();
|
|
261446
|
+
init_linear_client();
|
|
260789
261447
|
init_prepare();
|
|
260790
261448
|
init_pr_discovery();
|
|
260791
261449
|
init_mention_scan();
|
|
@@ -260801,7 +261459,7 @@ import { dirname as dirname15 } from "path";
|
|
|
260801
261459
|
function createJsonLogFileSink(path) {
|
|
260802
261460
|
if (!path)
|
|
260803
261461
|
return { emit: () => {} };
|
|
260804
|
-
let
|
|
261462
|
+
let chain = (async () => {
|
|
260805
261463
|
try {
|
|
260806
261464
|
await mkdir12(dirname15(path), { recursive: true });
|
|
260807
261465
|
await Bun.write(path, "");
|
|
@@ -260811,7 +261469,7 @@ function createJsonLogFileSink(path) {
|
|
|
260811
261469
|
emit(event) {
|
|
260812
261470
|
const line = JSON.stringify({ ts: Date.now(), v: VERSION, ...event }) + `
|
|
260813
261471
|
`;
|
|
260814
|
-
|
|
261472
|
+
chain = chain.then(async () => {
|
|
260815
261473
|
try {
|
|
260816
261474
|
await appendFile2(path, line);
|
|
260817
261475
|
} catch {}
|
|
@@ -262919,6 +263577,18 @@ var init_tmux = __esm(() => {
|
|
|
262919
263577
|
decoder = new TextDecoder;
|
|
262920
263578
|
});
|
|
262921
263579
|
|
|
263580
|
+
// apps/agent/src/sort/compare.ts
|
|
263581
|
+
function chain(...comparators) {
|
|
263582
|
+
return (a, b2) => {
|
|
263583
|
+
for (const c of comparators) {
|
|
263584
|
+
const r = c(a, b2);
|
|
263585
|
+
if (r !== 0)
|
|
263586
|
+
return r;
|
|
263587
|
+
}
|
|
263588
|
+
return 0;
|
|
263589
|
+
};
|
|
263590
|
+
}
|
|
263591
|
+
|
|
262922
263592
|
// apps/agent/src/list-sort.ts
|
|
262923
263593
|
function assignTier(status) {
|
|
262924
263594
|
if (status === null || status.kind === "error")
|
|
@@ -262941,7 +263611,7 @@ function createdAtOf(status) {
|
|
|
262941
263611
|
return "";
|
|
262942
263612
|
}
|
|
262943
263613
|
function sortRows(rows) {
|
|
262944
|
-
const cmp = chain((a, b2) => assignTier(a.status) - assignTier(b2.status), (a, b2) => {
|
|
263614
|
+
const cmp = chain((a, b2) => assignTier(a.status) - assignTier(b2.status), (a, b2) => a.bucketOrder - b2.bucketOrder, (a, b2) => {
|
|
262945
263615
|
const ia = a.issueCreatedAt;
|
|
262946
263616
|
const ib = b2.issueCreatedAt;
|
|
262947
263617
|
if (ia === ib)
|
|
@@ -262957,7 +263627,7 @@ function sortRows(rows) {
|
|
|
262957
263627
|
if (ca === cb)
|
|
262958
263628
|
return 0;
|
|
262959
263629
|
return ca < cb ? -1 : 1;
|
|
262960
|
-
}, (a, b2) => a.
|
|
263630
|
+
}, (a, b2) => a.identifier.localeCompare(b2.identifier));
|
|
262961
263631
|
return [...rows].sort(cmp);
|
|
262962
263632
|
}
|
|
262963
263633
|
var init_list_sort = () => {};
|
|
@@ -263006,7 +263676,8 @@ __export(exports_list, {
|
|
|
263006
263676
|
formatReviewCell: () => formatReviewCell,
|
|
263007
263677
|
formatPrStatusMarker: () => formatPrStatusMarker,
|
|
263008
263678
|
formatBlockedCell: () => formatBlockedCell,
|
|
263009
|
-
buildBuckets: () => buildBuckets
|
|
263679
|
+
buildBuckets: () => buildBuckets,
|
|
263680
|
+
backlogRankByIssueId: () => backlogRankByIssueId
|
|
263010
263681
|
});
|
|
263011
263682
|
import { join as join36 } from "path";
|
|
263012
263683
|
function countTaskItems(content) {
|
|
@@ -263108,14 +263779,15 @@ function buildBuckets(indicators) {
|
|
|
263108
263779
|
{ label: "auto-merge", indicator: indicators.getAutoMerge, exclude: [] }
|
|
263109
263780
|
];
|
|
263110
263781
|
}
|
|
263111
|
-
async function fetchBucketIssues(apiKey, bucket, team, assignee) {
|
|
263782
|
+
async function fetchBucketIssues(apiKey, bucket, team, assignee, ticketNumbers) {
|
|
263112
263783
|
if (!bucket.indicator || bucket.indicator.filter.length === 0)
|
|
263113
263784
|
return [];
|
|
263114
263785
|
const spec = {
|
|
263115
263786
|
team,
|
|
263116
263787
|
assignee,
|
|
263117
263788
|
include: bucket.indicator.filter,
|
|
263118
|
-
exclude: bucket.exclude
|
|
263789
|
+
exclude: bucket.exclude,
|
|
263790
|
+
...ticketNumbers.length > 0 ? { numbers: ticketNumbers } : {}
|
|
263119
263791
|
};
|
|
263120
263792
|
return fetchOpenIssues(apiKey, spec);
|
|
263121
263793
|
}
|
|
@@ -263159,13 +263831,19 @@ function formatPrStatusMarker(status, failedCheckNames) {
|
|
|
263159
263831
|
return "ok";
|
|
263160
263832
|
return parts.join(" ");
|
|
263161
263833
|
}
|
|
263162
|
-
|
|
263834
|
+
function backlogRankByIssueId(issues) {
|
|
263835
|
+
const ordered = orderIssuesHierarchically(issues.map((issue2) => linearIssueToOrderable(issue2)));
|
|
263836
|
+
const rankById = new Map;
|
|
263837
|
+
ordered.forEach((o, i) => rankById.set(o.id, i));
|
|
263838
|
+
return rankById;
|
|
263839
|
+
}
|
|
263840
|
+
async function fetchAndPrintLinear(apiKey, buckets, team, assignee, cwd2, runner, ignoreCiChecks = [], checks3 = false, review = false, ticketNumbers = []) {
|
|
263163
263841
|
const bucketResults = await Promise.all(buckets.map(async (bucket) => {
|
|
263164
263842
|
if (!bucket.indicator || bucket.indicator.filter.length === 0) {
|
|
263165
263843
|
return { bucket, issues: [], error: null };
|
|
263166
263844
|
}
|
|
263167
263845
|
try {
|
|
263168
|
-
const issues = await fetchBucketIssues(apiKey, bucket, team, assignee);
|
|
263846
|
+
const issues = await fetchBucketIssues(apiKey, bucket, team, assignee, ticketNumbers);
|
|
263169
263847
|
return { bucket, issues, error: null };
|
|
263170
263848
|
} catch (err) {
|
|
263171
263849
|
return {
|
|
@@ -263183,16 +263861,17 @@ ${bucket.label}: error fetching from Linear \u2014 ${error48}
|
|
|
263183
263861
|
}
|
|
263184
263862
|
}
|
|
263185
263863
|
const seen = new Map;
|
|
263186
|
-
|
|
263864
|
+
const issueById = new Map;
|
|
263187
263865
|
for (const { bucket, issues } of bucketResults) {
|
|
263188
263866
|
for (const issue2 of issues) {
|
|
263189
263867
|
if (seen.has(issue2.id))
|
|
263190
263868
|
continue;
|
|
263869
|
+
issueById.set(issue2.id, issue2);
|
|
263191
263870
|
seen.set(issue2.id, {
|
|
263192
263871
|
issueId: issue2.id,
|
|
263193
263872
|
identifier: issue2.identifier,
|
|
263194
263873
|
status: null,
|
|
263195
|
-
bucketOrder:
|
|
263874
|
+
bucketOrder: 0,
|
|
263196
263875
|
issueCreatedAt: issue2.createdAt,
|
|
263197
263876
|
bucketLabel: bucket.label,
|
|
263198
263877
|
stateName: issue2.state.name,
|
|
@@ -263203,6 +263882,9 @@ ${bucket.label}: error fetching from Linear \u2014 ${error48}
|
|
|
263203
263882
|
}
|
|
263204
263883
|
}
|
|
263205
263884
|
const rows = [...seen.values()];
|
|
263885
|
+
const rankById = backlogRankByIssueId([...issueById.values()]);
|
|
263886
|
+
for (const row of rows)
|
|
263887
|
+
row.bucketOrder = rankById.get(row.issueId) ?? 0;
|
|
263206
263888
|
try {
|
|
263207
263889
|
const attachmentsByIssue = await fetchAttachmentsForIssues(apiKey, rows.map((r) => r.issueId));
|
|
263208
263890
|
for (const row of rows) {
|
|
@@ -263319,6 +264001,15 @@ Linear: LINEAR_API_KEY not set \u2014 cannot fetch tickets. Configured buckets:
|
|
|
263319
264001
|
}
|
|
263320
264002
|
return;
|
|
263321
264003
|
}
|
|
264004
|
+
let ticketNumbers = [];
|
|
264005
|
+
try {
|
|
264006
|
+
ticketNumbers = resolveTicketNumbers(input.ticketTokens ?? [], team);
|
|
264007
|
+
} catch (err) {
|
|
264008
|
+
process.stderr.write(`Error: ${formatTicketError(err)}
|
|
264009
|
+
`);
|
|
264010
|
+
process.exitCode = 1;
|
|
264011
|
+
return;
|
|
264012
|
+
}
|
|
263322
264013
|
if (team)
|
|
263323
264014
|
process.stdout.write(`
|
|
263324
264015
|
team: ${team}
|
|
@@ -263326,13 +264017,21 @@ team: ${team}
|
|
|
263326
264017
|
if (assignee)
|
|
263327
264018
|
process.stdout.write(`assignee: ${assignee}
|
|
263328
264019
|
`);
|
|
263329
|
-
|
|
264020
|
+
if (ticketNumbers.length > 0)
|
|
264021
|
+
process.stdout.write(`ticket: ${ticketNumbers.join(", ")}
|
|
264022
|
+
`);
|
|
264023
|
+
await fetchAndPrintLinear(apiKey, buckets, team, assignee, projectRoot, localCmdRunner, cfg.ignoreCiChecks, input.checks, input.review, ticketNumbers);
|
|
263330
264024
|
}
|
|
263331
264025
|
function normalizeIdentifier(input) {
|
|
263332
|
-
|
|
263333
|
-
|
|
264026
|
+
let parsed;
|
|
264027
|
+
try {
|
|
264028
|
+
parsed = parseTicketIdentifier(input);
|
|
264029
|
+
} catch {
|
|
263334
264030
|
return null;
|
|
263335
|
-
|
|
264031
|
+
}
|
|
264032
|
+
if (parsed.teamKey === null)
|
|
264033
|
+
return null;
|
|
264034
|
+
return `${parsed.teamKey}-${parsed.number}`;
|
|
263336
264035
|
}
|
|
263337
264036
|
async function fetchIssueByIdentifier(apiKey, identifier) {
|
|
263338
264037
|
const match = identifier.match(/^([A-Z]+)-(\d+)$/);
|
|
@@ -263482,6 +264181,8 @@ var init_list = __esm(() => {
|
|
|
263482
264181
|
init_pr_status();
|
|
263483
264182
|
init_pr_url();
|
|
263484
264183
|
init_list_sort();
|
|
264184
|
+
init_ordering();
|
|
264185
|
+
init_queue_order();
|
|
263485
264186
|
init_ci();
|
|
263486
264187
|
init_linear_client();
|
|
263487
264188
|
init_indicators();
|
|
@@ -263791,7 +264492,8 @@ async function main3(argv) {
|
|
|
263791
264492
|
debug: args.debug,
|
|
263792
264493
|
name: args.name,
|
|
263793
264494
|
checks: args.checks,
|
|
263794
|
-
review: args.review
|
|
264495
|
+
review: args.review,
|
|
264496
|
+
ticketTokens: args.ticketTokens
|
|
263795
264497
|
});
|
|
263796
264498
|
});
|
|
263797
264499
|
return typeof process.exitCode === "number" ? process.exitCode : 0;
|
|
@@ -263811,6 +264513,19 @@ async function main3(argv) {
|
|
|
263811
264513
|
`);
|
|
263812
264514
|
return 0;
|
|
263813
264515
|
}
|
|
264516
|
+
if (args.ticketTokens.length > 0) {
|
|
264517
|
+
const { loadRalphyConfig: loadRalphyConfig2 } = await Promise.resolve().then(() => (init_config(), exports_config));
|
|
264518
|
+
const { resolveTicketNumbers: resolveTicketNumbers2, formatTicketError: formatTicketError2 } = await Promise.resolve().then(() => (init_linear_client(), exports_linear_client));
|
|
264519
|
+
const cfg = await loadRalphyConfig2(projectRoot);
|
|
264520
|
+
const team = args.linearTeam || cfg.linear.team;
|
|
264521
|
+
try {
|
|
264522
|
+
resolveTicketNumbers2(args.ticketTokens, team);
|
|
264523
|
+
} catch (err) {
|
|
264524
|
+
process.stderr.write(formatTicketError2(err) + `
|
|
264525
|
+
`);
|
|
264526
|
+
return 1;
|
|
264527
|
+
}
|
|
264528
|
+
}
|
|
263814
264529
|
await mkdir15(statesDir, { recursive: true });
|
|
263815
264530
|
await mkdir15(tasksDir, { recursive: true });
|
|
263816
264531
|
await mkdir15(join39(projectRoot, ".ralph"), { recursive: true });
|